Commit 36025b34 by peii

单个结算单

parent b745639c
{
"name": "BoneHouse_Business_APP",
"displayName": "BoneHouse_Business_APP"
"name": "BoneHouse_Hospital_APP",
"displayName": "BoneHouse_Hospital_APP"
}
\ No newline at end of file
......@@ -28,6 +28,9 @@ import BarCodePage from './containers/common/BarCodePage';
// 结算
import Settlement from '../src/pages/settlement/index';
import SettlementCollection from '../src/pages/settlement/collection';
import SettlementDetail from '../src/pages/settlement/detail';
import SettlementSaleDetail from '../src/pages/settlement/saleDetail';
import SettlementReject from '../src/pages/settlement/reject';
......@@ -54,7 +57,10 @@ const Router = createAppContainer(createStackNavigator({
SubSuccPage: {screen: SubSuccPage},
BarCodePage: {screen: BarCodePage},
Settlement: {screen: Settlement},
SettlementCollection: {screen: SettlementCollection},
SettlementReject: {screen: SettlementReject},
SettlementDetail: {screen: SettlementDetail},
SettlementSaleDetail: {screen: SettlementSaleDetail},
}, {
navigationOptions: {
gesturesEnabled: true
......
......@@ -71,7 +71,7 @@ class HomePage extends Component {
MOBILE_DISTRIBUTION_SETTLEMENT_GATHER: {
icon: require('../../images/quick_order.png'),
title: '分销-结算汇总',
page: 'QuickOrderPage',
page: 'SettlementCollection',
},
MOBILE_DISTRIBUTION_INVOICE_GATHER: {
icon: require('../../images/quick_order.png'),
......
@import '../../assets/styles/base.styl'
@import '../../assets/styles/variable.styl'
size = 18px
.checkbox
@extend .row
@extend .center
&-img
width size
height size
&-box
border-width 1px
border-color #ccc
width size
height @width
border-radius 2px
&-text
font-size 16px
padding-left 10px
color #333
\ No newline at end of file
/*
* @FilePath: /BoneHouse_Business_APP/src/components/checkbox/checkbox.tsx
* @Author: peii
* @Date: 2021-12-20 17:29:00
* @LastEditTime: 2021-12-20 18:35:15
* @LastEditors: peii
* @Vision: 1.0
* @Description: 多选框
*/
// @ts-nocheck
import React, { useState, useEffect } from 'react'
import { View, Text, TouchableOpacity, Image } from 'react-native'
import { isBlank, g } from '../../utils/utils'
import styles from './checkbox.styl'
export const Checkbox = ({ checked, indeterminate, onChange, activeOpacity = 0.5, children, style }) => {
const [check, setCheck] = useState(checked)
const [indeter, setIndeter] = useState(indeterminate)
useEffect(() => {
setCheck(checked)
setIndeter(indeterminate)
}, [checked, indeterminate])
const pressHandler = () => {
if (check) {
setCheck(false)
setIndeter(false)
} else {
setCheck(true)
setIndeter(false)
}
onChange && onChange(!check)
}
return (
<TouchableOpacity style={[g(styles, 'checkbox'), style]} activeOpacity={activeOpacity} onPress={pressHandler}>
{check ? (
<Image source={require('../../assets/images/cor_blue.png')} style={g(styles, 'checkbox-img')} />
) : indeter ? (
<Image source={require('../../assets/images/indeterminate.png')} style={g(styles, 'checkbox-img')} />
) : (
<View style={g(styles, 'checkbox-box')}></View>
)}
{children && <Text style={g(styles, 'checkbox-text')}>{children}</Text>}
</TouchableOpacity>
)
}
......@@ -11,6 +11,7 @@
width 100%
height 100%
padding 30px 0 40px
z-index 211
&-bd
width 100%
......
......@@ -73,6 +73,7 @@ export function TopModal(props: IModalProps) {
action,
headerHeight,
mask = true,
maskClickable = true,
contentHeight = 400,
initTop = 0,
} = props
......@@ -100,15 +101,15 @@ export function TopModal(props: IModalProps) {
if (!visible) return <></>
return (
<Animated.View
style={[g(styles, 'modal'), { width, height: modalHeight, opacity: opacity, top: initTop }]}
>
<Animated.View style={[g(styles, 'modal'), { width, height: modalHeight, opacity: opacity, top: initTop }]}>
{!!mask && (
<TouchableOpacity
style={[g(styles, 'modal-mask'), { top: contentHeight - hasNavHeight }]}
activeOpacity={1}
onPress={() => {
if (maskClickable) {
animated(top, -contentHeight, opacity, 0, onClose)
}
}}
></TouchableOpacity>
)}
......
......@@ -8,13 +8,13 @@
z-index 100
&-bd
// padding 0 20px
height 310px
padding-bottom 20px
height 350px
padding-bottom 48px
z-index 100
overflow hidden
&__inner
padding 20px
padding 15px
z-index 100
&-item
......@@ -26,7 +26,7 @@
&-ft
@extend .row
position absolute
bottom -40px
bottom 0px
width 100%
height 48px
background-color #fff
......
......@@ -2,7 +2,7 @@
* @FilePath: /BoneHouse_Business_APP/src/components/modals/filter/filter.tsx
* @Author: peii
* @Date: 2021-12-19 10:49:42
* @LastEditTime: 2021-12-19 17:37:05
* @LastEditTime: 2021-12-20 15:06:08
* @LastEditors: peii
* @Vision: 1.0
* @Description: 过滤弹窗
......@@ -18,6 +18,7 @@ import { FieldType } from '../../../enums'
import { TopModal } from '../base/top'
import FormInput from '../../form/input'
import FormSelect from '../../form/select'
import FormRadio from '../../form/radio'
import styles from './filter.styl'
type IProps = {
......@@ -37,6 +38,7 @@ type IState = {
const FormComponents = {
[FieldType.TEXT]: FormInput,
[FieldType.SELECT]: FormSelect,
[FieldType.RADIO]: FormRadio,
}
export default class Filter extends React.Component<IProps, IState> {
......@@ -57,7 +59,8 @@ export default class Filter extends React.Component<IProps, IState> {
const { action, modal } = this.state
const { visible, filterItems, data } = this.props
return (
<TopModal visible={visible} action={action} onClose={this.props.onClose} initTop={0}>
<>
<TopModal visible={visible} action={action} onClose={this.props.onClose} initTop={0} maskClickable={false}>
<View style={g(styles, 'filter-bd')}>
<ScrollView style={g(styles, 'filter-bd__inner')}>
{filterItems.map(item => {
......@@ -89,9 +92,9 @@ export default class Filter extends React.Component<IProps, IState> {
</TouchableOpacity>
</View>
</View>
{modal}
</TopModal>
{modal}
</>
)
}
}
/*
* @FilePath: /BoneHouse_Business_APP/src/pages/settlement/collection.tsx
* @Author: peii
* @Date: 2021-12-18 16:33:37
* @LastEditTime: 2021-12-20 17:09:34
* @LastEditors: peii
* @Vision: 1.0
* @Description: 结算汇总
*/
// @ts-nocheck
import React, { useEffect, useRef, useState, createRef } from 'react'
import { View, Text, TouchableOpacity, FlatList, Image } from 'react-native'
import { connect } from 'react-redux'
import * as R from 'ramda'
import { INavigation } from 'navigation'
import { IFormField } from 'bonehouse'
import Loading from '../../../app/containers/common/LodingModel'
import Header from '../../components/header/header'
import Resolution from '../../components/common/Resolution'
import FilterModal from './components/filter'
import SettlementList from './components/list'
import { isBlank, g } from '../../utils/utils'
import { FieldType } from '../../enums'
import api from '../../services/api'
import styles from './index.styl'
type IProps = {
navigation: INavigation
}
type IState = {
modalVisible: boolean
data: any[]
loading: boolean
otherFilterItems: IFormField[]
}
class SettlementCollection extends React.Component<IProps, IState> {
constructor(props: IProps) {
super(props)
this.toggleModalVisible = this.toggleModalVisible.bind(this)
this.getData = this.getData.bind(this)
}
state = {
modalVisible: false,
data: [],
loading: false,
otherFilterItems: [
{
field: 'settlement_number',
label: '结算单号',
type: FieldType.TEXT,
},
],
}
componentDidMount() {
this.toggleModalVisible()
}
toggleModalVisible(): void {
this.setState({ modalVisible: !this.state.modalVisible })
}
/**
* @description: 请求结算列表信息
* @param {*}
* @return {*}
*/
async getData(args): void {
this.setState({ loading: true })
const res = await api.getSettlements(args)
this.setState({ loading: false })
if (res.error_code !== 0) return
const data = R.propOr([], 'data')(res)
this.setState({ data })
}
render() {
const title = this.props.navigation.getParam('title', '骨科智慧仓')
const { modalVisible, data, loading, otherFilterItems } = this.state
return (
<View style={g(styles, 'container')}>
<Resolution.FixWidthView>
<Header
title={title}
backCallback={() => {
this.props.navigation.goBack()
}}
>
<TouchableOpacity style={g(styles, 'filter')} activeOpacity={0.8} onPress={this.toggleModalVisible}>
<Image source={require('../../assets/images/filter_icon.png')} style={g(styles, 'filter-icon')} />
</TouchableOpacity>
</Header>
<View style={g(styles, 'body')}>
{/* 过滤弹窗 */}
<FilterModal
visible={modalVisible}
onClose={this.toggleModalVisible}
searchHandler={this.getData}
otherFilterItems={otherFilterItems}
/>
{loading ? <Loading show={loading} /> : <SettlementList data={data} {...this.props} />}
</View>
</Resolution.FixWidthView>
</View>
)
}
}
const mapStateToProps = state => ({})
const mapDispatchToProps = dispatch => ({})
export default connect(mapStateToProps, mapDispatchToProps)(SettlementCollection)
......@@ -2,7 +2,7 @@
* @FilePath: /BoneHouse_Business_APP/src/pages/settlement/components/filter.tsx
* @Author: peii
* @Date: 2021-12-19 10:49:42
* @LastEditTime: 2021-12-19 18:26:15
* @LastEditTime: 2021-12-20 14:59:22
* @LastEditors: peii
* @Vision: 1.0
* @Description: 过滤弹窗
......@@ -26,6 +26,7 @@ type IProps = {
sysProfiles: {
OBS_SHOW_ORG_FLAG: string
}
otherFilterItems: IFromField[]
}
type IState = {
......@@ -71,8 +72,9 @@ class FilterModal extends React.Component<IProps, IState> {
componentDidMount() {
this.setFieldItems()
setTimeout(() => {
this.getCustomers()
}, 0)
}
onClose() {
......@@ -98,9 +100,11 @@ class FilterModal extends React.Component<IProps, IState> {
*/
setFieldItems() {
let { filterItems, data } = this.state
const { userInfo, sysProfiles } = this.props
const { userInfo, sysProfiles, otherFilterItems = [] } = this.props
const showOrg = sysProfiles.OBS_SHOW_ORG_FLAG !== 'N'
data.org_code = userInfo.department_code
data.org_code = userInfo.department_code && R.take(3, userInfo.department_code)
filterItems = R.concat(filterItems)(otherFilterItems)
this.setState({ filterItems, data })
if (!showOrg) return
......@@ -113,7 +117,7 @@ class FilterModal extends React.Component<IProps, IState> {
}
filterItems = R.insert(1, item, filterItems)
this.getOrganizations()
this.setState({ filterItems })
this.setState({ filterItems, data })
}
/**
......@@ -131,7 +135,7 @@ class FilterModal extends React.Component<IProps, IState> {
R.map(
R.applySpec({
value: R.prop('org_code'),
label: R.prop('org_name'),
label: R.compose(R.take(3), R.prop('org_name')),
}),
),
R.pathOr([], ['data', 'organizations']),
......@@ -155,8 +159,16 @@ class FilterModal extends React.Component<IProps, IState> {
const item = getFormItem(filterItems, 'customer_code')
// item.options = R.
// TODO:
item.options = R.compose(
R.map(
R.applySpec({
value: R.prop('customer_code'),
label: R.prop('customer_name'),
}),
),
R.pathOr([], ['data', 'customers']),
)(res)
this.setState({ filterItems })
}
/**
......
......@@ -4,15 +4,22 @@
.list
width 100%
padding 20px
margin-bottom 25px
.item
background-color #fff
padding 15px
margin-bottom 15px
&-line
@extend .row
justify-content space-between
align-items center
&-text
font-size 16px
line-height 28px
\ No newline at end of file
line-height 22px
margin-bottom 6px
&-left
width 70%
......@@ -2,7 +2,7 @@
* @FilePath: /BoneHouse_Business_APP/src/pages/settlement/components/list.tsx
* @Author: peii
* @Date: 2021-12-19 10:44:15
* @LastEditTime: 2021-12-19 18:04:24
* @LastEditTime: 2021-12-20 15:35:10
* @LastEditors: peii
* @Vision: 1.0
* @Description: 汇总列表
......@@ -11,18 +11,32 @@
import React, { Component } from 'react'
import { View, Text, TouchableOpacity, FlatList, Image } from 'react-native'
import { INavigation } from 'navigation'
import * as R from 'ramda'
import dayjs from 'dayjs'
import { isBlank, g } from '../../../utils/utils'
import styles from './list.styl'
type IProps = {
data: any[]
navigation: INavigation
}
class SettlementList extends Component<IProps> {
constructor(props) {
super(props)
this.renderItem = this.renderItem.bind(this)
this.itemPressHandler = this.itemPressHandler.bind(this)
}
/**
* @description:
* @param {*} item
* @return {*}
*/
itemPressHandler(item) {
console.log(item)
this.props.navigation.navigate('SettlementDetail', { order: item })
}
/**
......@@ -32,25 +46,29 @@ class SettlementList extends Component<IProps> {
*/
renderItem({ item, index }) {
return (
<View style={g(styles, 'item')}>
<TouchableOpacity style={g(styles, 'item')} activeOpacity={0.8} onPress={() => this.itemPressHandler(item)}>
<View style={g(styles, 'item-line')}>
<Text style={g(styles, 'item-text')}>{item.settlement_number}</Text>
<Text style={g(styles, 'item-text')}>{item.settled_date}</Text>
<Text style={g(styles, 'item-text')}>
{item.settled_date && dayjs(item.settled_date).format('YYYY-MM-DD')}
</Text>
</View>
<View style={g(styles, 'item-line')}>
<View style={g(styles, 'item-left')}>
<Text style={g(styles, 'item-text')}>结算总数量: {item.settlement_quantity}</Text>
<Text style={g(styles, 'item-text')}>结算总金额: {item.settlement_price}</Text>
<Text style={g(styles, 'item-text', 'item-left-text')}>结算总数量: {item.sum_quantity}</Text>
<Text style={g(styles, 'item-text', 'item-left-text')}>结算总金额: {item.sum_settlement_amount}</Text>
</View>
<View style={g(styles, 'item-right')}></View>
<Text style={g(styles, 'item-text__rigth')}>{item.header_status}</Text>
</View>
<View style={g(styles, 'item-line')}>
<Text style={g(styles, 'item-text')}>备注: {item.remark}</Text>
<Text style={g(styles, 'item-text')}>{item.customer_name}</Text>
<Text style={g(styles, 'item-text')}>{item.status || '未确定'}</Text>
<Text style={g(styles, 'item-text', 'item-left-text')}>客户: {item.customer_name}</Text>
</View>
<View style={g(styles, 'item-line')}>
<Text style={g(styles, 'item-text', 'item-left-text')}>备注: {item.header_remark}</Text>
</View>
</TouchableOpacity>
)
}
......
@import '../../assets/styles/base.styl'
@import '../../assets/styles/variable.styl'
.container
background-color home_background_color
.body
flex 1
&-hd
@extend .middle
padding-left 20px
padding-right 20px
height 40px
background-color #fff
&__text
font-size 16px
&-bd
flex 1
padding 15px
.card
@extend .row
background-color #fff
padding 15px
&-info
flex 1
&-line
@extend .row
&-text
font-size 16px
margin-bottom 5px
&-key
width 60px
&-select
@extend .middle
align-items flex-end
width 60px
&__checkbox
width 100%
height 100%
justify-content flex-end
/*
* @FilePath: /BoneHouse_Business_APP/src/pages/settlement/detail.tsx
* @Author: peii
* @Date: 2021-12-20 15:27:45
* @LastEditTime: 2021-12-20 18:31:55
* @LastEditors: peii
* @Vision: 1.0
* @Description: 结算详情
*/
// @ts-nocheck
import React from 'react'
import { View, Text, FlatList, TouchableOpacity, Image } from 'react-native'
import { connect } from 'react-redux'
import * as R from 'ramda'
import { INavigation } from 'navigation'
import Loading from '../../../app/containers/common/LodingModel'
import { Checkbox } from '../../components/checkbox/checkbox'
import Header from '../../components/header/header'
import Resolution from '../../components/common/Resolution'
import { isBlank, g } from '../../utils/utils'
import api from '../../services/api'
import styles from './detail.styl'
type IProps = {
navigation: INavigation
}
type IState = {}
class Detail extends React.Component<IProps, IState> {
constructor(props: IProps) {
super(props)
this.renderHeader = this.renderHeader.bind(this)
this.renderItem = this.renderItem.bind(this)
}
state = {
data: [],
items: [],
loading: false,
}
componentDidMount() {
this.getData()
}
async getData() {
const order = this.props.navigation.getParam('order', {})
this.setState({ loading: true })
const res = await api.getSettlementLines({ settlement_number: order.settlement_number })
this.setState({ loading: false })
if (res.error_code !== 0) return
this.setState({
data: R.propOr([], 'data_group')(res),
items: R.propOr([], 'data')(res),
})
}
/**
* @description: 选择操作
* @param {*} item
* @return {*}
*/
selectHandler(checked, item) {
const { data } = this.state
const order = R.find(R.propEq('order_number', item.order_number))(data)
order._checked = checked
order._indeterminate = false
R.compose(
R.map(it => {
it._checked = checked
}),
R.propOr([], 'sal_order_list'),
)(order)
this.setState({ data })
}
renderHeader() {}
renderItem({ item }) {
return (
<View style={g(styles, 'card')}>
<View style={g(styles, 'card-info')}>
<View style={g(styles, 'card-line')}>
<Text style={g(styles, 'card-text', 'card-text-key')}>销售单: </Text>
<Text style={g(styles, 'card-text')}>{item.order_number}</Text>
</View>
<View style={g(styles, 'card-line')}>
<Text style={g(styles, 'card-text', 'card-text-key')}>出库单: </Text>
<Text style={g(styles, 'card-text')}>{item.source_header_number}</Text>
</View>
<View style={g(styles, 'card-line')}>
<Text style={g(styles, 'card-text', 'card-text-key')}>数量: </Text>
<Text style={g(styles, 'card-text')}>{item.sum_quantity}</Text>
</View>
<View style={g(styles, 'card-line')}>
<Text style={g(styles, 'card-text', 'card-text-key')}>金额: </Text>
<Text style={g(styles, 'card-text')}>{item.sum_settlement_amount}</Text>
</View>
</View>
<View style={g(styles, 'card-select')}>
<Checkbox
checked={item._checked}
indeterminate={item._indeterminate}
style={g(styles, 'card-select__checkbox')}
onChange={checked => this.selectHandler(checked, item)}
/>
</View>
</View>
)
}
render() {
const order = this.props.navigation.getParam('order', {})
const title = '结算确认详情'
const { data } = this.state
return (
<View style={g(styles, 'container')}>
<Resolution.FixWidthView>
<Header
title={title}
backCallback={() => {
this.props.navigation.goBack()
}}
/>
<View style={g(styles, 'body')}>
<View style={g(styles, 'body-hd')}>
<Text style={g(styles, 'body-hd__text')}>结算单号: {order.settlement_number}</Text>
</View>
<FlatList
style={g(styles, 'body-bd')}
data={data}
keyExtractor={it => it.order_number}
renderItem={this.renderItem}
renderHeader={this.renderHeader}
></FlatList>
</View>
</Resolution.FixWidthView>
</View>
)
}
}
const mapStateToProps = state => ({})
const mapDispatchToProps = dispatch => ({})
export default connect(mapStateToProps, mapDispatchToProps)(Detail)
......@@ -2,7 +2,7 @@
* @FilePath: /BoneHouse_Business_APP/src/pages/settlement/index.tsx
* @Author: peii
* @Date: 2021-12-18 16:33:37
* @LastEditTime: 2021-12-19 18:25:26
* @LastEditTime: 2021-12-20 15:32:04
* @LastEditors: peii
* @Vision: 1.0
* @Description: 结算确认首页
......@@ -14,6 +14,7 @@ import { View, Text, TouchableOpacity, FlatList, Image } from 'react-native'
import { connect } from 'react-redux'
import * as R from 'ramda'
import { INavigation } from 'navigation'
import Loading from '../../../app/containers/common/LodingModel'
import Header from '../../components/header/header'
import Resolution from '../../components/common/Resolution'
import FilterModal from './components/filter'
......@@ -40,17 +41,14 @@ class Settlement extends React.Component<IProps, IState> {
}
state = {
modalVisible: false,
data: [
{
settlement_number: 'SUR20212020020',
settled_date: '2021-01-01',
settlement_quantity: 30,
settlement_price: 999,
},
],
data: [],
loading: false,
}
componentDidMount() {
this.toggleModalVisible()
}
toggleModalVisible(): void {
this.setState({ modalVisible: !this.state.modalVisible })
}
......@@ -61,7 +59,13 @@ class Settlement extends React.Component<IProps, IState> {
* @return {*}
*/
async getData(args): void {
this.setState({ loading: true })
const res = await api.getSettlements(args)
this.setState({ loading: false })
if (res.error_code !== 0) return
const data = R.propOr([], 'data')(res)
this.setState({ data })
}
render() {
......@@ -86,8 +90,7 @@ class Settlement extends React.Component<IProps, IState> {
{/* 过滤弹窗 */}
<FilterModal visible={modalVisible} onClose={this.toggleModalVisible} searchHandler={this.getData} />
{/* 结算列表 */}
<SettlementList data={data} />
{loading ? <Loading show={loading} /> : <SettlementList data={data} {...this.props} />}
</View>
</Resolution.FixWidthView>
</View>
......
@import '../../assets/styles/base.styl'
@import '../../assets/styles/variable.styl'
/*
* @FilePath: /BoneHouse_Business_APP/src/pages/settlement/saleDetail.tsx
* @Author: peii
* @Date: 2021-12-20 15:27:45
* @LastEditTime: 2021-12-20 16:14:47
* @LastEditors: peii
* @Vision: 1.0
* @Description: 结算销售物料详情
*/
// @ts-nocheck
import React, { useEffect, useRef, useState, createRef } from 'react'
import { View, Text, TouchableOpacity, FlatList, Image } from 'react-native'
import { connect } from 'react-redux'
import * as R from 'ramda'
import { INavigation } from 'navigation'
import Header from '../../components/header/header'
import Resolution from '../../components/common/Resolution'
import { isBlank, g } from '../../utils/utils'
import api from '../../services/api'
import styles from './detail.styl'
type IProps = {
navigation: INavigation
}
type IState = {}
class SaleDetail extends React.Component<IProps, IState> {
state = {
data: [],
}
componentDidMount() {}
render() {
const order = this.props.navigation.getParam('order', {})
const title = '结算确认详情'
return (
<View style={g(styles, 'container')}>
<Resolution.FixWidthView>
<Header
title={title}
backCallback={() => {
this.props.navigation.goBack()
}}
/>
<View style={g(styles, 'body')}>
<View style={g(styles, 'body-hd')}>
<Text>结算单号: {order.settlement_number}</Text>
</View>
</View>
</Resolution.FixWidthView>
</View>
)
}
}
const mapStateToProps = state => ({})
const mapDispatchToProps = dispatch => ({})
export default connect(mapStateToProps, mapDispatchToProps)(SaleDetail)
......@@ -2,7 +2,7 @@
* @FilePath: /BoneHouse_Business_APP/src/services/api.ts
* @Author: peii
* @Date: 2021-12-19 16:06:26
* @LastEditTime: 2021-12-19 18:38:12
* @LastEditTime: 2021-12-20 12:01:25
* @LastEditors: peii
* @Vision: 1.0
* @Description: 未重构完全暂用的所有请求
......@@ -41,7 +41,7 @@ export default {
settlement_number?: string
header_status?: string
}) {
return request({ url: `${v}/sale/settlement_header/search` })
return request({ url: `${v}/sale/settlement_header/search`, data })
},
/**
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment