Authored by 于良

浏览记录 review by 草莓

... ... @@ -11,18 +11,47 @@ import ReactNative, {
TouchableOpacity,
} from 'react-native';
import LoadingIndicator from '../../../common/components/LoadingIndicator';
import ProductCell from './ProductCell';
export default class Browse extends Component {
constructor(props) {
super(props);
this._renderRow = this._renderRow.bind(this);
this.dataSource = new ListView.DataSource({
rowHasChanged: (r1, r2) => !Immutable.is(r1, r2),
});
}
_renderRow(rowData, sectionID, rowID) {
return (
<ProductCell
data={rowData}
/>
);
}
render() {
let {isFetching, productList, categoryList} = this.props.data;
let isLoading = productList.size == 0 && isFetching;
return (
<View style={styles.container}>
<ListView
enableEmptySections={true}
dataSource={this.dataSource.cloneWithRows(productList.toArray())}
renderRow={this._renderRow}
/>
<LoadingIndicator
isVisible={isLoading}
/>
</View>
);
}
... ...
'use strict';
import React, {Component} from 'react';
import ReactNative, {
View,
Text,
Image,
ListView,
TouchableOpacity,
StyleSheet,
Dimensions,
} from 'react-native';
import Immutable, {Map, List} from 'immutable';
import YH_Image from '../../../common/components/YH_Image';
import DeleteLineText from '../../../common/components/DeleteLineText';
export default class ProductCell extends Component{
constructor(props) {
super(props);
}
render() {
let data = this.props.data;
let prdImage = YH_Image.getSlicedUrl(data.get('image', ''), 113, 150, 2);
let salePrice = 0; // 售卖价
let originPrice = 0; // 原价
let salePriceStr = ''; // 拼接的售卖价
let originPriceStr = ''; // 拼接的原价
let showOriginPrice = true; // 是否显示原价
let salePriceColor = '#d0021b'; // 不显示原价时,售卖价颜色
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';
}
return (
<View style={styles.container}>
<YH_Image style={styles.prdImage} url={prdImage} />
<View style={styles.leftContainer}>
<Text>{data.get('product_name', '')}</Text>
<View style={styles.priceContainer}>
<Text style={[styles.nowPrice, {color: salePriceColor}]} numberOfLines={1}>{salePriceStr}</Text>
{showOriginPrice ? <DeleteLineText
style={styles.oldPriceContainer}
textStyle={styles.oldPrice}
lineStyle={styles.deleteLine}
text={originPriceStr}
/> : null}
</View>
</View>
</View>
);
}
};
let {width} = Dimensions.get('window');
const DEVICE_WIDTH_RATIO = width / 320;
let imageWidth = Math.floor(width / 2);
let imageHeight = Math.floor(imageWidth * 180 / 375);
let topRightWidth = Math.ceil(80 * DEVICE_WIDTH_RATIO);
let topLeftWidth = width - Math.ceil(84 * DEVICE_WIDTH_RATIO);
let styles = StyleSheet.create({
container: {
flexDirection: 'column',
width: width,
backgroundColor: 'white',
},
prdImage: {
width: 113,
height: 150,
},
priceContainer: {
flexDirection: 'row',
justifyContent: 'center',
marginTop: 10,
},
nowPrice: {
fontSize: 10,
color: '#d0021b',
},
oldPriceContainer: {
flexDirection: 'row',
marginLeft: 5,
},
oldPrice: {
fontSize: 10,
color: '#b0b0b0',
height: 16,
},
deleteLine: {
position: 'absolute',
top: (16 / 2) - 2,
left: 0,
right: 0,
height: 1,
backgroundColor: '#b0b0b0',
},
});
... ...
... ... @@ -25,4 +25,8 @@ export default keyMirror({
CANCEL_FAVORITE_SUCCESS: null,
CANCEL_FAVORITE_FAILURE: null,
//browse
HISTORY_LIST_REQUEST: null,
HISTORY_LIST_SUCCESS: null,
HISTORY_LIST_FAILURE: null,
});
... ...
... ... @@ -51,7 +51,7 @@ class BrowseContainer extends Component {
}
componentDidMount() {
this.props.actions.historyList();
}
componentWillUnmount() {
... ... @@ -59,13 +59,10 @@ class BrowseContainer extends Component {
}
render() {
let {
} = this.props.browse;
return (
<Browse
data={this.props.browse}
/>
);
}
... ...
... ... @@ -58,14 +58,11 @@ export function brandListFailure(error) {
};
}
/*
* reload bool 是否需要强制重新请求数据,
*/
export function brandList() {
return (dispatch, getState) => {
let {app, brand} = getState();
if (brand.isFetching || brand.endReached || brand.error) {
if (brand.isFetching || brand.endReached) {
return;
}
... ...
... ... @@ -4,10 +4,84 @@ import ReactNative from 'react-native';
import BrowseService from '../../services/BrowseService';
import Immutable, {Map} from 'immutable';
const {
SET_TYPE,
HISTORY_LIST_REQUEST,
HISTORY_LIST_SUCCESS,
HISTORY_LIST_FAILURE,
} = require('../../constants/actionTypes').default;
export function historyListRequest() {
return {
type: HISTORY_LIST_REQUEST,
};
}
export function historyListSuccess(json) {
return {
type: HISTORY_LIST_SUCCESS,
payload: json
};
}
export function historyListFailure(error) {
return {
type: HISTORY_LIST_FAILURE,
payload: error
};
}
export function historyList() {
return (dispatch, getState) => {
let {app, browse} = getState();
if (browse.isFetching) {
return;
}
let fetchList = (uid, page, pageSize, sourcePage) => {
dispatch(historyListRequest());
return new BrowseService(app.host).fetchList(uid, page, pageSize, sourcePage)
.then(json => {
let payload = parseHistoryList(json);
dispatch(historyListSuccess(payload));
})
.catch(error => {
dispatch(historyListFailure(error));
});
}
let uid = 0;
let sourcePage = '';
let page = browse.currentPage + 1;
let pageSize = browse.pageSize;
Promise.all([
ReactNative.NativeModules.YH_CommonHelper.sourcePage('YH_MineBrowseHistoryVC'),
]).then(result => {
sourcePage = result[0];
return ReactNative.NativeModules.YH_CommonHelper.uid();
}).then(data => {
uid = data;
fetchList(uid, page, pageSize, sourcePage);
})
.catch(error => {
fetchList(uid, page, pageSize, sourcePage);
});
};
}
function parseHistoryList(json) {
let currentPage = json && json.page ? json.page : 1;
let productList = json && json.product_list ? json.product_list : [];
let categoryList = json && json.category_list ? json.category_list : [];
return {
categoryList,
productList,
currentPage,
};
}
\ No newline at end of file
... ...
... ... @@ -4,7 +4,11 @@ import {Record, List, Map} from 'immutable';
let InitialState = Record({
isFetching: false,
error: null,
categoryList: List(),
productList: List(),
currentPage: 0,
pageSize: 100,
});
export default InitialState;
... ...
... ... @@ -4,8 +4,9 @@ import InitialState from './browseInitialState';
import Immutable, {Map} from 'immutable';
const {
SET_TYPE,
HISTORY_LIST_REQUEST,
HISTORY_LIST_SUCCESS,
HISTORY_LIST_FAILURE,
} = require('../../constants/actionTypes').default;
... ... @@ -13,8 +14,31 @@ const initialState = new InitialState;
export default function browseReducer(state=initialState, action) {
switch(action.type) {
case HISTORY_LIST_REQUEST: {
return state.set('isFetching', true)
.set('error', null);
}
case HISTORY_LIST_SUCCESS: {
let {
categoryList,
productList,
currentPage,
} = action.payload;
let newState = state.set('isFetching', false)
.set('error', null)
.set('categoryList', Immutable.fromJS(categoryList))
.set('productList', Immutable.fromJS(productList))
.set('currentPage', currentPage);
return newState;
}
case HISTORY_LIST_FAILURE: {
return state.set('isFetching', false)
.set('error', action.payload);
}
}
return state;
... ...
... ... @@ -40,7 +40,6 @@ export default class BrandService {
id,
uid,
type,
fromPage: 'iFP_MineCollectionBrand',
v,
}
})
... ...
... ... @@ -11,12 +11,15 @@ export default class CategoryService {
}
this.api = new Request(baseURL);
}
async getCategoryList(yh_channel, fromPage='aFP_Category'){
async fetchList(uid=0, page=1, limit=100, fromPage='') {
return await this.api.get({
url: '',
body: {
method: 'app.sort.get',
yh_channel,
method: 'app.browse.product',
uid,
page,
limit,
fromPage,
}
})
... ... @@ -27,6 +30,5 @@ export default class CategoryService {
throw(error);
});
}
}
... ...