Authored by 于良

Merge branch 'classify' of http://git.yoho.cn/mobile/YH_RNComponent into classify

... ... @@ -51,7 +51,7 @@ export default class ProductListView extends Component {
tipState = '去抢购';
}
return (
<TouchableOpacity onPress={() => {
<TouchableOpacity activeOpacity={1.0} onPress={() => {
this.props.onPressProductItem && this.props.onPressProductItem(rowData);
}}>
<View key={'row' + rowID} style={styles.rowContainer}>
... ... @@ -63,7 +63,7 @@ export default class ProductListView extends Component {
{rowData.wait?
<View style={[styles.secKillMarketPriceContainer,{marginTop:5}]}>
<Text style={[styles.secKillPrice,{color:'#d0021b'}]}>¥{rowData.secKillPrice}</Text>
<DeleteLineText style={{top:3,left:8}} text={rowData.marketPrice} />
<DeleteLineText style={{top:3,left:8}} text={'¥' + rowData.marketPrice} />
</View>
:null
}
... ... @@ -77,13 +77,17 @@ export default class ProductListView extends Component {
</View>
:<View style={styles.secKillMarketPriceContainer}>
<Text style={[styles.secKillPrice,{color:'#d0021b'}]}>¥{rowData.secKillPrice}</Text>
<DeleteLineText style={{top:3, left:8}} text={rowData.marketPrice} />
<DeleteLineText style={{top:3, left:8}} text={'¥' + rowData.marketPrice} />
</View>
}
</View>
<TouchableOpacity onPress={() => {
this.props.onPressRemindBtn && this.props.onPressRemindBtn(rowData);
if (rowData.wait) {
this.props.onPressRemindBtn && this.props.onPressRemindBtn(rowData);
}else {
this.props.onPressProductItem && this.props.onPressProductItem(rowData);
}
}}>
{
(tipState=='取消提醒')?
... ...
... ... @@ -11,6 +11,7 @@ import {
ListView,
TouchableOpacity,
RefreshControl,
InteractionManager,
} from 'react-native';
import Immutable, {Map} from 'immutable';
... ... @@ -35,7 +36,13 @@ export default class Seckill extends Component {
componentDidMount() {
if (Platform.OS === 'ios') {
InteractionManager.runAfterInteractions(() => {
this.listView && this.listView.getScrollResponder().startPullToRefresh();
});
}else{
this.props.onRefresh && this.props.onRefresh();
}
}
componentWillUnmount() {
... ... @@ -119,6 +126,7 @@ export default class Seckill extends Component {
queryActivityInfo,
queryProductList,
addCancelUserReminderTip,
ptr,
} = this.props;
this.isFetching = isFetching;
this.queryActivityInfo = queryActivityInfo;
... ... @@ -126,17 +134,21 @@ export default class Seckill extends Component {
let dataSource = {
ActivityProductList: [queryProductList.toArray()],
};
let isPullToRefresh = ptr && isFetching;
return (
<View style={styles.container}>
{
Platform.OS === 'ios'?<ListView
ref={(c) => {
this.listView = c;
}}
contentContainerStyle={styles.contentContainer}
enableEmptySections={true}
dataSource={this.dataSource.cloneWithRowsAndSections(dataSource)}
renderRow={this.renderRow}
enablePullToRefresh={true}
isOnPullToRefresh={isFetching}
isOnPullToRefresh={isPullToRefresh}
onRefreshData={() => {
//强制刷新数据
if (isFetching) {
... ... @@ -155,6 +167,9 @@ export default class Seckill extends Component {
</View>
}}
/>:<ListView
ref={(c) => {
this.listView = c;
}}
refreshControl={
<RefreshControl
refreshing={false}
... ...
... ... @@ -21,6 +21,7 @@ export default class SeckillTimeListView extends Component {
this._renderRow = this._renderRow.bind(this);
this._renderSeparator = this._renderSeparator.bind(this);
this._scrollToFocusActivity = this._scrollToFocusActivity.bind(this);
this._caculateTimerState = this._caculateTimerState.bind(this);
this.dataSource = new ListView.DataSource({
rowHasChanged: (r1, r2) => r1.key != r2.key,
... ... @@ -28,7 +29,6 @@ export default class SeckillTimeListView extends Component {
this.curFocusActivity = Immutable.fromJS({});
this.secKillProductVoList = Immutable.fromJS([]);
this.state = {
selectedIndex: 0,
tickHour: '00',
tickMinute: '00',
tickSecond: '00',
... ... @@ -49,14 +49,45 @@ export default class SeckillTimeListView extends Component {
});
// if (curFocusIndex > 1 && curFocusIndex < listLength-2) {
scrollX = (curFocusIndex - 1) * rowContainerWidth;
this.listView && this.listView.scrollTo({x: scrollX, y: 0, animated: false});
this.listView && this.listView.scrollTo({x: scrollX, y: 0, animated: true});
// }
}
}
_caculateTimerState() {
let nowTime = Date.parse(new Date()) / 1000 + diffTime;
let time = this.curFocusActivity.has('now') ? this.curFocusActivity.get('endTime'): this.curFocusActivity.get('startTime') / 1000;
let offsetTime = time - nowTime;
let hour = parseInt(offsetTime / (60 * 60), 10);
let minute = parseInt(offsetTime % (60 * 60) / 60, 10);
let second = offsetTime % 60;
if (offsetTime <= 0) {
if (!this.state.tickTimeOut) {
this.setState({
tickHour: '',
tickMinute: '',
tickSecond: '',
tickTimeOut: true,
});
}
} else {
this.setState({
tickHour: hour < 0 ? '00' : (hour < 10 ? ('0' + hour) : (hour > 99 ? 99 : hour)),
tickMinute: minute < 0 ? '00' : (minute < 10 ? ('0' + minute) : minute),
tickSecond: second < 0 ? '00' : (second < 10 ? ('0' + second) : second),
tickTimeOut: false,
});
}
}
componentDidMount() {
if (this.secKillProductVoList && this.secKillProductVoList.length > 0) {
this.curFocusActivity = this.secKillProductVoList.find(activityTimeItem => activityTimeItem.get('focus'));
}
let jumpToTimeoutActivity = () => {
this.secKillProductVoList.forEach((activityItem, i) => {
let nowTime = Date.parse(new Date()) / 1000 + diffTime;
... ... @@ -73,31 +104,7 @@ export default class SeckillTimeListView extends Component {
return;
}
jumpToTimeoutActivity();
let nowTime = Date.parse(new Date()) / 1000 + diffTime;
let time = this.curFocusActivity.has('now') ? this.curFocusActivity.get('endTime'): this.curFocusActivity.get('startTime') / 1000;
let offsetTime = time - nowTime;
let hour = parseInt(offsetTime / (60 * 60), 10);
let minute = parseInt(offsetTime % (60 * 60) / 60, 10);
let second = offsetTime % 60;
if (offsetTime <= 0) {
if (!this.state.tickTimeOut) {
this.props.onFocusToCurStartedActivity && this.props.onFocusToCurStartedActivity(this.curFocusActivity.toJS());
}
this.setState({
tickHour: '00',
tickMinute: '00',
tickSecond: '00',
tickTimeOut: true,
});
} else {
this.setState({
tickHour: hour < 0 ? '00' : (hour < 10 ? ('0' + hour) : hour),
tickMinute: minute < 0 ? '00' : (minute < 10 ? ('0' + minute) : minute),
tickSecond: second < 0 ? '00' : (second < 10 ? ('0' + second) : second),
tickTimeOut: false,
});
}
this._caculateTimerState();
}.bind(this), 1000);
this._scrollToFocusActivity();
... ... @@ -110,10 +117,10 @@ export default class SeckillTimeListView extends Component {
componentWillReceiveProps(nextProps) {
if (nextProps.resource && nextProps.resource.length > 0) {
let focusActivity = nextProps.resource.find(activityTimeItem => activityTimeItem.get('focus'));
this.curFocusActivity = focusActivity;
this.curFocusActivity = nextProps.resource.find(activityTimeItem => activityTimeItem.get('focus'));
}
this._scrollToFocusActivity();
this._caculateTimerState();
}
... ... @@ -121,7 +128,7 @@ export default class SeckillTimeListView extends Component {
rowData = rowData.toJS();
let colorStyle = rowData.focus ? {color: '#d30018'} : {color: '#3e3e3e'};
return (
<TouchableOpacity onPress={() => {
<TouchableOpacity activeOpacity={1.0} onPress={() => {
if (rowData.focus) {
return;
}
... ... @@ -151,7 +158,7 @@ export default class SeckillTimeListView extends Component {
</View>
: null}
{rowData.over ? <Text style={[colorStyle,{fontSize: 10}]}>{rowData.time} 已开抢</Text> : null}
{rowData.over ? <Text style={[colorStyle,{fontSize: 13}]}>{rowData.time} 已开抢</Text> : null}
{rowData.wait ?
<View key={'row' + rowID} style={styles.rowContainerFocus}>
<Text style={[colorStyle,{fontSize: 13}]}>{rowData.time} 即将开抢</Text>
... ... @@ -198,10 +205,6 @@ export default class SeckillTimeListView extends Component {
resource,
diff,
} = this.props;
if (resource && resource.length > 0) {
let focusActivity = resource.find(activityTimeItem => activityTimeItem.get('focus'));
this.curFocusActivity = focusActivity;
}
diffTime = diff;
this.secKillProductVoList = resource;
backgroundWidth = Math.max(rowContainerWidth * (resource.length - 1) + rowContainerFocusWidth, width);
... ... @@ -215,6 +218,7 @@ export default class SeckillTimeListView extends Component {
dataSource={this.dataSource.cloneWithRows(resource)}
renderSeparator={this._renderSeparator}
renderRow={this._renderRow}
showsHorizontalScrollIndicator={false}
scrollEnabled={true}
horizontal={true}
scrollsToTop={false}
... ...
... ... @@ -17,9 +17,9 @@ export default keyMirror({
QUERY_PRODUCT_LIST_SUCCESS: null,
QUERY_PRODUCT_LIST_FAILURE: null,
QUERY_REMIND_LIST_REQUEST: null,
QUERY_REMIND_LIST_SUCCESS: null,
QUERY_REMIND_LIST_FAILURE: null,
QUERY_PRODUCT_AND_REMIND_LIST_REQUEST: null,
QUERY_PRODUCT_AND_REMIND_LIST_SUCCESS: null,
QUERY_PRODUCT_AND_REMIND_LIST_FAILURE: null,
ADD_CANCEL_USER_REMINDER_REQUEST: null,
ADD_CANCEL_USER_REMINDER_SUCCESS: null,
... ...
... ... @@ -74,7 +74,7 @@ class SeckillContainer extends Component {
}
_onFocusToCurStartedActivity(activity) {
this.props.actions.getSeckillQueryActivity(activity.startTime);
this.props.actions.getSeckillQueryActivity(activity.startTime / 1000);
}
render() {
... ... @@ -86,12 +86,14 @@ class SeckillContainer extends Component {
queryProductList,
queryRemindList,
addCancelUserReminderTip,
ptr,
} = this.props.seckill;
return (
<Seckill
isFetching = {isFetching}
error = {error}
ptr = {ptr}
queryActivityInfo = {queryActivityInfo}
queryProductList = {queryProductList}
queryRemindList = {queryRemindList}
... ...
... ... @@ -2,6 +2,8 @@
import ReactNative from 'react-native';
import SeckillService from '../../services/SeckillService';
import Immutable, {Map} from 'immutable';
const Platform = require('Platform');
const moment = require('moment');
... ... @@ -16,9 +18,9 @@ const {
QUERY_PRODUCT_LIST_SUCCESS,
QUERY_PRODUCT_LIST_FAILURE,
QUERY_REMIND_LIST_REQUEST,
QUERY_REMIND_LIST_SUCCESS,
QUERY_REMIND_LIST_FAILURE,
QUERY_PRODUCT_AND_REMIND_LIST_REQUEST,
QUERY_PRODUCT_AND_REMIND_LIST_SUCCESS,
QUERY_PRODUCT_AND_REMIND_LIST_FAILURE,
ADD_CANCEL_USER_REMINDER_REQUEST,
ADD_CANCEL_USER_REMINDER_SUCCESS,
... ... @@ -84,22 +86,22 @@ export function queryProductListFailure(error) {
}
}
export function queryRemindListRequest() {
export function queryProductAndRemindListRequest() {
return {
type: QUERY_REMIND_LIST_REQUEST
type: QUERY_PRODUCT_AND_REMIND_LIST_REQUEST
}
}
export function queryRemindListSuccess(json) {
export function queryProductAndRemindListSuccess(json) {
return {
type: QUERY_REMIND_LIST_SUCCESS,
type: QUERY_PRODUCT_AND_REMIND_LIST_SUCCESS,
payload: json
}
}
export function queryRemindListFailure(error) {
export function queryProductAndRemindListFailure(error) {
return {
type: QUERY_REMIND_LIST_FAILURE,
type: QUERY_PRODUCT_AND_REMIND_LIST_FAILURE,
payload: error
}
}
... ... @@ -145,6 +147,7 @@ export function updateSecKillProductList(json) {
}
export function setStartTime(startTime) {
startTime = moment(startTime, 'YYYYMMDDHHmmss').unix();
return {
type: SET_START_TIME,
payload: startTime,
... ... @@ -168,7 +171,7 @@ export function getSeckillQueryActivity(inStartTime = 0) {
let focusActivity = processedTimeInfo.focusActivity;
curActivityId = focusActivity.activityId;
if (Date.now() < focusActivity.startTime) {
dispatch(getSeckillRemindList(curActivityId));
dispatch(getSeckillProductRemindList(curActivityId));
} else {
dispatch(getSeckillProductList(curActivityId));
}
... ... @@ -188,69 +191,57 @@ export function getSeckillQueryActivity(inStartTime = 0) {
export function getSeckillProductList(activityId = curActivityId) {
curActivityId = activityId;
return (dispatch, getState) => {
dispatch(queryProductListRequest());
let queryProductList = (activityId) => {
let {app, seckill} = getState();
let {queryRemindList} = seckill;
queryRemindList = queryRemindList.toJS();
return new SeckillService(app.host).fetchQueryProductList(activityId)
.then(json => {
let productList = productAddFlag(json, queryRemindList);
dispatch(queryProductListSuccess(productList, queryRemindList));
})
.catch(error => {
dispatch(queryProductListFailure(error));
});
}
ReactNative.NativeModules.YH_CommonHelper.uid()
.then(uid => {
queryProductList(activityId);
let {app, seckill} = getState();
let {queryRemindList} = seckill;
queryRemindList = queryRemindList.toJS();
return new SeckillService(app.host).fetchQueryProductList(activityId)
.then(json => {
let productList = [];
if (queryRemindList && queryRemindList.length > 0) {
productList = productAddFlag(json, queryRemindList);
} else {
productList = productAddFlag(json);
}
dispatch(queryProductListSuccess(productList));
})
.catch(error => {
ReactNative.NativeModules.YH_CommonHelper.login()
.then(uid => {
queryProductList(activityId);
})
.catch(error => {
});
dispatch(queryProductListFailure(error));
});
};
}
export function getSeckillRemindList(activityId = curActivityId) {
/*
* 秒杀商品列表
*/
export function getSeckillProductRemindList(activityId = curActivityId) {
curActivityId = activityId;
return (dispatch, getState) => {
dispatch(queryRemindListRequest());
let queryRemindList = (activityId, uid) => {
let {app} = getState();
return new SeckillService(app.host).fetchQueryRemindList(activityId, uid)
.then(json => {
dispatch(queryRemindListSuccess(json));
dispatch(getSeckillProductList(activityId));
})
let queryProductRemindList = (activityId, uid) => {
dispatch(queryProductAndRemindListRequest());
let {app, seckill} = getState();
let {queryProductList} = seckill;
Promise.all([
new SeckillService(app.host).fetchQueryProductList(activityId),
new SeckillService(app.host).fetchQueryRemindList(activityId, uid),
]).then(result => {
let productList = result[0];
let remindList = result[1];
productList = productAddFlag(productList, remindList);
dispatch(queryProductAndRemindListSuccess({productList,remindList}));
})
.catch(error => {
dispatch(queryRemindListFailure(error));
dispatch(getSeckillProductList(activityId));
dispatch(queryProductAndRemindListFailure(error));
});
}
ReactNative.NativeModules.YH_CommonHelper.uid()
.then(uid => {
queryRemindList(activityId, uid);
queryProductRemindList(activityId, uid);
})
.catch(error => {
ReactNative.NativeModules.YH_CommonHelper.login()
.then(uid => {
queryRemindList(activityId, uid);
})
.catch(error => {
});
dispatch(getSeckillProductList(activityId));
});
};
}
... ... @@ -276,9 +267,8 @@ export function addCancelUserReminder(method='app.seckill.addUserReminder', acti
productItem.remindFlag = remindFlag;
}
});
dispatch(updateSecKillProductList(queryProductList));
dispatch(addCancelUserReminderSuccess(okTip));
dispatch(updateSecKillProductList(queryProductList));
})
.catch(error => {
dispatch(addCancelUserReminderFailure(failTip));
... ... @@ -304,7 +294,7 @@ export function clickActivityTimeItem(activity) {
});
dispatch(updateSecKillProductVoList(queryActivityInfo.secKillProductVoList));
if (Date.now() < curActivity.startTime) {
dispatch(getSeckillRemindList(curActivityId));
dispatch(getSeckillProductRemindList(curActivityId));
} else {
dispatch(getSeckillProductList(curActivityId));
}
... ... @@ -325,39 +315,56 @@ export function clickProductItem(product) {
export function clickRemindBtn(product) {
return (dispatch, getState) => {
ReactNative.NativeModules.YH_CommonHelper.uid()
.then(uid => {
queryRemindList(uid);
})
.catch(error => {
ReactNative.NativeModules.YH_CommonHelper.login()
.then(uid => {
dispatch(getSeckillProductRemindList(product.activityId));
})
.catch(error => {
});
});
if (!product.secKillSku || product.secKillSku.length == 0) {
return;
}
let skn = product.secKillSku[0].productSkn;
let actionName,
action,
params,
on_off,
method;
let okTip,
failTip,
result;
// default
on_off = true;
action = 'go.addSecKill';
method = 'app.seckill.addUserReminder';
params = {
skn: skn,
startTime: product.startTime,
productName: product.productName,
};
okTip = '设置提醒成功,将在开抢3分钟前提醒';
failTip = '设置提醒失败';
if (product.remindFlag) {
on_off = false;
action = 'go.delSecKill';
okTip = '取消提醒成功';
failTip = '取消提醒失败';
method = 'app.seckill.cancelUserReminder';
}
let queryRemindList = (uid) => {
let {app, seckill} = getState();
let {queryProductList} = seckill;
if (!product.secKillSku || product.secKillSku.length == 0) {
return;
}
let skn = product.secKillSku[0].productSkn;
let actionName,
action,
params,
on_off,
method;
let okTip,
failTip,
result;
// default
on_off = true;
action = 'go.addSecKill';
method = 'app.seckill.addUserReminder';
params = {
skn: skn,
startTime: product.startTime,
productName: product.productName,
};
okTip = '设置提醒成功,将在开抢3分钟前提醒';
failTip = '设置提醒失败';
if (product.remindFlag) {
on_off = false;
action = 'go.delSecKill';
okTip = '取消提醒成功';
failTip = '取消提醒失败';
method = 'app.seckill.cancelUserReminder';
}
ReactNative.NativeModules.YH_SeckillHelper.remindTip({
method: action,
arguments: params,
... ... @@ -369,23 +376,10 @@ export function clickRemindBtn(product) {
dispatch(addCancelUserReminder(method, product.activityId, skn,uid, product.id, okTip, failTip));
})
.catch(error => {
dispatch(addCancelUserReminderFailure(error));
});
};
ReactNative.NativeModules.YH_CommonHelper.uid()
.then(uid => {
queryRemindList(uid);
})
.catch(error => {
ReactNative.NativeModules.YH_CommonHelper.login()
.then(uid => {
queryRemindList(uid);
})
.catch(error => {
});
});
}
}
... ... @@ -397,7 +391,7 @@ export function refreshList() {
if (curActivityId !== 0 && queryActivityInfo.secKillProductVoList) {
queryActivityInfo.secKillProductVoList.forEach((activityInfo, i) => {
if (activityInfo.get('activityId') === curActivityId) {
dispatch(getSeckillQueryActivity(activityInfo.get('startTime')));
dispatch(getSeckillQueryActivity(activityInfo.get('startTime')/1000));
}
});
} else {
... ... @@ -452,7 +446,6 @@ function productAddFlag(productList, remindList) {
product.over = true;
}
});
return productList;
}
... ... @@ -465,7 +458,6 @@ function parseActivityTimeLsit(json, focusTime=0) {
newActivityTimeList = secKillProductVoList.sort((a,b) => a.startTime - b.startTime);// orderBy startTime ASC
if (focusTime) {
focusTime = moment(focusTime, 'YYYYMMDDHHmmss').unix();
focusIndex = newActivityTimeList.findIndex(activityTimeItem=> activityTimeItem.startTime === focusTime);
if (focusIndex !== -1) {
... ...
... ... @@ -3,6 +3,7 @@
import {Record, List, Map} from 'immutable';
let InitialState = Record({
ptr: false, // 是否下拉刷新
contentCode: 'b78b32ed81b18dde8ac84fd33602b88b',
host:'http://api.yoho.cn',
isFetching: false,
... ...
... ... @@ -14,9 +14,9 @@ const {
QUERY_PRODUCT_LIST_SUCCESS,
QUERY_PRODUCT_LIST_FAILURE,
QUERY_REMIND_LIST_REQUEST,
QUERY_REMIND_LIST_SUCCESS,
QUERY_REMIND_LIST_FAILURE,
QUERY_PRODUCT_AND_REMIND_LIST_REQUEST,
QUERY_PRODUCT_AND_REMIND_LIST_SUCCESS,
QUERY_PRODUCT_AND_REMIND_LIST_FAILURE,
ADD_CANCEL_USER_REMINDER_REQUEST,
ADD_CANCEL_USER_REMINDER_SUCCESS,
... ... @@ -39,6 +39,7 @@ export default function seckillReducer(state=initialState, action) {
}
case QUERY_ACTIVITY_REQUEST: {
return state.set('isFetching', true)
.set('ptr', true)
.set('error', null);
}
case QUERY_ACTIVITY_SUCCESS: {
... ... @@ -48,14 +49,17 @@ export default function seckillReducer(state=initialState, action) {
return state.set('isFetching', false)
.set('queryActivityInfo', newQueryActivity)
.set('ptr', false)
.set('error', null);
}
case QUERY_ACTIVITY_FAILURE: {
return state.set('isFetching', false)
.set('ptr', false)
.set('error', action.payload);
}
case QUERY_PRODUCT_LIST_REQUEST: {
return state.set('isFetching', true)
.set('queryProductList',Immutable.fromJS([]))
.set('error', null);
}
case QUERY_PRODUCT_LIST_SUCCESS: {
... ... @@ -67,16 +71,19 @@ export default function seckillReducer(state=initialState, action) {
return state.set('isFetching', false)
.set('error', action.payload);
}
case QUERY_REMIND_LIST_REQUEST: {
case QUERY_PRODUCT_AND_REMIND_LIST_REQUEST: {
return state.set('isFetching', true)
.set('queryProductList', Immutable.fromJS([]))
.set('queryRemindList', Immutable.fromJS([]))
.set('error', null);
}
case QUERY_REMIND_LIST_SUCCESS: {
case QUERY_PRODUCT_AND_REMIND_LIST_SUCCESS: {
return state.set('isFetching', false)
.set('queryRemindList', Immutable.fromJS(action.payload))
.set('queryProductList', Immutable.fromJS(action.payload.productList))
.set('queryRemindList', Immutable.fromJS(action.payload.remindList))
.set('error', null);
}
case QUERY_REMIND_LIST_FAILURE: {
case QUERY_PRODUCT_AND_REMIND_LIST_FAILURE: {
return state.set('isFetching', false)
.set('error', action.payload);
}
... ...