Authored by 孙凯

add 筛选 review by qiangbing

Showing 29 changed files with 1005 additions and 18 deletions
... ... @@ -21,6 +21,15 @@ import appInitialState from './reducers/app/appInitialState';
import productListInitialState from './reducers/productList/productListInitialState';
import ProductListContainer from './containers/ProductListContainer';
import screenInitialState from './reducers/screen/screenInitialState';
import screenCategoryInitialState from './reducers/screenCategory/screenCategoryInitialState';
import screenSubInitialState from './reducers/screenSub/screenSubInitialState';
import ScreenContainer from './containers/ScreenContainer';
import ScreenCategoryContainer from './containers/ScreenCategoryContainer';
import ScreenSubContainer from './containers/ScreenSubContainer';
import {
setPlatform,
setChannel,
... ... @@ -36,6 +45,9 @@ function getInitialState() {
const _initState = {
app: (new appInitialState()),
productS: (new productListInitialState()),
screen: (new screenInitialState()),
screenCategory: (new screenCategoryInitialState()),
screenSub: (new screenSubInitialState()),
};
return _initState;
}
... ... @@ -53,11 +65,31 @@ export default function native(platform) {
store.dispatch(setType(type));
store.dispatch(setBrandId(brand_id));
return (
<Provider store={store}>
<ProductListContainer />
</Provider>
);
if (type == 'YH_ScreenCategoryView' ) {
return (
<Provider store={store}>
<ScreenContainer />
</Provider>
);
} else if(type == 'YH_ProductFilterCategoryView' ){
return (
<Provider store={store}>
<ScreenCategoryContainer />
</Provider>
);
}else if (type == 'YH_ProductFilterSubView' ){
return (
<Provider store={store}>
<ScreenSubContainer />
</Provider>
);
}else if (type == 'YH_ProductListRNView' ){
return (
<Provider store={store}>
<ProductListContainer />
</Provider>
);
}
}
});
... ...
'use strict';
import React from 'react';
import ReactNative from 'react-native';
import Immutable, {Map} from 'immutable';
import DeviceInfo from 'react-native-device-info';
const {
View,
Text,
TouchableOpacity,
Dimensions,
StyleSheet,
Platform,
} = ReactNative;
export default class Header extends React.Component {
constructor(props) {
super (props);
}
render() {
return (
<View style={styles.container}>
<Text style={styles.name}>筛选商品</Text>
<TouchableOpacity onPress={() => {this.props.cancelAction && this.props.cancelAction()}} >
<View style={styles.cancelButton}>
<Text style={styles.cancelText}>清空</Text>
</View>
</TouchableOpacity>
<TouchableOpacity onPress={() => {this.props.okAction && this.props.okAction()}} >
<View style={styles.okButton}>
<Text style={styles.okText}>确定</Text>
</View>
</TouchableOpacity>
</View>
);
}
}
let {width, height} = Dimensions.get('window');
let backgroundWidth = width;
let backgroundHeight = 64;
let buttonHeight = 30;
let buttonWidth = 50;
let rightOffset = 50;
let styles = StyleSheet.create({
container: {
width: backgroundWidth,
height: backgroundHeight,
backgroundColor: 'gray',
flexDirection: 'row',
},
name: {
fontSize: 14,
color: 'white',
marginTop: backgroundHeight - 20 - 10,
marginLeft: 10,
width: 100,
height: buttonHeight,
backgroundColor: 'transparent',
},
cancelButton: {
height: buttonHeight,
width: buttonWidth,
backgroundColor: 'white',
marginTop: backgroundHeight - buttonHeight - 10,
alignItems: 'center',
justifyContent: 'center',
marginLeft: width - rightOffset - 110 - 10 - 2*buttonWidth - 10,
},
cancelText: {
color: 'black',
},
okButton: {
height: buttonHeight,
width: buttonWidth,
backgroundColor: 'black',
marginTop: backgroundHeight - buttonHeight - 10,
alignItems: 'center',
justifyContent: 'center',
marginLeft: 10,
},
okText: {
color: 'white',
},
});
... ...
'use strict';
import React, {Component} from 'react';
import ReactNative, {
View,
Text,
Image,
ListView,
StyleSheet,
Dimensions,
TouchableOpacity,
Platform,
} from 'react-native';
import Header from './Header';
import ScreenCell from './ScreenCell';
export default class Screen 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,highlightRow) {
return(
<ScreenCell resource={rowData} onSelect={this.props.onSelectItem}></ScreenCell>
);
}
render() {
let {resource} = this.props;
let list = resource&&resource.get('categoryFilterList')?resource.get('categoryFilterList'):null;
return (
<View style={styles.container}>
<Header okAction={this.props.okAction} cancelAction={this.props.cancelAction}/>
{list?<ListView
ref='ScreenList'
enableEmptySections={true}
dataSource={this.dataSource.cloneWithRows(list.toArray())}
renderRow={this.renderRow}
/>:null}
</View>
);
}
}
let {width, height} = Dimensions.get('window');
let styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#f4f4f4',
},
});
... ...
'use strict';
import React from 'react';
import ReactNative from 'react-native';
import Immutable, {Map} from 'immutable';
import DeviceInfo from 'react-native-device-info';
const {
View,
Text,
TouchableOpacity,
Dimensions,
StyleSheet,
Platform,
Image,
} = ReactNative;
export default class ScreenCell extends React.Component {
constructor(props) {
super (props);
}
render() {
let resource = this.props.resource?this.props.resource.toJS():null;
if (!resource) {
return null;
}
let name = resource.name+': ';
let isTrue = resource.isSelect;
let select = resource.select;
let value = select?select.name:'';
let subFilter = resource.subFilter;
return (
<View style={styles.container}>
<TouchableOpacity onPress={() => {this.props.onSelect && this.props.onSelect(subFilter)}} >
<View style={styles.cell}>
<Text style={styles.name}>{name}</Text>
<Text style={{color: isTrue ? 'rgb(146, 146, 146)' : '#444444'}}>{value}</Text>
<Image style={styles.arrow} source={require('../../images/arrow_gray.png')}></Image>
</View>
<View style={{width: width,height: 0.5,backgroundColor: 'rgb(235, 235, 235)'}}/>
</TouchableOpacity>
</View>
);
}
}
let {width, height} = Dimensions.get('window');
let backgroundWidth = width;
let backgroundHeight = 40;
let rightOffset = 50;
let styles = StyleSheet.create({
container: {
width: backgroundWidth,
height: backgroundHeight,
alignItems: 'center',
},
cell: {
width: backgroundWidth,
height: backgroundHeight-0.5,
backgroundColor: '#f0f0f0',
flexDirection: 'row',
alignItems: 'center',
},
name: {
marginLeft: 10,
color: 'rgb(146, 146, 146)'
},
arrow: {
height: 12,
position: 'absolute',
marginVertical: (backgroundHeight - 12 )/2,
right: 10 + rightOffset,
},
});
... ...
'use strict';
import React, {Component} from 'react';
import ReactNative, {
View,
Text,
Image,
ListView,
StyleSheet,
Dimensions,
TouchableOpacity,
Platform,
} from 'react-native';
export default class ScreenCategory extends Component {
constructor(props) {
super(props);
}
render() {
let {resource} = this.props;
return (
<View style={styles.container}>
<Text>aaaaaaa</Text>
</View>
);
}
}
let {width, height} = Dimensions.get('window');
let styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#f4f4f4',
},
});
... ...
'use strict';
import React, {Component} from 'react';
import ScreenSubCell from './ScreenSubCell';
import ReactNative, {
View,
Text,
Image,
ListView,
StyleSheet,
Dimensions,
TouchableOpacity,
Platform,
} from 'react-native';
export default class ScreenSub 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,highlightRow) {
return(
<ScreenSubCell resource={rowData} />
);
}
render() {
let {resource} = this.props;
let obj = resource&&resource.get('filterSub')?resource.get('filterSub'):null;
let list = obj?obj.get('list'):null;
console.log(list?list.toJS():'a');
return (
<View style={styles.container}>
{list?<ListView
ref='ScreenSubList'
enableEmptySections={true}
dataSource={this.dataSource.cloneWithRows(list.toArray())}
renderRow={this.renderRow}
/>:null}
</View>
);
}
}
let {width, height} = Dimensions.get('window');
let styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#f4f4f4',
},
});
... ...
'use strict';
import React from 'react';
import ReactNative from 'react-native';
import Immutable, {Map} from 'immutable';
import DeviceInfo from 'react-native-device-info';
const {
View,
Text,
TouchableOpacity,
Dimensions,
StyleSheet,
Platform,
Image,
} = ReactNative;
export default class ScreenSubCell extends React.Component {
constructor(props) {
super (props);
}
render() {
let resource = this.props.resource?this.props.resource.toJS():null;
if (!resource) {
return null;
}
let isSelect = resource.isSelect;
let key = resource.key;
let name = resource.name;
return (
<View style={styles.container}>
<TouchableOpacity onPress={() => {console.log('aaaaaaa');}} >
<View style={styles.cell}>
<Text style={styles.name}>{name}</Text>
<Image style={styles.arrow} source={require('../../images/arrow_gray.png')}></Image>
</View>
<View style={{width: width,height: 0.5,backgroundColor: 'rgb(235, 235, 235)'}}/>
</TouchableOpacity>
</View>
);
}
}
let {width, height} = Dimensions.get('window');
let backgroundWidth = width;
let backgroundHeight = 40;
let rightOffset = 50;
let styles = StyleSheet.create({
container: {
width: backgroundWidth,
height: backgroundHeight,
alignItems: 'center',
},
cell: {
width: backgroundWidth,
height: backgroundHeight-0.5,
backgroundColor: '#f0f0f0',
flexDirection: 'row',
alignItems: 'center',
},
name: {
marginLeft: 10,
color: 'rgb(146, 146, 146)'
},
arrow: {
height: 12,
position: 'absolute',
marginVertical: (backgroundHeight - 12 )/2,
right: 10 + rightOffset,
},
});
... ...
... ... @@ -5,6 +5,13 @@ export default keyMirror({
SET_PLATFORM: null,
SET_HOST: null,
SET_CHANNEL: null,
SET_DATASOURCE: null,
SET_DATASOURCE_CATEGORY: null,
SET_DATASOURCE_SUB: null,
SET_TYPE: null,
SET_BRANDID: null,
GET_BRAND_BANNER_INFO_REQUEST: null,
... ...
'use strict'
import React, {Component} from 'react';
import ReactNative, {
StyleSheet,
Dimensions,
Platform,
View,
Text,
NativeModules,
InteractionManager,
NativeAppEventEmitter,
} from 'react-native'
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
import {Map} from 'immutable';
import * as screenCategoryActions from '../reducers/screenCategory/screenCategoryActions';
import * as appActions from '../reducers/app/appActions';
import ScreenCategory from '../components/screenCategory/ScreenCategory';
const actions = [
screenCategoryActions,
appActions
];
function mapStateToProps(state) {
return {
...state
};
}
function mapDispatchToProps(dispatch) {
const creators = Map()
.merge(...actions)
.filter(value => typeof value === 'function')
.toObject();
return {
actions: bindActionCreators(creators, dispatch),
dispatch
};
}
class ScreenCategoryContainer extends Component {
constructor(props) {
super(props);
}
componentWillUnmount() {
}
render() {
let {app, sreenCategory} = this.props;
return (
<View style={styles.container}>
<ScreenCategory
resource={sreenCategory}
/>
</View>
);
}
}
let {width, height} = Dimensions.get('window');
let styles = StyleSheet.create({
container: {
flex: 1,
},
});
export default connect(mapStateToProps, mapDispatchToProps)(ScreenCategoryContainer);
... ...
'use strict'
import React, {Component} from 'react';
import ReactNative, {
StyleSheet,
Dimensions,
Platform,
View,
Text,
NativeModules,
InteractionManager,
NativeAppEventEmitter,
} from 'react-native'
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
import {Map} from 'immutable';
import * as screenActions from '../reducers/screen/screenActions';
import * as appActions from '../reducers/app/appActions';
import Screen from '../components/screen/Screen';
const actions = [
screenActions,
appActions
];
function mapStateToProps(state) {
return {
...state
};
}
function mapDispatchToProps(dispatch) {
const creators = Map()
.merge(...actions)
.filter(value => typeof value === 'function')
.toObject();
return {
actions: bindActionCreators(creators, dispatch),
dispatch
};
}
class ScreenContainer extends Component {
constructor(props) {
super(props);
this.updateFilter = this.updateFilter.bind(this);
this.cancelAction = this.cancelAction.bind(this);
this.onSelectItem = this.onSelectItem.bind(this);
this.okAction = this.okAction.bind(this);
this.subscription = NativeAppEventEmitter.addListener(
'updateFilter',
(dic) => {
this.updateFilter(dic);
}
);
}
componentWillUnmount() {
this.subscription && this.subscription.remove();
}
okAction() {
ReactNative.NativeModules.YH_ScreenCategoryViewHelper.okAction();
}
cancelAction() {
ReactNative.NativeModules.YH_ScreenCategoryViewHelper.cancelAction();
}
onSelectItem(subFilter) {
ReactNative.NativeModules.YH_ScreenCategoryViewHelper.didSelectScreenIetmIndex(subFilter);
}
updateFilter(dic){
if (dic) {
this.props.actions.updateDataSource(dic);
}
}
render() {
let {app, screen} = this.props;
return (
<View style={styles.container}>
<Screen
resource={screen}
okAction={this.okAction}
cancelAction={this.cancelAction}
onSelectItem={this.onSelectItem}
/>
</View>
);
}
}
let {width, height} = Dimensions.get('window');
let styles = StyleSheet.create({
container: {
flex: 1,
},
});
export default connect(mapStateToProps, mapDispatchToProps)(ScreenContainer);
... ...
'use strict'
import React, {Component} from 'react';
import ReactNative, {
StyleSheet,
Dimensions,
Platform,
View,
Text,
NativeModules,
InteractionManager,
NativeAppEventEmitter,
} from 'react-native'
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
import {Map} from 'immutable';
import * as screenCategoryActions from '../reducers/screenSub/screenSubActions';
import * as appActions from '../reducers/app/appActions';
import ScreenSub from '../components/screenSub/ScreenSub';
const actions = [
screenCategoryActions,
appActions
];
function mapStateToProps(state) {
return {
...state
};
}
function mapDispatchToProps(dispatch) {
const creators = Map()
.merge(...actions)
.filter(value => typeof value === 'function')
.toObject();
return {
actions: bindActionCreators(creators, dispatch),
dispatch
};
}
class ScreenSubContainer extends Component {
constructor(props) {
super(props);
this.updateFilterSub = this.updateFilterSub.bind(this);
this.subscription = NativeAppEventEmitter.addListener(
'updateFilterSub',
(dic) => {
this.updateFilterSub(dic);
}
);
}
componentWillUnmount() {
this.subscription && this.subscription.remove();
}
updateFilterSub(dic){
if (dic) {
this.props.actions.updateDataSource(dic);
}
}
render() {
let {app, screenSub} = this.props;
return (
<View style={styles.container}>
<ScreenSub
resource={screenSub}
/>
</View>
);
}
}
let {width, height} = Dimensions.get('window');
let styles = StyleSheet.create({
container: {
flex: 1,
},
});
export default connect(mapStateToProps, mapDispatchToProps)(ScreenSubContainer);
... ...
import {combineReducers} from 'redux';
import app from './app/appReducer';
import productS from './productList/productListReducer';
import screen from './screen/screenReducer';
import screenCategory from './screenCategory/screenCategoryReducer';
import screenSub from './screenSub/screenSubReducer';
const rootReducer = combineReducers({
app,
productS,
screen,
screenCategory,
screenSub,
});
export default rootReducer;
... ...
... ... @@ -446,6 +446,10 @@ export function getProductList(reload=false) {
let list = [...oldList, ...payload.list];
payload.list = list;
}
let categoryFilterList = payload.categoryFilterList;
let filterCategoryDetailFilterList = payload.filterCategoryDetailFilterList;
let filters = parsecategoryFilter({categoryFilterList,filterCategoryDetailFilterList});
ReactNative.NativeModules.YH_ProductListRNViewHelper.setFilterData(filters);
dispatch(productListSuccess(payload));
})
.catch(error => {
... ... @@ -465,6 +469,48 @@ function randomString(len) {
  return pwd;
}
function parsecategoryFilter(json) {
let categoryFilterList = json.categoryFilterList;
let filterCategoryDetailFilterList = json.filterCategoryDetailFilterList;
for (var i = 0; i < categoryFilterList.length; i++) {
let key = categoryFilterList[i].key;
let type = 0;
if (key == 'sort') {
type = 0;
}else if (key == 'brand'){
type = 1;
}else if (key == 'color'){
type = 2;
}else if (key == 'sizeKey'){
type = 3;
}else if (key == 'price'){
type = 4;
}else if (key == 'p_d'){
type = 5;
}else if (key == 'gender'){
type = 7;
}else if (key == 'style'){
type = 10;
}
_.forEach(filterCategoryDetailFilterList, (v, k) => {
if (k == key) {
let list = v;
for (var j = 0; j < list.length; j++) {
if (list[j].isSelect) {
categoryFilterList[i].select = list[j];
categoryFilterList[i].subFilter = {list,key,type};
}
}
}
});
}
return{
categoryFilterList,
}
}
function parseProductList(json) {
let currentPage = json && json.page ? json.page : 1;
let pageCount = json && json.page_total ? json.page_total : 0;
... ... @@ -647,6 +693,32 @@ function parseProductList(json) {
filterCategoryDetailFilterList.p_d = newP_dList;
}
if (filter['style']) {
categoryFilterList.push({
key: 'style',
name: '风格',
isSelect: false,
});
let p_dObject = filter['style'];
p_dObject = sortListByField(p_dObject, 'style_name'); // 折扣,价格区间,需要排序
let newP_dList = [];
newP_dList.push({
key: '',
name: '所有风格',
isSelect: true,
});
_.forEach(p_dObject, (v, k) => {
newP_dList.push({
key: v._key,
name: v.name,
isSelect: false,
});
});
filterCategoryDetailFilterList.style;
filterCategoryDetailFilterList.style = newP_dList;
}
let recId = randomString(40);
return {
list,
... ...
... ... @@ -47,6 +47,7 @@ let InitialState = Record({
p_d: '', //折扣
sort: '', //品类
brand: '', //品牌
style: '', //风格
})),
filterNameFactors: new (Record({
gender: '所有性别', //性别
... ... @@ -56,6 +57,7 @@ let InitialState = Record({
p_d: '所有折扣', //折扣
sort: '所有品类', //品类
brand: '所有品牌', //品牌
style: '所有风格', //风格
})),
receiveCouponResult: new (Record({
showMessage: '',
... ...
... ... @@ -80,22 +80,30 @@ export default function productListReducer(state=initialState, action) {
.setIn(['productList', 'error'], null);
}
case PRODUCT_LIST_SUCCESS: {
let {
list,
currentPage,
pageCount,
total,
endReached,
} = action.payload;
list,
categoryFilterList,
filterCategoryDetailFilterList,
currentPage,
pageCount,
total,
recId,
endReached,
} = action.payload;
let newState = state.setIn(['productList', 'isFetching'], false)
.setIn(['productList', 'error'], null)
.setIn(['productList', 'list'], Immutable.fromJS(list))
.setIn(['productList', 'currentPage'], currentPage)
.setIn(['productList', 'pageCount'], pageCount)
.setIn(['productList', 'total'], total)
.setIn(['productList', 'endReached'], endReached)
.setIn(['productList', 'error'], null)
.setIn(['productList', 'list'], Immutable.fromJS(list))
.setIn(['productList', 'currentPage'], currentPage)
.setIn(['productList', 'pageCount'], pageCount)
.setIn(['productList', 'total'], total)
.setIn(['productList', 'endReached'], endReached);
if (currentPage == 1 && state.categoryFilterList.size == 0 && state.filterCategoryDetailFilterList.size == 0) {
newState = newState.set('categoryFilterList', Immutable.fromJS(categoryFilterList))
.set('filterCategoryDetailFilterList', Immutable.fromJS(filterCategoryDetailFilterList));
}
return newState;
}
case PRODUCT_LIST_FAILURE: {
... ...
'use strict';
import ReactNative from 'react-native';
const {
SET_DATASOURCE,
} = require('../../constants/actionTypes').default;
export function updateDataSource(data) {
return {
type: SET_DATASOURCE,
payload: data
};
}
... ...
'use strict';
import Immutable, {Record, List, Map} from 'immutable';
let InitialState = Record({
categoryFilterList: List(),
filterCategoryDetailFilterList: List(),
dataSourceType: 0,
});
export default InitialState;
... ...
'use strict';
import InitialState from './screenInitialState';
import Immutable, {Map} from 'immutable';
const {
SET_DATASOURCE
} = require('../../constants/actionTypes').default;
const initialState = new InitialState;
export default function screenReducer(state=initialState, action) {
switch(action.type){
case SET_DATASOURCE:
{
return state.set('categoryFilterList',Immutable.fromJS(action.payload.categoryFilterList))
.set('filterCategoryDetailFilterList',Immutable.fromJS(action.payload.filterCategoryDetailFilterList))
.set('dataSourceType', action.payload.dataSourceType);
}
}
return state;
}
... ...
'use strict';
import ReactNative from 'react-native';
const {
SET_DATASOURCE_CATEGORY,
} = require('../../constants/actionTypes').default;
export function updateDataSource(data) {
return {
type: SET_DATASOURCE_CATEGORY,
payload: data
};
}
... ...
'use strict';
import Immutable, {Record, List, Map} from 'immutable';
let InitialState = Record({
screenList: List(),
dataSourceType: 0,
});
export default InitialState;
... ...
'use strict';
import InitialState from './screenCategoryInitialState';
import Immutable, {Map} from 'immutable';
const {
SET_DATASOURCE_CATEGORY
} = require('../../constants/actionTypes').default;
const initialState = new InitialState;
export default function screenCategoryReducer(state=initialState, action) {
switch(action.type){
case SET_DATASOURCE_CATEGORY:
{
return state.set('screenList',Immutable.fromJS(action.payload.dataList)).set('dataSourceType', action.payload.dataSourceType);
}
}
return state;
}
... ...
'use strict';
import ReactNative from 'react-native';
const {
SET_DATASOURCE_SUB,
} = require('../../constants/actionTypes').default;
export function updateDataSource(data) {
return {
type: SET_DATASOURCE_SUB,
payload: data
};
}
... ...
'use strict';
import Immutable, {Record, List, Map} from 'immutable';
let InitialState = Record({
filterSub: new (Record({
key: '',
list: List(),
})),
});
export default InitialState;
... ...
'use strict';
import InitialState from './screenSubInitialState';
import Immutable, {Map} from 'immutable';
const {
SET_DATASOURCE_SUB
} = require('../../constants/actionTypes').default;
const initialState = new InitialState;
export default function screenSubReducer(state=initialState, action) {
switch(action.type){
case SET_DATASOURCE_SUB:
{
return state.setIn(['filterSub', 'key'], action.payload.key)
.setIn(['filterSub', 'list'], Immutable.fromJS(action.payload.list));
}
}
return state;
}
... ...
'use strict';
import Request from '../../common/services/Request';
export default class ScreenCategoryService {
constructor(host) {
let baseURL = 'http://api.yoho.cn';
if(host){
baseURL = host;
}
this.api = new Request(baseURL);
}
}
... ...
'use strict';
import Request from '../../common/services/Request';
export default class ScreenService {
constructor(host) {
let baseURL = 'http://api.yoho.cn';
if(host){
baseURL = host;
}
this.api = new Request(baseURL);
}
}
... ...
'use strict';
import Request from '../../common/services/Request';
export default class ScreenSubService {
constructor(host) {
let baseURL = 'http://api.yoho.cn';
if(host){
baseURL = host;
}
this.api = new Request(baseURL);
}
}
... ...