Authored by lixia.zhang

浏览记录分页功能

... ... @@ -12,6 +12,7 @@ import ReactNative, {
} from 'react-native';
import LoadingIndicator from '../../../common/components/LoadingIndicator';
import LoadMoreIndicator from '../../../common/components/LoadMoreIndicator';
import ProductCell from './ProductCell';
import CategorySelector from './CategorySelector';
import NoDataView from '../product/NoDataView'
... ... @@ -89,7 +90,7 @@ export default class Browse extends Component {
renderSectionHeader() {
let {isFetching, selectedProductList, categoryList, selectedCategoryIndex} = this.props.data;
let {isFetching, categoryList, selectedCategoryIndex} = this.props.data;
return (
<CategorySelector
data={categoryList}
... ... @@ -104,10 +105,11 @@ export default class Browse extends Component {
render() {
let {isFetching, productList, selectedProductList, categoryList, selectedCategoryIndex, isDeleting, showEmpty} = this.props.data;
let {isFetching, productList, categoryList, selectedCategoryIndex, isDeleting, showEmpty, currentPage, page_total} = this.props.data;
let isLoading = (selectedProductList.size == 0 && isFetching) || isDeleting;
let isLoading = (productList.size == 0 && isFetching) || isDeleting;
let showList = !isFetching && productList.size > 0;
let isLoadingMore = isFetching && currentPage > 0;
return (
<View style={styles.container}>
{showList ? <SwipeListView
... ... @@ -116,7 +118,7 @@ export default class Browse extends Component {
enableEmptySections={true}
disableRightSwipe={true}
yh_viewVisible = {true}
sections={[{data:selectedProductList.toArray(),key:'browse'}]}
sections={[{data:productList.toArray(),key:'browse'}]}
renderItem={this.renderItem}
renderSectionHeader={this.renderSectionHeader}
renderHiddenRow={ (data, rowMap) => (
... ... @@ -131,6 +133,18 @@ export default class Browse extends Component {
)}
rightOpenValue={-70}
categoryId={selectedCategoryIndex}
ListFooterComponent={()=>{
if (page_total == currentPage) {
return <View style={styles.placeholder} />;
} else {
return <LoadMoreIndicator isVisible={isLoadingMore} animating={true}/>;
}
}}
onEndReached={() => {
if (productList && productList.size > 0 && currentPage < page_total) {
this.props.onEndReached && this.props.onEndReached();
}
}}
/> : null}
{showEmpty ? <NoDataView type={'browse'} onPressGuangGuang={this.props.onPressGuangGuang}/> : null}
... ...
... ... @@ -12,6 +12,7 @@ import ReactNative, {
} from 'react-native';
import LoadingIndicator from '../../../common/components/LoadingIndicator';
import LoadMoreIndicator from '../../../common/components/LoadMoreIndicator';
import ProductCell from './ProductCell';
import CategorySelector from './CategorySelector';
import Swipeable from 'react-native-swipeable';
... ... @@ -115,7 +116,7 @@ export default class Browse extends Component {
}
renderSectionHeader() {
let {isFetching, selectedProductList, categoryList, selectedCategoryIndex} = this.props.data;
let {isFetching, categoryList, selectedCategoryIndex} = this.props.data;
return (
<CategorySelector
data={categoryList}
... ... @@ -130,9 +131,10 @@ export default class Browse extends Component {
render() {
let {isFetching, productList, selectedProductList, categoryList, selectedCategoryIndex, isDeleting, showEmpty} = this.props.data;
let {isFetching, productList, categoryList, selectedCategoryIndex, isDeleting, showEmpty, currentPage, page_total} = this.props.data;
let isLoading = (selectedProductList.size == 0 && isFetching) || isDeleting;
let isLoading = (productList.size == 0 && isFetching) || isDeleting;
let isLoadingMore = isFetching && currentPage > 0;
let showList = !isFetching && productList.size > 0;
return (
<View style={styles.container}>
... ... @@ -143,10 +145,22 @@ export default class Browse extends Component {
scrollEnabled={!this.state.isSwiping}
enableEmptySections={true}
yh_viewVisible = {true}
dataSource={this.dataSource.cloneWithRows(selectedProductList.toArray())}
dataSource={this.dataSource.cloneWithRows(productList.toArray())}
renderRow={this.renderRow}
renderSectionHeader={this.renderSectionHeader}
onScroll={this.handleScroll}
onScroll={this.handleScroll}renderFooter={()=>{
if (page_total == currentPage) {
return <View style={styles.placeholder} />;
} else {
return <LoadMoreIndicator isVisible={isLoadingMore} animating={true}/>;
}
}}
onEndReached={() => {
if (productList && productList.size > 0 && currentPage < page_total) {
this.props.onEndReached && this.props.onEndReached();
}
}}
/> : null}
{showEmpty ? <NoDataView type={'browse'} onPressGuangGuang={this.props.onPressGuangGuang}/> : null}
... ...
... ... @@ -24,6 +24,7 @@ class SwipeListView extends Component {
this.state = {
scrollState: true,
}
this.getItemLayout = this.getItemLayout.bind(this);
}
... ... @@ -52,6 +53,12 @@ class SwipeListView extends Component {
}
}
getItemLayout(data, index) {
let {fliter,shopsdecorator} = this.props;
return {length: data.length, offset: 122 * index + 45, index};//cell高度122, 顶部偏移45
}
onRowOpen(rowId, rowMap) {
const cellIdentifier = `${rowId}`;
if (this.openCellId && this.openCellId !== cellIdentifier) {
... ... @@ -146,6 +153,7 @@ class SwipeListView extends Component {
yh_viewVisible = {true}
ref={ c => this.setRefs(c) }
renderItem={(item) => this.renderItem(item, this._rows)}
getItemLayout={this.getItemLayout}
onScroll={ e => this.onScroll(e) }
/>
)
... ...
... ... @@ -31,6 +31,10 @@ export default keyMirror({
HISTORY_LIST_SUCCESS: null,
HISTORY_LIST_FAILURE: null,
HISTORY_SORT_LIST_REQUEST: null,
HISTORY_SORT_LIST_SUCCESS: null,
HISTORY_SORT_LIST_FAILURE: null,
SET_SELECTED_CATEGORY: null,
HISTORY_DELETE_REQUEST: null,
... ...
... ... @@ -53,11 +53,12 @@ class BrowseContainer extends Component {
this.onPressFindSimilar = this.onPressFindSimilar.bind(this);
this.onPressDelete = this.onPressDelete.bind(this);
this.onPressGuangGuang = this.onPressGuangGuang.bind(this);
this.onEndReached = this.onEndReached.bind(this);
this.subscription = NativeAppEventEmitter.addListener(
'ClearHistoryEvent',
(reminder) => {
let selectedProducts = this.props.browse.selectedProductList;
let selectedProducts = this.props.browse.productList;
selectedProducts = selectedProducts&&selectedProducts.toJS();
if (selectedProducts.length) {
... ... @@ -73,7 +74,8 @@ class BrowseContainer extends Component {
}
componentDidMount() {
this.props.actions.historyList();
this.props.actions.historySortList();
this.props.actions.historyList(0);
}
componentWillUnmount() {
... ... @@ -114,6 +116,10 @@ class BrowseContainer extends Component {
this.props.actions.deleteOneHistory(data.get('product_skn'), index);
}
onEndReached() {
this.props.actions.historyList();
}
render() {
return (
... ... @@ -124,6 +130,7 @@ class BrowseContainer extends Component {
onPressFindSimilar={this.onPressFindSimilar}
onPressDelete={this.onPressDelete}
onPressGuangGuang={this.onPressGuangGuang}
onEndReached={this.onEndReached}
/>
);
}
... ...
... ... @@ -6,6 +6,10 @@ import Immutable, {Map} from 'immutable';
import {Platform} from 'react-native';
const {
HISTORY_SORT_LIST_REQUEST,
HISTORY_SORT_LIST_SUCCESS,
HISTORY_SORT_LIST_FAILURE,
HISTORY_LIST_REQUEST,
HISTORY_LIST_SUCCESS,
HISTORY_LIST_FAILURE,
... ... @@ -24,45 +28,78 @@ const {
export function setSelectedCategory(catId, index, catName) {
return (dispatch, getState) => {
dispatch({
type: SET_SELECTED_CATEGORY,
payload: {index}
});
dispatch(historyList(catId));
};
}
export function historySortListRequest() {
return {
type: HISTORY_SORT_LIST_REQUEST,
};
}
export function historySortListSuccess(json) {
return {
type: HISTORY_SORT_LIST_SUCCESS,
payload: json
};
}
export function historySortListFailure(error) {
return {
type: HISTORY_SORT_LIST_FAILURE,
payload: error
};
}
export function historySortList() {
return (dispatch, getState) => {
let {app, browse} = getState();
let productList = browse.productList.toJS();
let newProductList = [];
if (catId == -1) {
newProductList = productList;
} else {
productList.map((item, i) => {
if (item.category_id == catId) {
newProductList.push(item);
if (browse.isFetching) {
return;
}
let fetchList = (uid, sourcePage) => {
dispatch(historySortListRequest());
return new BrowseService(app.host).fetchSortList(uid, sourcePage)
.then(json => {
if (json.length > 0) {
json = [{category_id: -1, category_name: '全部'} , ...json];
}
dispatch(historySortListSuccess(json));
})
.catch(error => {
dispatch(historySortListFailure(error));
});
}
let pName = 'iFP_MineBrowseHistory';
if(Platform.OS === 'android'){
pName = 'aFP_MineBrowseHistory';
}
for (var i = 0; i < newProductList.length; i++) {
let item = newProductList[i];
let yh_exposureData = {
'P_NAME': pName,
'TAB_ID': parseInt(index) + 1,
'TAB_NAME': catName,
'I_INDEX': i + 1,
'PRD_SKN': item.product_skn?item.product_skn:'',
exposureEnd : 1,
};
item.yh_exposureData = yh_exposureData;
}
dispatch({
type: SET_SELECTED_CATEGORY,
payload: {productList: newProductList, index}
let uid = 0;
let sourcePage = '';
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, sourcePage);
})
.catch(error => {
fetchList(uid, sourcePage);
});
};
}
export function historyListRequest() {
export function historyListRequest(category_id) {
return {
type: HISTORY_LIST_REQUEST,
payload: category_id
};
}
... ... @@ -80,21 +117,36 @@ export function historyListFailure(error) {
};
}
export function historyList() {
export function historyList(category_id) {
return (dispatch, getState) => {
let {app, browse} = getState();
let productList = [];
if (browse && browse.productList && browse.productList.size > 0) {
productList = browse.productList.toJSON();
};
if (browse.isFetching) {
return;
}
let fetchList = (uid, page, pageSize, sourcePage) => {
dispatch(historyListRequest());
return new BrowseService(app.host).fetchList(uid, page, pageSize, sourcePage)
let fetchList = (uid, category_id, page, sourcePage) => {
dispatch(historyListRequest(category_id));
return new BrowseService(app.host).fetchPagelist(uid, category_id, page, sourcePage)
.then(json => {
let payload = parseHistoryList(json);
dispatch(historyListSuccess(payload));
let show = payload.productList.length > 0;
let currentPage = json && json.page ? json.page : 1;
let page_total = json && json.page_total ? json.page_total : 1;
let newproductList = json && json.product_list ? json.product_list : [];
if (productList.length) {
if (newproductList.length) {
productList=[...productList, ...newproductList];
};
} else if (newproductList.length){
productList = newproductList;
}
dispatch(historyListSuccess({currentPage, page_total, productList}));
let show = productList.length > 0;
ReactNative.NativeModules.YH_RecorderHelper.setRightClearButtonVisiblity(show);
})
.catch(error => {
... ... @@ -105,57 +157,25 @@ export function historyList() {
let uid = 0;
let sourcePage = '';
let page = browse.currentPage + 1;
let pageSize = browse.pageSize;
if (!category_id) {
category_id = browse.curCategoryID;
};
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);
fetchList(uid, category_id, page, sourcePage);
})
.catch(error => {
fetchList(uid, page, pageSize, sourcePage);
fetchList(uid, category_id, page, 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 : [];
let pName = 'iFP_MineBrowseHistory';
if(Platform.OS === 'android'){
pName = 'aFP_MineBrowseHistory';
}
for (var i = 0; i < productList.length; i++) {
let item = productList[i];
let yh_exposureData = {
'P_NAME': pName,
'TAB_ID': '1',
'TAB_NAME': '全部',
'I_INDEX': i + 1 + '',
'PRD_SKN': item.product_skn?item.product_skn:'',
exposureEnd : 1,
};
item.yh_exposureData = yh_exposureData;
}
if (categoryList.length > 0) {
categoryList = [{category_id: -1, category_name: '全部'} , ...categoryList];
}
return {
categoryList,
productList,
currentPage,
};
}
export function historyDeleteRequest() {
return {
... ... @@ -189,9 +209,7 @@ export function deleteOneHistory(skn, index) {
dispatch(historyDeleteRequest());
return new BrowseService(app.host).deleteHistory(skn, uid, sourcePage)
.then(json => {
let {productList, selectedProductList} = browse;
let selectedProduct = selectedProductList.toJS()[index];
selectedProductList = selectedProductList.delete(index);
let {productList} = browse;
let lists = productList.toArray();
let indexInAll = productList.findIndex((item, i) => {
return item.get('product_skn') == skn;
... ... @@ -199,10 +217,10 @@ export function deleteOneHistory(skn, index) {
if (indexInAll != -1) {
productList = productList.delete(indexInAll);
}
if (selectedProductList.size == 0 || selectedProductList.length == 0) {
dispatch(deleteSelectedProducts([selectedProduct]));
if (productList.size == 0 || productList.length == 0) {
dispatch(historySortList());
}else {
dispatch(historyDeleteSuccess({productList, selectedProductList}));
dispatch(historyDeleteSuccess({productList}));
}
let show = productList.size > 0;
... ... @@ -269,11 +287,9 @@ export function clearHistory(selectedProducts) {
dispatch(historyClearRequest());
return new BrowseService(app.host).deleteHistory(skns, uid, sourcePage)
.then(json => {
let {productList, selectedProductList} = browse;
console.log('000')
dispatch(deleteSelectedProducts(selectedProducts));
let show = productList.size > 0;
ReactNative.NativeModules.YH_RecorderHelper.setRightClearButtonVisiblity(show);
dispatch(historySortList());
dispatch(historyList(0));
dispatch({type: HISTORY_CLEAR_SUCCESS});
})
.catch(error => {
dispatch(historyClearFailure(error));
... ... @@ -299,40 +315,3 @@ export function clearHistory(selectedProducts) {
};
}
export function deleteSelectedProducts(selectedProducts) {
return (dispatch, getState) => {
let {app, browse} = getState();
if (browse.productList.size == 0) {
return;
}
let {productList, selectedProductList, categoryList} = browse;
let newProductList = [];
let categoryId = selectedProducts[0].category_id;
categoryList = categoryList.toJS();
let newCategoryList = [];
categoryList.map((categoryItem, i)=> {
if (categoryItem.category_id != categoryId) {
newCategoryList.push(categoryItem);
}
});
productList = productList.toJS();
productList.map((item, j) => {
let exist = false;
selectedProducts.map((selectedItem, i) => {
if (item.product_skn == selectedItem.product_skn) {
exist = true;
}
});
if (!exist) {
newProductList.push(item);
}
});
dispatch({
type: HISTORY_CLEAR_SUCCESS,
payload: {productList: newProductList,categoryList:newCategoryList,index:0}
});
};
}
... ...
... ... @@ -8,9 +8,10 @@ let InitialState = Record({
categoryList: List(),
productList: List(),
currentPage: 0,
page_total:0,
pageSize: 100,
selectedCategoryIndex: 0,
selectedProductList: List(),
curCategoryID: 0,
isDeleting: false,
showEmpty: false,
... ...
... ... @@ -4,6 +4,10 @@ import InitialState from './browseInitialState';
import Immutable, {Map, List} from 'immutable';
const {
HISTORY_SORT_LIST_REQUEST,
HISTORY_SORT_LIST_SUCCESS,
HISTORY_SORT_LIST_FAILURE,
HISTORY_LIST_REQUEST,
HISTORY_LIST_SUCCESS,
HISTORY_LIST_FAILURE,
... ... @@ -25,37 +29,47 @@ export default function browseReducer(state=initialState, action) {
switch(action.type) {
case HISTORY_LIST_REQUEST: {
return state.set('isFetching', true)
.set('error', null)
.set('curCategoryID', action.payload);
}
case HISTORY_SORT_LIST_REQUEST:{
return state.set('isFetching', true)
.set('error', null);
}
case HISTORY_LIST_SUCCESS: {
let {
categoryList,
productList,
currentPage,
page_total,
} = action.payload;
let showEmpty = productList.length == 0;
let newState = state.set('isFetching', false)
.set('error', null)
.set('categoryList', Immutable.fromJS(categoryList))
.set('productList', Immutable.fromJS(productList))
.set('selectedProductList', Immutable.fromJS(productList))
.set('page_total', Immutable.fromJS(page_total))
.set('currentPage', currentPage)
.set('showEmpty', showEmpty);
return newState;
}
case HISTORY_LIST_FAILURE: {
case HISTORY_LIST_FAILURE:
case HISTORY_SORT_LIST_FAILURE:{
return state.set('isFetching', false)
.set('error', action.payload);
}
case HISTORY_SORT_LIST_SUCCESS: {
return state.set('isFetching', false)
.set('categoryList', Immutable.fromJS(action.payload));
}
case SET_SELECTED_CATEGORY: {
let {productList, index} = action.payload;
return state.set('selectedCategoryIndex', index)
.set('selectedProductList', Immutable.fromJS(productList))
.set('currentPage', 0)
.set('productList',List());
}
case HISTORY_DELETE_REQUEST:
... ... @@ -66,10 +80,7 @@ export default function browseReducer(state=initialState, action) {
case HISTORY_DELETE_SUCCESS: {
let {productList, selectedProductList} = action.payload;
let showEmpty = productList.size == 0;
return state.set('isDeleting', false)
.set('productList', productList)
.set('selectedProductList', selectedProductList)
.set('showEmpty', showEmpty);
return state.set('isDeleting', false);
}
case HISTORY_DELETE_FAILURE:
... ... @@ -80,15 +91,8 @@ export default function browseReducer(state=initialState, action) {
case HISTORY_CLEAR_SUCCESS: {
let {productList,categoryList,index} = action.payload;
let show = productList.length==0;
return state.set('isDeleting', false)
.set('productList', Immutable.fromJS(productList))
.set('selectedProductList', Immutable.fromJS(productList))
.set('categoryList', Immutable.fromJS(categoryList))
.set('selectedCategoryIndex',index)
.set('showEmpty', show);
return state.set('isDeleting', false);
}
}
... ...
... ... @@ -12,14 +12,31 @@ export default class CategoryService {
this.api = new Request(baseURL);
}
async fetchList(uid=0, page=1, limit=100, fromPage='') {
async fetchSortList(uid=0, fromPage='') {
return await this.api.get({
url: '',
body: {
method: 'app.browse.product',
method: 'app.browse.sortlist',
uid,
fromPage
}
})
.then((json) => {
return json;
})
.catch((error) => {
throw(error);
});
}
async fetchPagelist(uid=0, category_id=0, page=1, fromPage='') {
return await this.api.get({
url: '',
body: {
method: 'app.browse.pagelist',
uid,
category_id,
page,
limit,
fromPage,
}
})
... ... @@ -31,6 +48,7 @@ export default class CategoryService {
});
}
async deleteHistory(skn=0, uid=0, fromPage='') {
let param = skn ? {uid, skn, fromPage,} : {uid, fromPage,};
return await this.api.get({
... ...