Authored by 叶弯弯

完成发货入库模块。reviewed by shixiang。

... ... @@ -42,6 +42,7 @@ import userInitialState from './reducers/user/userInitialState';
import accountSettlementInitialState from './reducers/accountSettlement/accountSettlementInitialState';
import saleStatisticsInitialState from './reducers/saleStatistics/saleStatisticsInitialState';
import stockStatsInitialState from './reducers/stockStats/stockStatsInitialState';
import deliveryStatsInitialState from './reducers/deliveryStats/deliveryStatsInitialState';
import App from './containers/App';
... ... @@ -57,6 +58,7 @@ import AccountSettlementContainer from './containers/AccountSettlementContainer'
import AboutUsContainer from './containers/AboutUsContainer'
import StockStatsContainer from './containers/StockStatsContainer'
import SaleStatisticsContainer from './containers/SaleStatisticsContainer'
import DeliveryStatsContainer from './containers/DeliveryStatsContainer'
import NavBar from './components/NavBar';
import TabIcon from './containers/TabIcon';
... ... @@ -80,6 +82,7 @@ function getInitialState() {
actStmt: (new accountSettlementInitialState),
saleStats: (new saleStatisticsInitialState()),
stockStats: (new stockStatsInitialState()),
deliveryStats: (new deliveryStatsInitialState()),
};
return _initState;
}
... ... @@ -161,9 +164,9 @@ export default function native(platform) {
/>
<Scene
key='AccountSettlement'
component={AccountSettlementContainer}
title='对账结算'
key='DeliveryStats'
component={DeliveryStatsContainer}
title='发货入库'
hideNavBar={false}
initial={false}
navBar={NavBar}
... ... @@ -183,6 +186,17 @@ export default function native(platform) {
/>
<Scene
key='AccountSettlement'
component={AccountSettlementContainer}
title='对账结算'
hideNavBar={false}
initial={false}
navBar={NavBar}
titleStyle={styles.navTitle}
type='push'
/>
<Scene
key='AboutUs'
component={AboutUsContainer}
title='关于我们'
... ...
'use strict';
import React from 'react-native';
let {
Component,
View,
Text,
StyleSheet,
Dimensions,
Platform,
DatePickerAndroid,
TouchableHighlight,
Image,
} = React;
export default class DatePicker extends Component {
static propTypes = {
containerStyle: View.propTypes.style,
};
constructor(props) {
super(props);
this._showDatePicker = this._showDatePicker.bind(this);
}
render() {
return (
<View style={[styles.container, this.props.containerStyle]}>
<TouchableHighlight underlayColor={'white'}
onPress={() => {this._showDatePicker(this.props.currentStartDate, '2000-1-1', this.props.currentEndDate, true)}}>
<View style={styles.dateContainer}>
<Text style={styles.dateText}>{this.props.currentStartDate}</Text>
<Image source={require('../images/down.png')}/>
</View>
</TouchableHighlight>
<Text style={styles.middleText}></Text>
<TouchableHighlight underlayColor={'white'}
onPress={() => {this._showDatePicker(this.props.currentEndDate, this.props.currentStartDate, this.props.maxDate, false)}}>
<View style={styles.dateContainer}>
<Text style={styles.dateText}>{this.props.currentEndDate}</Text>
<Image source={require('../images/down.png')}/>
</View>
</TouchableHighlight>
</View>
);
}
async _showDatePicker(currentDate, minDate, maxDate, ifStartDate) {
let currentDateArr = currentDate.split('-');
let minDateArr = minDate.split('-');
let maxDateArr = maxDate.split('-');
if (Platform.OS === 'android') {
try {
const {action, year, month, day} = await DatePickerAndroid.open({
date: new Date(currentDateArr[0], (currentDateArr[1] - 1), currentDateArr[2]),
minDate: new Date(minDateArr[0], (minDateArr[1] - 1), minDateArr[2]),
maxDate: new Date(maxDateArr[0], (maxDateArr[1] - 1), maxDateArr[2]),
});
if (action !== DatePickerAndroid.dismissedAction) {
let pickedDate = year + '-' + (month + 1) + '-' + day;
this.props.newDatePicked(pickedDate, ifStartDate);
}
} catch ({code, message}) {
}
} else {
}
}
}
let {width, height} = Dimensions.get('window');
let styles = StyleSheet.create({
container: {
width,
height: 45,
backgroundColor: 'white',
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
},
middleText: {
marginLeft: 15,
marginRight: 15,
color: '#444444',
fontSize: 14,
},
dateText: {
color: '#444444',
fontSize: 14,
paddingRight: 5,
},
dateContainer: {
flex: 1,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
}
});
... ...
'use strict';
import React, {Component} from 'react';
import PlainTextSection from './PlainTextSection';
import Placeholder from './Placeholder';
import DatePicker from './DatePicker';
import FixedHeaderList from './FixedHeaderList';
import {
StyleSheet,
View,
} from 'react-native';
export default class DeliveryStats extends Component {
constructor(props) {
super (props);
}
render() {
return (
<View style={styles.container}>
<DatePicker currentStartDate={this.props.currentStartDate}
currentEndDate={this.props.currentEndDate}
maxDate={this.props.maxDate}
newDatePicked={this.props.newDatePicked}/>
<Placeholder />
<PlainTextSection content={this.props.section2} />
<Placeholder />
<FixedHeaderList content={this.props.content}
header={this.props.header}/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
});
... ...
'use strict';
import React from 'react-native';
let {
Component,
View,
Text,
Image,
ListView,
TouchableHighlight,
Dimensions,
StyleSheet,
} = React;
export default class FixedHeaderList extends Component {
// static propTypes = {
// content: React.PropTypes.arrayOf(
// React.PropTypes.shape({
// type: React.PropTypes.string,
// thumb: React.PropTypes.number,
// title: React.PropTypes.string,
// })
// ),
// onPress: React.PropTypes.func,
// };
constructor(props) {
super(props);
this._renderRow = this._renderRow.bind(this);
this._renderHeader = this._renderHeader.bind(this);
this.ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
// this.dataSource = ds.cloneWithRows(this.props.content);
this.headers = [];
for (let i = 0; i < this.props.header.length; i++) {
this.headers.push(<Text style={styles.headerText}>{this.props.header[i]}</Text>);
if (i !== (this.props.header.length - 1)) {
this.headers.push(<View style={{width: 1, height: 14, backgroundColor: '#e5e5e5'}}/>);
}
}
}
_renderRow(rowData, sectionID, rowID) {
return (
<TouchableHighlight onPress={() => {}} underlayColor={'white'} >
<View style={styles.row}>
<View style={styles.firstColumn}>
<Text style={styles.blackText}>{rowData.id}</Text>
<Text style={styles.blackText}>{rowData.date}</Text>
</View>
<Text style={styles.redText}>{rowData.deliveryNum}</Text>
<Text style={styles.redText}>{rowData.deliveryAmount}</Text>
</View>
</TouchableHighlight>
);
}
_renderHeader() {
return (
<View key={'listHeader'} style={styles.headerContainer}>
{this.headers}
</View>
);
}
render() {
return (
<ListView
style={styles.container}
dataSource={this.ds.cloneWithRows(this.props.content)}
renderRow={this._renderRow}
renderSeparator={(sectionID, rowID) => <View key={`${sectionID}-${rowID}`} style={styles.separator}/>}
renderHeader={this._renderHeader}
enableEmptySections={true}
/>
);
}
}
let {width, height} = Dimensions.get('window');
let styles = StyleSheet.create({
container: {
flex: 1,
},
separator: {
height: 1,
},
headerContainer: {
flexDirection: 'row',
backgroundColor: 'white',
height: 45,
alignItems: 'center',
borderBottomColor: '#F0F0F0',
borderBottomWidth: 1,
},
headerText: {
fontSize: 14,
color: '#444444',
textAlign: 'center',
flex: 1,
},
row: {
flexDirection: 'row',
paddingTop: 15,
paddingBottom: 15,
alignItems: 'center',
backgroundColor: 'white',
},
firstColumn: {
flex: 1,
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
},
blackText: {
fontSize: 14,
color: '#444444',
textAlign: 'center',
},
redText: {
fontSize: 14,
color: '#D0021B',
flex: 1,
textAlign: 'center',
}
});
... ...
... ... @@ -56,7 +56,7 @@ export default class StockStats extends Component {
dataSource={this.ds.cloneWithRows(this.props.section3)}
renderRow={this._renderRow}
renderSeparator={(sectionID, rowID) => <View key={`${sectionID}-${rowID}`} style={styles.separator}/>}
onEndReachedThreshold={-50}
onEndReachedThreshold={-10}
onEndReached={this.props.requestData}
enableEmptySections={true} />
</View>
... ... @@ -73,7 +73,7 @@ const styles = StyleSheet.create({
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
height: 50,
height: 45,
backgroundColor: 'white',
},
date: {
... ...
... ... @@ -61,10 +61,17 @@ export default keyMirror({
STOCK_STATS_REQUEST: null,
STOCK_STATS_SUCCESS: null,
STOCK_STATS_FAILURE: null,
SALE_STATS_REQUEST: null,
SALE_STATS_SUCCESS: null,
SALE_STATS_FAILURE: null,
DELIVERY_STATS_REQUEST: null,
DELIVERY_STATS_SUCCESS: null,
DELIVERY_STATS_FAILURE: null,
CHOOSE_DELIVERY_START_DATE: null,
CHOOSE_DELIVERY_END_DATE: null,
/*
GET_PROFILE_REQUEST: null,
GET_PROFILE_SUCCESS: null,
... ...
'use strict';
import React, { Component } from 'react';
import DeliveryStats from '../components/DeliveryStats'
import {
StyleSheet,
View,
Text,
ListView,
Dimensions,
Platform,
} from 'react-native';
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
import {Map} from 'immutable';
import * as deliveryStatsActions from '../reducers/deliveryStats/deliveryStatsActions';
import {getLastDay} from '../utils/dateTool';
const actions = [
deliveryStatsActions,
];
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
};
}
export default class DeliveryStatsContainer extends Component {
constructor(props) {
super(props);
this._requestData = this._requestData.bind(this);
}
componentDidMount() {
this.props.actions.requestData();
}
_requestData() {
this.props.actions.requestData();
}
render() {
let section2 = [
{
top: '到货入库总数量',
bottom: `${this.props.deliveryStats.sum}`,
},
{
top: '到货入库总金额(元)',
bottom: `${this.props.deliveryStats.totalAmount}`,
}
];
let header = [
'单号/时间', '发货入库数量', '发货入库总金额(元)'
];
return (
<View style={styles.container}>
<DeliveryStats
currentStartDate={this.props.deliveryStats.startDay}
currentEndDate={this.props.deliveryStats.endDay}
maxDate={getLastDay()}
newDatePicked={this.props.actions.newDatePicked}
section2={section2}
content={this.props.deliveryStats.jsonData.toJS()}
header={header}
/>
</View>
);
}
}
let {width, height} = Dimensions.get('window');
let navbarHeight = (Platform.OS === 'android') ? 50 : 64;
let styles = StyleSheet.create({
container: {
flex: 1,
top: navbarHeight,
height: height - navbarHeight,
},
});
export default connect(mapStateToProps, mapDispatchToProps)(DeliveryStatsContainer);
... ...
... ... @@ -93,6 +93,7 @@ let navbarHeight = (Platform.OS === 'android') ? 50 : 64;
let styles = StyleSheet.create({
container: {
flex: 1,
top: navbarHeight,
height: height - navbarHeight,
},
... ...
'use strict';
import Request from '../../services/Request';
import DeliveryStatsService from '../../services/HomeService';
const {
DELIVERY_STATS_REQUEST,
DELIVERY_STATS_SUCCESS,
DELIVERY_STATS_FAILURE,
CHOOSE_DELIVERY_START_DATE,
CHOOSE_DELIVERY_END_DATE,
} = require('../../constants/actionTypes').default;
export function chooseStartDate(startDay) {
return {
type: CHOOSE_DELIVERY_START_DATE,
payload: startDay,
}
}
export function chooseEndDate(endDay) {
return {
type: CHOOSE_DELIVERY_END_DATE,
payload: endDay,
}
}
export function newDatePicked(pickedDate, ifStartDate) {
return ifStartDate ? chooseStartDate(pickedDate) : chooseEndDate(pickedDate);
}
export function request() {
return {
type: DELIVERY_STATS_REQUEST,
}
}
export function success(json) {
return {
type: DELIVERY_STATS_SUCCESS,
payload: json,
}
}
export function failure(error) {
return {
type: DELIVERY_STATS_FAILURE,
payload: error,
}
}
export function requestData() {
// return dispatch => {
// dispatch(request());
// return new DeliveryStatsService()
// .deliveryStatsData()
// .then(json => {
// dispatch(success(json));
// })
// .catch(error => {
// dispatch(failure(error));
// })
// };
return success(testStockStatsData);
}
let testStockStatsData = {
sum: '100',
totalAmount: '100000.00',
list: [
{
id: '1111',
date: '2016-05-06',
deliveryNum: '222222',
deliveryAmount: '1111.00',
},
{
id: '1111',
date: '2016-05-06',
deliveryNum: '222222',
deliveryAmount: '1111.00',
},
{
id: '1111',
date: '2016-05-06',
deliveryNum: '222222',
deliveryAmount: '1111.00',
},
{
id: '1111',
date: '2016-05-06',
deliveryNum: '222222',
deliveryAmount: '1111.00',
},
{
id: '1111',
date: '2016-05-06',
deliveryNum: '222222',
deliveryAmount: '1111.00',
},
{
id: '1111',
date: '2016-05-06',
deliveryNum: '222222',
deliveryAmount: '1111.00',
},
{
id: '1111',
date: '2016-05-06',
deliveryNum: '222222',
deliveryAmount: '1111.00',
},
{
id: '0000',
date: '2016-05-06',
deliveryNum: '222222',
deliveryAmount: '1111.00',
},
]
}
... ...
'use strict';
import {List, Record} from 'immutable';
import {getLastDay} from '../../utils/dateTool';
let InitialState = Record({
error: null,
isFetching: false,
pageCount: 0,
startDay: getLastDay(),
endDay: getLastDay(),
sum: '0',
totalAmount: '0',
jsonData: List([]),
});
export default InitialState;
... ...
'use strict';
import DeliveryStatsInitialState from './deliveryStatsInitialState'
import Immutable, {List, Record} from 'immutable';
const {
DELIVERY_STATS_REQUEST,
DELIVERY_STATS_SUCCESS,
DELIVERY_STATS_FAILURE,
CHOOSE_DELIVERY_START_DATE,
CHOOSE_DELIVERY_END_DATE,
} = require('../../constants/actionTypes').default;
const initialState = new DeliveryStatsInitialState;
export default function deliveryStatsReducer(state = initialState, action) {
if (!(state instanceof DeliveryStatsInitialState)) return initialState.merge(state);
switch (action.type) {
case DELIVERY_STATS_REQUEST: {
let nextState = state.set('isFetching', true).set('error', null);
return nextState;
}
case DELIVERY_STATS_SUCCESS: {
const {jsonData} = state;
// let origin = jsonData.toJS();
let data = [...action.payload.list];
// let newPageCount = action.payload.list ? state.pageCount + 1 : state.pageCount;
let nextState = state.set('isFetching',false)
.set('sum', action.payload.sum)
.set('totalAmount', action.payload.totalAmount)
.set('jsonData', List(data));
// .set('pageCount', newPageCount)
return nextState;
}
case DELIVERY_STATS_FAILURE: {
let nextState = state.set('isFetching', false)
.set('error', action.playload);
return nextState;
}
case CHOOSE_DELIVERY_START_DATE: {
let nextState = state.set('startDay', action.payload);
return nextState;
}
case CHOOSE_DELIVERY_END_DATE: {
let nextState = state.set('endDay', action.payload);
return nextState;
}
}
return state;
}
... ...
... ... @@ -18,6 +18,7 @@ import user from './user/userReducer';
import stockStats from './stockStats/stockStatsReducer';
import actStmt from './accountSettlement/accountSettlementReducer';
import saleStats from './saleStatistics/saleStatisticsReducer';
import deliveryStats from './deliveryStats/deliveryStatsReducer';
import { combineReducers } from 'redux';
... ... @@ -35,7 +36,8 @@ const rootReducer = combineReducers({
user,
actStmt,
stockStats,
saleStats
saleStats,
deliveryStats,
});
export default rootReducer;
... ...
... ... @@ -45,8 +45,8 @@ export function requestData() {
}
let testStockStatsData = {
sum: 100,
totalAmount: 100000.00,
sum: '100',
totalAmount: '100000.00',
list: [
{
brand: 'vans',
... ... @@ -120,141 +120,5 @@ let testStockStatsData = {
stockNum: '77',
thumb: 'https://facebook.github.io/react/img/logo_og.png',
},
{
brand: 'vans',
product: 'dddddddddddddddddddddddd 超清来袭ddddddddddd',
vendor: '222222',
sku: '111111111',
importPrice: '222',
stockNum: '78',
thumb: 'https://facebook.github.io/react/img/logo_og.png',
},
{
brand: 'vans',
product: 'dddddddddddddddddddddddd 超清来袭ddddddddddd',
vendor: '222222',
sku: '111111111',
importPrice: '222',
stockNum: '79',
thumb: 'https://facebook.github.io/react/img/logo_og.png',
},
{
brand: 'vans',
product: 'dddddddddddddddddddddddd 超清来袭ddddddddddd',
vendor: '222222',
sku: '111111111',
importPrice: '222',
stockNum: '80',
thumb: 'https://facebook.github.io/react/img/logo_og.png',
},
{
brand: 'vans',
product: 'dddddddddddddddddddddddd 超清来袭ddddddddddd',
vendor: '222222',
sku: '111111111',
importPrice: '222',
stockNum: '81',
thumb: 'https://facebook.github.io/react/img/logo_og.png',
},
{
brand: 'vans',
product: 'dddddddddddddddddddddddd 超清来袭ddddddddddd',
vendor: '222222',
sku: '111111111',
importPrice: '222',
stockNum: '82',
thumb: 'https://facebook.github.io/react/img/logo_og.png',
},
{
brand: 'vans',
product: 'dddddddddddddddddddddddd 超清来袭ddddddddddd',
vendor: '222222',
sku: '111111111',
importPrice: '222',
stockNum: '83',
thumb: 'https://facebook.github.io/react/img/logo_og.png',
},
{
brand: 'vans',
product: 'dddddddddddddddddddddddd 超清来袭ddddddddddd',
vendor: '222222',
sku: '111111111',
importPrice: '222',
stockNum: '84',
thumb: 'https://facebook.github.io/react/img/logo_og.png',
},
{
brand: 'vans',
product: 'dddddddddddddddddddddddd 超清来袭ddddddddddd',
vendor: '222222',
sku: '111111111',
importPrice: '222',
stockNum: '85',
thumb: 'https://facebook.github.io/react/img/logo_og.png',
},
{
brand: 'vans',
product: 'dddddddddddddddddddddddd 超清来袭ddddddddddd',
vendor: '222222',
sku: '111111111',
importPrice: '222',
stockNum: '86',
thumb: 'https://facebook.github.io/react/img/logo_og.png',
},
{
brand: 'vans',
product: 'dddddddddddddddddddddddd 超清来袭ddddddddddd',
vendor: '222222',
sku: '111111111',
importPrice: '222',
stockNum: '87',
thumb: 'https://facebook.github.io/react/img/logo_og.png',
},
{
brand: 'vans',
product: 'dddddddddddddddddddddddd 超清来袭ddddddddddd',
vendor: '222222',
sku: '111111111',
importPrice: '222',
stockNum: '88',
thumb: 'https://facebook.github.io/react/img/logo_og.png',
},
{
brand: 'vans',
product: 'dddddddddddddddddddddddd 超清来袭ddddddddddd',
vendor: '222222',
sku: '111111111',
importPrice: '222',
stockNum: '89',
thumb: 'https://facebook.github.io/react/img/logo_og.png',
},
{
brand: 'vans',
product: 'dddddddddddddddddddddddd 超清来袭ddddddddddd',
vendor: '222222',
sku: '111111111',
importPrice: '222',
stockNum: '90',
thumb: 'https://facebook.github.io/react/img/logo_og.png',
},
{
brand: 'vans',
product: 'dddddddddddddddddddddddd 超清来袭ddddddddddd',
vendor: '222222',
sku: '111111111',
importPrice: '222',
stockNum: '91',
thumb: 'https://facebook.github.io/react/img/logo_og.png',
},
{
brand: 'vans',
product: 'dddddddddddddddddddddddd 超清来袭ddddddddddd',
vendor: '222222',
sku: '111111111',
importPrice: '222',
stockNum: '92',
thumb: 'https://facebook.github.io/react/img/logo_og.png',
},
]
}
... ...
... ... @@ -60,6 +60,21 @@ export default class UserService {
throw(error);
})
}
async deliveryStatsData() {
return await this.api.get({
url: '/',
body: {
}
})
.then((json) => {
return json;
})
.catch((error) => {
throw(error);
})
}
}
... ...
'use strict'
export function getLastDay() {
let date = new Date();
let lastDay = date.getFullYear() + '-' + (date.getMonth() + 1) + '-' + (date.getDate() - 1);
return lastDay;
}
... ...