feat(销售统计): 完成销售统计100%

This commit is contained in:
xuan 2022-10-14 19:02:38 +08:00
parent 4861cc9eb9
commit 52f070adda
18 changed files with 809 additions and 438 deletions

View File

@ -141,7 +141,7 @@ export const formatMillionYuan = (num, digit = 10000) => {
* @param {*} x
* @returns
*/
export const toDecimal2 = (x) => {
export const toDecimal2 = x => {
var f = parseFloat(x)
if (isNaN(f)) {
return 0
@ -203,3 +203,55 @@ export const numberWithCommas = ({ number = 0, digit = 2 }) => {
return 0.0
}
}
// 计算数值大于指定值
export const setPriceUnit = (num, cls) => {
if (cls) {
let res = formatMillionYuan(num, 1000)
return {
cls: res.million ? cls : '',
num: res.num,
}
} else if (num > 100000000) {
let res = formatMillionYuan(num, 100000000)
return {
cls: res.million ? 's-e' : '',
num: res.num,
}
} else {
let res = formatMillionYuan(num)
return {
cls: res.million ? 's-w' : '',
num: res.num,
}
}
}
//不四舍五入, val:原数据,num:保留位数
const noScale = (val, num = 2) => {
val = parseFloat(val)
num = parseInt(num)
const power = Math.pow(10, num)
val = val * power + ''
val = val.split('.')[0]
val = parseInt(val) / power
return val
}
//处理数据单位(自然数)
export const dataUnit = val => {
let newVal = ''
val = parseFloat(val)
if (val >= 100000000) {
newVal = noScale(val / 100000000) + '亿'
} else if (val >= 10000000) {
newVal = noScale(val / 10000000) + 'kw'
} else if (val >= 10000) {
newVal = noScale(val / 10000) + 'w'
} else if (val >= 1000) {
newVal = noScale(val / 1000) + 'k'
} else {
newVal = val
}
return newVal
}

View File

@ -117,7 +117,7 @@ function delay(delayTime = 25): Promise<null> {
})
}
function delayQuerySelector(
export function delayQuerySelector(
selectorStr: string,
delayTime = 500
): Promise<any[]> {
@ -170,6 +170,5 @@ export const shareShop = () => {
}
}
}
export {
delayQuerySelector
}

View File

@ -29,7 +29,7 @@ const LoadMore: FC<LoadMorePropsType> = props => {
component = <LoadingCard title={loadingText}></LoadingCard>
} else if (status === 'more') {
component = (
<View onClick={handleShowMore}>
<View className='flex-row' onClick={handleShowMore}>
<Text style={{ marginRight: '5px' }}>{moreText}</Text>
<Iconfont name='icon-zhankai' size={32}></Iconfont>
</View>

View File

@ -1,4 +1,4 @@
import { FC, useEffect, useMemo, useState } from 'react'
import { FC, memo, useEffect, useMemo, useState } from 'react'
import DropDownItem from '../dropDown-item'
import FilterButton from '../filterButton'
import { EnumMarketingDepartmentApi } from '@/api/index'
@ -17,7 +17,7 @@ type EnumList = {
name: string
}
// 营销部门
const SelectSaleType: FC<SelectSaleTypeProps> = props => {
const SelectSaleType: FC<SelectSaleTypeProps> = memo((props) => {
const selectName = '营销部门'
@ -64,5 +64,5 @@ const SelectSaleType: FC<SelectSaleTypeProps> = props => {
</View>
</DropDownItem>
)
}
})
export default SelectSaleType

View File

@ -1,4 +1,4 @@
import { FC, useEffect, useMemo, useState } from 'react'
import { FC, memo, useEffect, useMemo, useState } from 'react'
import DropDownItem from '../dropDown-item'
import FilterButton from '../filterButton'
import { SaleOrderDataFormdataFormStatus } from '@/api/index'
@ -18,7 +18,7 @@ type EnumList = {
name: string
}
// 销售排行指标
const SelectSaleRankingIndicators: FC<SelectSaleTypeProps> = props => {
const SelectSaleRankingIndicators: FC<SelectSaleTypeProps> = memo((props) => {
const selectName = '排行指标'
@ -65,5 +65,5 @@ const SelectSaleRankingIndicators: FC<SelectSaleTypeProps> = props => {
</View>
</DropDownItem>
)
}
})
export default SelectSaleRankingIndicators

View File

@ -1,4 +1,4 @@
import { FC, useEffect, useMemo, useState } from 'react'
import { FC, memo, useEffect, useMemo, useState } from 'react'
import DropDownItem from '../dropDown-item'
import FilterButton from '../filterButton'
import { EnumSalesTypeApi } from '@/api/index'
@ -9,7 +9,7 @@ type ChangedValue = string | number
interface SelectSaleTypeProps {
onChange?: (value: ChangedValue) => void
defaultValue?: string
defaultValue?: ChangedValue
}
type EnumList = {
@ -18,9 +18,9 @@ type EnumList = {
name: string
}
// 销售类型
const SelectSaleType: FC<SelectSaleTypeProps> = props => {
const SelectSaleType: FC<SelectSaleTypeProps> = memo((props) => {
const selectName = '销售类型'
const { onChange } = props
const { onChange, defaultValue = 0 } = props
console.log(props)
const { fetchData } = EnumSalesTypeApi()
@ -35,7 +35,7 @@ const SelectSaleType: FC<SelectSaleTypeProps> = props => {
getData()
}, [])
const [currentValue, setCurrentValue] = useState<ChangedValue>(-1)
const [currentValue, setCurrentValue] = useState<ChangedValue>(defaultValue)
const handleClick = (value: ChangedValue) => {
setCurrentValue(value)
@ -63,5 +63,5 @@ const SelectSaleType: FC<SelectSaleTypeProps> = props => {
</View>
</DropDownItem>
)
}
})
export default SelectSaleType

View File

@ -1,7 +1,7 @@
import { formatDateTime } from '@/common/format'
import { View, Text } from '@tarojs/components'
import dayjs from 'dayjs'
import { FC, useState } from 'react'
import { FC, memo, useRef, useState } from 'react'
import DropDownItem from '../dropDown-item'
import FilterButton from '../filterButton'
import IconFont from '../iconfont/iconfont'
@ -11,6 +11,8 @@ import styles from './index.module.scss'
export type ChangedValue = string[]
interface SelectSaleTypeProps {
defaultValue?: Key // 默认值
timeOptions?: {[Property: string]: Value} // 支持自定义 时间配置
onChange?: (value: ChangedValue) => void
}
@ -65,7 +67,7 @@ const FilterTimeOptions = {
.add(0, 'day')
.format('YYYY-MM-DD')} 00:00:00`,
},
'6': {
'custom': {
name: '自定义时间',
date_min: '',
date_max: '',
@ -75,10 +77,13 @@ const FilterTimeOptions = {
type Key = keyof typeof FilterTimeOptions
type Value = typeof FilterTimeOptions[Key]
const SelectTimePicker: FC<SelectSaleTypeProps> = props => {
const { onChange: change } = props
const SelectTimePicker: FC<SelectSaleTypeProps> = memo((props) => {
const { onChange: change, defaultValue = '0', timeOptions = FilterTimeOptions } = props
// rerender 的时候需要更新 ref 的值
const Options = useRef({ ...timeOptions, 'custom': FilterTimeOptions['custom'] })
Options.current = { ...timeOptions, 'custom': FilterTimeOptions['custom'] }
const [currentValue, setCurrentValue] = useState('0')
const [currentValue, setCurrentValue] = useState(defaultValue)
const [currentDate, setCurrentDate] = useState({
start: new Date().toLocaleDateString(),
@ -96,10 +101,11 @@ const SelectTimePicker: FC<SelectSaleTypeProps> = props => {
const handleClick = (key: Key) => {
setCurrentValue(key)
change?.([FilterTimeOptions[key].date_min, FilterTimeOptions[key].date_max])
setCustomFilterButtonText('自定义时间')
change?.([Options.current[key].date_min, Options.current[key].date_max])
customFilterButtonText.current = '自定义时间'
}
// 选择时间
// 选择自定义时间
const onSelectDate = event => {
console.log(event?.value, 'event?.value?.start')
setCurrentDate({
@ -107,27 +113,28 @@ const SelectTimePicker: FC<SelectSaleTypeProps> = props => {
end: event?.value?.end,
})
setShowTime(false)
setCustomFilterButtonText(`${formatDateTime(event?.value?.start, 'YYYY年MM月DD日')}${formatDateTime(event?.value?.end, 'YYYY年MM月DD日')}`)
customFilterButtonText.current = `${formatDateTime(event?.value?.start, 'YYYY年MM月DD日')}${formatDateTime(event?.value?.end, 'YYYY年MM月DD日')}`
change?.([event?.value?.start, event?.value?.end])
}
const [customFilterButtonText, setCustomFilterButtonText] = useState('自定义时间')
// const [customFilterButtonText, setCustomFilterButtonText] = useState('自定义时间')
const customFilterButtonText = useRef('自定义时间')
// 点击自定义时间
const handleCustomTime = () => {
setCurrentValue('6')
setCurrentValue('custom')
setShowTime(true)
}
return (
<>
<DropDownItem
title={currentValue === '0' ? '查询日期' : FilterTimeOptions[currentValue].name}
title={currentValue === '0' ? '查询日期' : Options.current[currentValue].name}
direction='down'
value={currentValue}
activeColor='#337fff'>
<View className={styles.grid} style={{ paddingBottom: '24rpx' }}>
{Object.entries(FilterTimeOptions)
{Object.entries(Options.current)
.slice(0, -1)
.map(([key, value]) => {
return (
@ -136,14 +143,14 @@ const SelectTimePicker: FC<SelectSaleTypeProps> = props => {
</FilterButton>
)
})}
<FilterButton customClassName={styles.customFilterTime} isActive={'6' === currentValue} onClick={handleCustomTime}>
<Text>{customFilterButtonText}</Text>
<IconFont name='icon-chakanquanbukehu' color={'6' === currentValue ? '#3983ff' : '#7f7f7f'}></IconFont>
<FilterButton customClassName={styles.customFilterTime} isActive={'custom' === currentValue} onClick={handleCustomTime}>
<Text>{customFilterButtonText.current}</Text>
<IconFont name='icon-chakanquanbukehu' color={'custom' === currentValue ? '#3983ff' : '#7f7f7f'}></IconFont>
</FilterButton>
</View>
</DropDownItem>
<TimePickerPopup start={currentDate.start} end={currentDate.end} showTime={showTime} closePopup={handClose} onSelectDate={onSelectDate}></TimePickerPopup>
</>
)
}
})
export default SelectTimePicker

View File

@ -11,10 +11,11 @@ interface CellPropsType {
onClick?: () => void
customStyle?: React.CSSProperties
customClassName?: string
customDescClassName?: string
iconName?: IconNames
}
const Cell:FC<CellPropsType> = (props) => {
const {title, desc, isLink = false, customClassName, customStyle, onClick, iconName} = props
const { title, desc, isLink = false, customClassName, customStyle, onClick, iconName, customDescClassName } = props
const onClickRef = useRef(onClick)
onClickRef.current = onClick
@ -31,7 +32,7 @@ const Cell:FC<CellPropsType> = (props) => {
<View>{title}</View>
</View>
<View className={styles.desc}>
<Text className={styles.descText}>{desc}</Text>
<Text className={classNames(styles.descText, customDescClassName)}>{desc}</Text>
{isLink && <IconFont name='icon-chakanquanbukehu' size={46} color='inherit'></IconFont>}
</View>
</View>

View File

@ -3,7 +3,6 @@
&--title {
position: relative;
z-index: 2000;
background-color: white;
display: flex;
flex-flow: row nowrap;

View File

@ -9,7 +9,8 @@ export type StatusParam = 0|1|2|3
type Params = {
styleObj?: React.CSSProperties
selfonScrollToLower?: () => void
hasMore?: boolean
enableLoadMoreStatus?: boolean
safeAreaInsetBottom?: boolean
moreStatus?: boolean
statusMore?: StatusParam //0:数据从无到有加载数据1没有任何数据 2下拉加载3下拉没有数据
children?: ReactNode
@ -35,7 +36,8 @@ export default memo(
selfOnRefresherRefresh,
selfOnRefresherRestore,
selfOnRefresherAbort,
hasMore = true,
safeAreaInsetBottom=true,
enableLoadMoreStatus = true,
children,
lowerThresholdNum = 5,
paddingBottom = 0,
@ -43,7 +45,7 @@ export default memo(
refresherEnabled = false,
moreStatus = true,
statusMore = 0,
enableBackToTop=true,
enableBackToTop = true,
}: Params) => {
const scrollToLower = () => {
selfonScrollToLower?.()
@ -51,7 +53,7 @@ export default memo(
const scrollToUpper = () => {
selfOnScrollToUpper?.()
}
const scroll = (e) => {
const scroll = e => {
selfOnScroll?.(e)
}
const refresherPulling = () => {
@ -74,32 +76,17 @@ export default memo(
}
}, [statusMore])
return (
<>
<ScrollView
style={styleObj}
className={style.scroll_main}
scrollY
onScrollToLower={() => scrollToLower()}
onScrollToUpper={() => scrollToUpper()}
onScroll={(e) => scroll(e)}
lowerThreshold={lowerThresholdNum}
refresherEnabled={refresherEnabled}
refresherTriggered={refresherTriggered}
onRefresherPulling={() => refresherPulling()}
onRefresherRefresh={() => refresherRefresh()}
onRefresherRestore={() => refresherRestore()}
onRefresherAbort={() => refresherAbort()}
refresherBackground='#F8F8F8'
enableBackToTop={enableBackToTop}
scrollTop={scrollTop}>
{(!moreStatus && (
<>
<View style={{ paddingBottom: paddingBottom + 'rpx' }} className={style.scrollViewCon}>
{children}
</View>
</>
)) || (
const component = () => {
if(enableLoadMoreStatus){
if (!moreStatus){
return (
<View style={{ paddingBottom: paddingBottom + 'rpx' }} className={style.scrollViewCon}>
{children}
</View>
)
}else{
return (
<>
{(statusMore == 2 || statusMore == 3) && (
<View style={{ paddingBottom: paddingBottom + 'rpx' }} className={style.scrollViewCon}>
@ -117,9 +104,39 @@ export default memo(
{statusMore == 0 && <LoadingCard />}
{statusMore == 1 && <LoadingCard loadingIcon={false} title='暂无数据' />}
</>
)}
)
}
<View className='common_safe_area_y'></View>
}else{
return (
<View style={{ paddingBottom: paddingBottom + 'rpx' }} className={style.scrollViewCon}>
{children}
</View>
)
}
}
return (
<>
<ScrollView
style={styleObj}
className={style.scroll_main}
scrollY
onScrollToLower={() => scrollToLower()}
onScrollToUpper={() => scrollToUpper()}
onScroll={e => scroll(e)}
lowerThreshold={lowerThresholdNum}
refresherEnabled={refresherEnabled}
refresherTriggered={refresherTriggered}
onRefresherPulling={() => refresherPulling()}
onRefresherRefresh={() => refresherRefresh()}
onRefresherRestore={() => refresherRestore()}
onRefresherAbort={() => refresherAbort()}
refresherBackground='#F8F8F8'
enableBackToTop={enableBackToTop}
scrollTop={scrollTop}>
{component()}
{safeAreaInsetBottom && <View className='common_safe_area_y'></View>}
</ScrollView>
</>
)

View File

@ -72,8 +72,10 @@ $am-ms: 200ms;
min-height: 200px;
width: 100%;
border-radius: 20px 20px 0px 0px;
box-shadow: 1px 1px 1px 1px #f2f2f2;
transform: translate3d(0, 100%, 0);
&-withShadow {
box-shadow: 0px -1px 9px -1px #333;
}
}
.drawer_container_top {
@ -82,8 +84,10 @@ $am-ms: 200ms;
min-height: 200px;
width: 100%;
border-radius: 0 0 20px 20px;
box-shadow: 6px 6px 5px 14px red;
transform: translate3d(0, -100%, 0);
&-withShadow {
box-shadow: 0 1px 9px -1px #333;
}
}
.drawer_container_right {
@ -93,5 +97,8 @@ $am-ms: 200ms;
min-width: 300px;
border-radius: 20px 0 0 20px;
transform: translate3d(100%, 0, 0);
&-withShadow {
box-shadow: -1px 0px 9px -1px #333;
}
}
}

View File

@ -21,8 +21,8 @@ export interface Params extends PopupEvent {
position?: 'bottom' | 'top' | 'right' //弹出位置
customStyle?: React.CSSProperties
overlayStyle?: React.CSSProperties
safeAreaInsetBottom?: boolean // 是否为iphoneX提供小黑条适配
showOverLay?: boolean // 是否显示遮罩层
safeAreaInsetBottom?: boolean // 是否为iphoneX提供小黑条适配
showOverLay?: boolean // 是否显示遮罩层
}
export default memo(
({
@ -53,38 +53,38 @@ export default memo(
useEffect(() => {
return () => {
clearTimeout(animationTime.current)
}
}, [])
return (
<>
<View className={style.drawer_main}>
<View catchMove={true} className={classnames(style.drawer, show ? style.drawer_active : '')} style={customStyle}>
<View
className={classnames(style.drawer_mask, { [style.drawer_mask_active]: show, [style['drawer_mask--hidden']]: !showOverLay })}
onClick={onClose}
style={overlayStyle}></View>
<View
style={{ position: `${isFixed == true ? 'fixed' : 'absolute'}` }}
className={classnames(style.drawer_container, style['drawer_container_' + position], { [style.drawer_container_active]: show })}
onClick={e => e.stopPropagation()}>
{showTitle && <View className={style.drawer_container_title}>{title}</View>}
{showIconButton && (
<View className={style.common_close_btn_icon}>
<CloseBtnIcon onClose={onClose} />
</View>
)}
<View id='drawerContainerContext' className={style.drawer_container_context}>
{children}
<View className={style.drawer_main}>
<View catchMove={true} className={classnames(style.drawer, show ? style.drawer_active : '')} style={customStyle}>
<View
className={classnames(style.drawer_mask, { [style.drawer_mask_active]: show, [style['drawer_mask--hidden']]: !showOverLay })}
onClick={onClose}
style={overlayStyle}></View>
<View
style={{ position: `${isFixed == true ? 'fixed' : 'absolute'}` }}
className={classnames(style.drawer_container, style['drawer_container_' + position], {
[style.drawer_container_active]: show,
[style[`drawer_container_${position}-withShadow`]]: !showOverLay,
})}
onClick={e => e.stopPropagation()}>
{showTitle && <View className={style.drawer_container_title}>{title}</View>}
{showIconButton && (
<View className={style.common_close_btn_icon}>
<CloseBtnIcon onClose={onClose} />
</View>
{safeAreaInsetBottom && <View className='common_safe_area_y'></View>}
)}
<View id='drawerContainerContext' className={style.drawer_container_context}>
{children}
</View>
{safeAreaInsetBottom && <View className='common_safe_area_y'></View>}
</View>
</View>
</>
</View>
)
},
)

View File

@ -106,7 +106,7 @@ export default memo(({list = [],
}
</ScrollView>
<View className={styles.sideBar_con}>
<InfiniteScroll statusMore={statusMore} hasMore={hasMore} selfonScrollToLower={() => selfOnScrolltolower?.()} refresherTriggered={refresherTriggered} refresherEnabled={true} selfOnRefresherRefresh={() => selfOnRefresherRefresh?.()}>
<InfiniteScroll statusMore={statusMore} selfonScrollToLower={() => selfOnScrolltolower?.()} refresherTriggered={refresherTriggered} refresherEnabled={true} selfOnRefresherRefresh={() => selfOnRefresherRefresh?.()}>
{children}
</InfiniteScroll>
</View>

View File

@ -1,12 +1,12 @@
import { ScrollView, View, Text } from '@tarojs/components'
import classnames from 'classnames'
import { FC, useState } from 'react'
import { FC, useCallback, useMemo, useState } from 'react'
import Iconfont from '../iconfont/iconfont'
import InfiniteScroll from '../infiniteScroll'
import LoadMore, { LoadMoreStatus } from '../LoadMore'
import styles from './index.module.scss'
type ColumnsType = {
export type ColumnsType = {
title: string
dataIndex: string
width: string
@ -15,29 +15,26 @@ type ColumnsType = {
ellipsis?: boolean | { isEllipsis: boolean; rows: number }
}
type RecordType = {
export type RecordType = {
key: string
[Property: string]: any
}
interface TablePropsType {
export interface TablePropsType {
columns: ColumnsType[]
dataSource: RecordType[]
dataSource?: { list: RecordType[]; total: number }
onLoadMore?: () => void
height?: number
}
const Table: FC<TablePropsType> = props => {
const { columns, dataSource } = props
const [showMore, setShowMore] = useState(false)
const [loadMoreStatus, setLoadMoreStatus] = useState<LoadMoreStatus>('loading')
const { columns, dataSource, onLoadMore, height=400 } = props
const handleShowMore = () => {
onLoadMore && onLoadMore()
}
const getColumnStyle = (columnConfig: ColumnsType) => {
const getColumnStyle = useCallback((columnConfig: ColumnsType) => {
const columnStyle = {}
if (typeof columnConfig.ellipsis === 'boolean' && columnConfig.ellipsis) {
columnStyle[styles.ellipsis_1] = true
@ -51,13 +48,25 @@ const Table: FC<TablePropsType> = props => {
}
}
return columnStyle
}
}, [])
const loadMoreComponent = useMemo(() => {
if (dataSource) {
if (dataSource.list.length < dataSource.total) {
return <LoadMore status='more' onClick={handleShowMore}></LoadMore>
} else if (dataSource.list.length >= dataSource.total) {
return <LoadMore status='noMore' onClick={handleShowMore}></LoadMore>
}
} else {
return <LoadMore status='loading' onClick={handleShowMore}></LoadMore>
}
}, [dataSource])
const sourceContainer = () => {
return (
<>
{!!dataSource.length &&
dataSource.map(source => {
{!!dataSource?.list?.length &&
dataSource.list.map(source => {
return (
<View className={classnames(styles.tr, styles['bg-line'])} key={source.key}>
{columns.map(column => {
@ -81,9 +90,7 @@ const Table: FC<TablePropsType> = props => {
</View>
)
})}
{showMore && (
<LoadMore status={loadMoreStatus} onClick={handleShowMore}></LoadMore>
)}
{loadMoreComponent}
</>
)
}
@ -99,7 +106,9 @@ const Table: FC<TablePropsType> = props => {
)
})}
</View>
<ScrollView>{sourceContainer()}</ScrollView>
<InfiniteScroll enableLoadMoreStatus={false} safeAreaInsetBottom={true}>
{sourceContainer()}
</InfiniteScroll>
</View>
)
}

View File

@ -0,0 +1,181 @@
// 订单
export const OrderForm = {
summary: {
summaryTitle: '订单总数',
tips: '已成功下单的总单数',
value: {
num: '',
cls: '',
},
total: {
num: '',
cls: '',
},
},
form: {
processing_order_number: {
cellTitle: '待配布订单',
tips: '已经预约和正在配布的订单数',
value: {
num: '',
cls: '',
},
},
processed_order_number: {
cellTitle: '已配布订单',
tips: '所有配完布、已批准发货、已经发货的订单总单数',
value: {
num: '',
cls: '',
},
},
},
}
// 配布
export const ArrangedForm = {
summary: {
summaryTitle: '已配布匹数',
tips: '所有配完布、已批准发货、已经发货的订单总匹数',
value: {
num: '',
cls: '',
},
total: {
num: '',
cls: '',
},
},
form: {
wait_collect_order_number: {
cellTitle: '待收款单数',
tips: '已配完布但未批准发货的所有订单总单数',
value: {
num: '',
cls: '',
},
},
wait_collect_number: {
cellTitle: '待收款匹数',
tips: '已配完布但未批准发货的所有订单总匹数',
value: {
num: '',
cls: '',
},
},
wait_collect_amount_sum: {
cellTitle: '待收款金额',
tips: '已配完布但未批准发货的所有订单总金额',
value: {
num: '',
cls: '',
},
},
not_shipped_order_number: {
cellTitle: '待发货单数',
tips: '已批准发货但未发货出库的所有订单总单数',
value: {
num: '',
cls: '',
},
},
not_shipped_number: {
cellTitle: '待发货匹数',
tips: '已批准发货但未发货出库的所有订单总匹数',
value: {
num: '',
cls: '',
},
},
not_shipped_amount_sum: {
cellTitle: '待发货金额',
tips: '已批准发货但未发货出库的所有订单总金额',
value: {
num: '',
cls: '',
},
},
shipped_order_number: {
cellTitle: '已发货单数',
tips: '已经发货出库的所有订单总单数',
value: {
num: '',
cls: '',
},
},
shipped_number: {
cellTitle: '已发货匹数',
tips: '已经发货出库的所有订单总匹数',
value: {
num: '',
cls: '',
},
},
shipped_amount_sum: {
cellTitle: '已发货金额',
tips: '已经发货出库的所有订单总金额',
value: {
num: '',
cls: '',
},
},
},
}
// 货款
export const PaymentAmountForm = {
summary: {
summaryTitle: '货款金额',
tips: '已经发货出库的所有订单总金额',
value: {
num: '',
cls: '',
},
},
form: {
amount_unreceived_sum: {
cellTitle: '未收金额',
tips: '已经批准发货出库但未收到货款的所有订单总金额',
value: {
num: '',
cls: '',
},
},
amount_received_sum: {
cellTitle: '已收金额',
tips: '已收且已经发货出库的所有订单总金额',
value: {
num: '',
cls: '',
},
},
},
}
// 退货
export const ReturnGoodsOrderForm = {
summary: {
summaryTitle: '退货单数',
tips: '已经完成退货入库的退货单总单数',
value: {
num: '',
cls: '',
},
},
form: {
return_goods_number: {
cellTitle: '退货匹数',
tips: '已经完成退货入库的退货单总匹数',
value: {
num: '',
cls: '',
},
},
return_amount_sum: {
cellTitle: '退货金额',
tips: '已经完成退货入库的退货单总金额',
value: {
num: '',
cls: '',
},
},
},
}

View File

@ -87,3 +87,5 @@ page {
.amount {
color: $color_main;
}

View File

@ -1,4 +1,5 @@
import { SaleOrderDataFormApi } from '@/api/statistic/saleStatistic'
import { ProductRankApi, PurchaserRankApi, SaleOrderDataFormApi, SalesmanRankApi } from '@/api/statistic/saleStatistic'
import { formatPriceDiv, setPriceUnit, dataUnit } from '@/common/format'
import { getFilterData } from '@/common/util'
import Cell from '@/components/cell'
import Divider from '@/components/Divider'
@ -8,326 +9,159 @@ import SelectMarketingDepartment from '@/components/SelectMarketingDepartment'
import SelectSaleRankingIndicators from '@/components/SelectSaleRankingIndicators'
import SelectSaleType from '@/components/SelectSaleType'
import SelectTimePicker, { ChangedValue } from '@/components/SelectTimePicker'
import Table from '@/components/table'
import Table, { TablePropsType } from '@/components/table'
import ToolTip from '@/components/toolTips'
import { View, Text } from '@tarojs/components'
import { useDidShow } from '@tarojs/taro'
import classnames from 'classnames'
import { useCallback, useState } from 'react'
import dayjs from 'dayjs'
import { memo, useCallback, useEffect, useRef, useState } from 'react'
import styles from './index.module.scss'
import { OrderForm, ArrangedForm, PaymentAmountForm, ReturnGoodsOrderForm } from './config'
//需要传进来的数据示例
const exampledataSource = [
{
key: '1',
username: '小红',
count: '123打发手动阀手动阀啊手动阀',
gb: '321',
dbd: '¥6634.93w',
},
{
key: '2',
username: '小红',
count: '123',
gb: '321',
dbd: '¥6634.93w',
},
{
key: '3',
username: '小红',
count: '123',
gb: '321',
dbd: '¥6634.93w',
},
{
key: '4',
username: '小红',
count: '123',
gb: '321',
dbd: '¥6634.93w',
},
{
key: '5',
username: '小红',
count: '123',
gb: '321',
dbd: '¥6634.93w',
},
{
key: '6',
username: '小红',
count: '123',
gb: '321',
dbd: '¥6634.93w',
},
{
key: '7',
username: '小红',
count: '123',
gb: '321',
dbd: '¥6634.93w',
},
{
key: '8',
username: '小红',
count: '123',
gb: '321',
dbd: '¥6634.93w',
},
{
key: '9',
username: '小红',
count: '123',
gb: '321',
dbd: '¥6634.93w',
},
{
key: '10',
username: '小红',
count: '123',
gb: '321',
dbd: '¥6634.93w',
},
]
//处理金额(后端单位分,转元)
const priceformat = (val: number) => {
return dataUnit(val / 100)
}
//需要传进来的表头数据示例
const examplecolumns = [
{
key: 'username',
title: '编号',
dataIndex: 'username',
width: '20%',
const defaultLimit = 10
const FilterTimeOptions = {
'0': {
name: '今天',
date_min: `${dayjs(new Date())
.add(0, 'day')
.format('YYYY-MM-DD')} 00:00:00`,
date_max: `${dayjs(new Date())
.add(1, 'day')
.format('YYYY-MM-DD')} 00:00:00`,
},
{
key: 'count',
title: '面料名称',
dataIndex: 'count',
width: '20%',
ellipsis: {
isEllipsis: true,
rows: 2,
},
'1': {
name: '昨日',
date_min: `${dayjs(new Date())
.add(-1, 'day')
.format('YYYY-MM-DD')} 00:00:00`,
date_max: `${dayjs(new Date())
.add(0, 'day')
.format('YYYY-MM-DD')} 00:00:00`,
},
{
key: 'gb',
title: '匹数',
dataIndex: 'gb',
width: '30%',
'2': {
name: '近7日',
date_min: `${dayjs(new Date())
.add(-7, 'day')
.format('YYYY-MM-DD')} 00:00:00`,
date_max: `${dayjs(new Date())
.add(0, 'day')
.format('YYYY-MM-DD')} 00:00:00`,
},
{
key: 'dbd',
title: '交易金额',
dataIndex: 'dbd',
width: '30%',
render: (text: string) => <Text className={styles.amount}>{text}</Text>,
'3': {
name: '近30日',
date_min: `${dayjs(new Date())
.add(-30, 'day')
.format('YYYY-MM-DD')} 00:00:00`,
date_max: `${dayjs(new Date())
.add(0, 'day')
.format('YYYY-MM-DD')} 00:00:00`,
},
]
'4': {
name: '近90日',
date_min: `${dayjs(new Date())
.add(-90, 'day')
.format('YYYY-MM-DD')} 00:00:00`,
date_max: `${dayjs(new Date())
.add(0, 'day')
.format('YYYY-MM-DD')} 00:00:00`,
},
}
// 销售统计
const saleStatistic = () => {
// 订单
const OrderForm = {
summary: {
summaryTitle: '订单总数',
tips: '已成功下单的总单数',
value: '51321',
total: '231231',
},
form: {
processing_order_number: {
cellTitle: '待配布订单',
tips: '已经预约和正在配布的订单数',
value: '5132',
},
processed_order_number: {
cellTitle: '已配布订单',
tips: '所有配完布、已批准发货、已经发货的订单总单数',
value: '564651',
},
},
}
// 配布
const ArrangedForm = {
summary: {
summaryTitle: '已配布匹数',
tips: '所有配完布、已批准发货、已经发货的订单总匹数',
value: '53453',
total: '456345',
},
form: {
wait_collect_order_number: {
cellTitle: '待收款单数',
tips: '已配完布但未批准发货的所有订单总单数',
value: '45634',
},
wait_collect_number: {
cellTitle: '待收款匹数',
tips: '已配完布但未批准发货的所有订单总匹数',
value: '463',
},
wait_collect_amount_sum: {
cellTitle: '待收款金额',
tips: '已配完布但未批准发货的所有订单总金额',
value: '4563',
},
not_shipped_order_number: {
cellTitle: '待发货单数',
tips: '已批准发货但未发货出库的所有订单总单数',
value: '4563',
},
not_shipped_number: {
cellTitle: '待发货匹数',
tips: '已批准发货但未发货出库的所有订单总匹数',
value: '4563',
},
not_shipped_amount_sum: {
cellTitle: '待发货金额',
tips: '已批准发货但未发货出库的所有订单总金额',
value: '4563',
},
shipped_order_number: {
cellTitle: '已发货单数',
tips: '已经发货出库的所有订单总单数',
value: '4563',
},
shipped_number: {
cellTitle: '已发货匹数',
tips: '已经发货出库的所有订单总匹数',
value: '463',
},
shipped_amount_sum: {
cellTitle: '已发货金额',
tips: '已经发货出库的所有订单总金额',
value: '4563',
},
},
}
// 货款
const paymentAmountForm = {
summary: {
summaryTitle: '货款金额',
tips: '已经发货出库的所有订单总金额',
value: '456345',
total: '45634',
},
form: {
amount_unreceived_sum: {
cellTitle: '未收金额',
tips: '已经批准发货出库但未收到货款的所有订单总金额',
value: '4563',
},
amount_received_sum: {
cellTitle: '已收金额',
tips: '已收且已经发货出库的所有订单总金额',
value: '4563',
},
},
}
// 退货
const ReturnGoodsOrderForm = {
summary: {
summaryTitle: '退货单数',
tips: '已经完成退货入库的退货单总单数',
value: '4563',
total: '4563',
},
form: {
return_goods_number: {
cellTitle: '退货匹数',
tips: '已经完成退货入库的退货单总匹数',
value: '4563',
},
return_amount_sum: {
cellTitle: '退货金额',
tips: '已经完成退货入库的退货单总金额',
value: '4563',
},
},
}
const { fetchData } = SaleOrderDataFormApi()
const [saleType, setSaleType] = useState<number | null>(null)
const [saleType, setSaleType] = useState<number | null>(0)
const [saleDepartmentId, setSaleDepartmentId] = useState<number | null>(null)
const [dateRange, setDateRange] = useState({
date_min: '',
date_max: '',
date_min: FilterTimeOptions[0].date_min,
date_max: FilterTimeOptions[0].date_max,
})
useEffect(() => {
getData()
}, [saleType, saleDepartmentId, dateRange])
const getData = async () => {
// console.log(
// 'getFilterData',
// getFilterData({
// sale_type: saleType,
// sale_department_id: saleDepartmentId,
// date_min: dateRange.date_min,
// date_max: dateRange.date_max,
// }),
// )
// const res = await fetchData(getFilterData({
// sale_type: saleType,
// sale_department_id: saleDepartmentId,
// date_min: dateRange.date_min,
// date_max: dateRange.date_max,
// }))
// if(res.data){
// }
const res = await fetchData(
getFilterData({
sale_type: saleType,
sale_department_id: saleDepartmentId,
date_min: dateRange.date_min,
date_max: dateRange.date_max,
}),
)
if (res.data) {
// 订单
OrderForm.summary.value = setPriceUnit(res.data.order_number)
OrderForm.summary.total = setPriceUnit(res.data.total_roll)
OrderForm.form.processed_order_number.value = setPriceUnit(res.data.processed_order_number)
OrderForm.form.processing_order_number.value = setPriceUnit(res.data.processing_order_number)
// 配布
ArrangedForm.summary.total = setPriceUnit(res.data.arranged_amount_sum)
ArrangedForm.summary.value = setPriceUnit(res.data.arranged_number)
ArrangedForm.form.not_shipped_amount_sum.value = setPriceUnit(formatPriceDiv(res.data.not_shipped_amount_sum) as number)
ArrangedForm.form.not_shipped_number.value = setPriceUnit(res.data.not_shipped_amount_sum)
ArrangedForm.form.not_shipped_order_number.value = setPriceUnit(res.data.not_shipped_order_number)
ArrangedForm.form.shipped_amount_sum.value = setPriceUnit(formatPriceDiv(res.data.shipped_amount_sum) as number)
ArrangedForm.form.shipped_number.value = setPriceUnit(res.data.shipped_number)
ArrangedForm.form.shipped_order_number.value = setPriceUnit(res.data.shipped_order_number)
ArrangedForm.form.wait_collect_amount_sum.value = setPriceUnit(formatPriceDiv(res.data.wait_collect_amount_sum) as number)
ArrangedForm.form.wait_collect_number.value = setPriceUnit(res.data.wait_collect_number)
ArrangedForm.form.wait_collect_order_number.value = setPriceUnit(res.data.wait_collect_order_number)
// 货款
PaymentAmountForm.summary.value = setPriceUnit(formatPriceDiv(res.data.payment_amount_sum) as number)
PaymentAmountForm.form.amount_received_sum.value = setPriceUnit(formatPriceDiv(res.data.amount_received_sum) as number)
PaymentAmountForm.form.amount_unreceived_sum.value = setPriceUnit(formatPriceDiv(res.data.amount_unreceived_sum) as number)
// 退货
ReturnGoodsOrderForm.summary.value = setPriceUnit(res.data.return_goods_order_number)
ReturnGoodsOrderForm.form.return_amount_sum.value = setPriceUnit(formatPriceDiv(res.data.return_amount_sum) as number)
ReturnGoodsOrderForm.form.return_goods_number.value = setPriceUnit(res.data.return_goods_number)
console.log(res.data)
}
}
useDidShow(()=>{
getData()
})
const onChangeTimePicker = useCallback((value: ChangedValue) => {
console.log(value)
setDateRange({
date_max: value[0],
date_min: value[1],
date_max: value[1],
date_min: value[0],
})
}, [])
const onChangeSaleType = useCallback((saleType: number) => {
console.log('saleType', saleType)
setSaleType(saleType)
// 全部
if (saleType === -1) {
setSaleType(null)
} else {
setSaleType(saleType)
}
}, [])
const onChangeDepartment = useCallback((department: number) => {
console.log('department', department)
setSaleDepartmentId(department)
// 全部
if (department === -1) {
setSaleDepartmentId(null)
} else {
setSaleDepartmentId(department)
}
}, [])
const onChangeIndicators = (indicators: number) => {
console.log('indicators', indicators)
}
const tabsConfig = [
{
name: '面料',
key: 0,
},
{
name: '客户',
key: 1,
},
{
name: '业务员',
key: 2,
},
]
const [currentKey, setCurrentKey] = useState(tabsConfig[0].key)
const handleClickTab = event => {
const key = event.target.dataset.key
if (key === currentKey) return
setCurrentKey(key)
}
return (
<View className={styles.saleStatistic}>
{/* <View style={{background: 'red', width: '100%', height: '200px'}}></View> */}
<View className={styles['saleStatistic--filterBar']}>
<SelectSaleType onChange={onChangeSaleType}></SelectSaleType>
<SelectMarketingDepartment onChange={onChangeDepartment}></SelectMarketingDepartment>
<SelectTimePicker onChange={onChangeTimePicker}></SelectTimePicker>
<SelectTimePicker onChange={onChangeTimePicker} defaultValue='0' timeOptions={FilterTimeOptions}></SelectTimePicker>
</View>
<View className={styles['saleStatistic--content']}>
<LayoutBlock circle flexDirection='col'>
@ -343,8 +177,11 @@ const saleStatistic = () => {
<Iconfont name='icon-tishi' size={36} color='#707070'></Iconfont>
</View>
</ToolTip>
<View className={styles['totalSummary--current']}>{OrderForm.summary.value}</View>
<View className={styles['totalSummary--totalNum']}> {OrderForm.summary.total} </View>
<View className={classnames(styles['totalSummary--current'], OrderForm.summary.value.cls)}>{OrderForm.summary.value.num}</View>
<View className={classnames(styles['totalSummary--totalNum'])}>
<Text className={OrderForm.summary.total.cls}>{OrderForm.summary.total.num}</Text>
</View>
</View>
{Object.entries(OrderForm.form).map(([key, value]) => {
return (
@ -358,7 +195,8 @@ const saleStatistic = () => {
</View>
</ToolTip>
}
desc={value.value}
desc={value.value.num}
customDescClassName={value.value.cls}
customClassName={styles['cell-desc']}></Cell>
)
})}
@ -376,8 +214,10 @@ const saleStatistic = () => {
<Iconfont name='icon-tishi' size={36} color='#707070'></Iconfont>
</View>
</ToolTip>
<View className={styles['totalSummary--current']}>{ArrangedForm.summary.value}</View>
<View className={styles['totalSummary--totalNum']}> {ArrangedForm.summary.total}</View>
<View className={classnames(styles['totalSummary--current'], ArrangedForm.summary.value.cls)}>{ArrangedForm.summary.value.num}</View>
<View className={classnames(styles['totalSummary--totalNum'])}>
<Text className={ArrangedForm.summary.total.cls}>{ArrangedForm.summary.total.num}</Text>
</View>
</View>
{Object.entries(ArrangedForm.form).map(([key, value], index) => {
return (
@ -392,7 +232,8 @@ const saleStatistic = () => {
</View>
</ToolTip>
}
desc={value.value}
desc={value.value.num}
customDescClassName={value.value.cls}
customClassName={styles['cell-desc']}></Cell>
{(index + 1) % 3 === 0 && <Divider direction='horizontal' customStyles={{ margin: '30rpx 0' }}></Divider>}
</>
@ -406,14 +247,15 @@ const saleStatistic = () => {
</View>
<Divider direction='horizontal' customStyles={{ margin: '30rpx 0' }}></Divider>
<View className={styles.totalSummary}>
<ToolTip placement='top' content={paymentAmountForm.summary.tips}>
<ToolTip placement='top' content={PaymentAmountForm.summary.tips}>
<View className='flex-row items-center'>
<Text className={styles['totalSummary--title']}>{paymentAmountForm.summary.summaryTitle}</Text>
<Text className={styles['totalSummary--title']}>{PaymentAmountForm.summary.summaryTitle}</Text>
<Iconfont name='icon-tishi' size={36} color='#707070'></Iconfont>
</View>
</ToolTip>
<View className={classnames(styles['totalSummary--current'], PaymentAmountForm.summary.value.cls)}>{PaymentAmountForm.summary.value.num}</View>
</View>
{Object.entries(paymentAmountForm.form).map(([key, value]) => {
{Object.entries(PaymentAmountForm.form).map(([key, value]) => {
return (
<Cell
key={key}
@ -425,7 +267,8 @@ const saleStatistic = () => {
</View>
</ToolTip>
}
desc={value.value}
desc={value.value.num}
customDescClassName={value.value.cls}
customClassName={styles['cell-desc']}></Cell>
)
})}
@ -443,7 +286,9 @@ const saleStatistic = () => {
<Iconfont name='icon-tishi' size={36} color='#707070'></Iconfont>
</View>
</ToolTip>
<View className={styles['totalSummary--current']}>{ReturnGoodsOrderForm.summary.value}</View>
<View className={classnames(styles['totalSummary--current'], ReturnGoodsOrderForm.summary.value.cls)}>
{ReturnGoodsOrderForm.summary.value.num}
</View>
</View>
{Object.entries(ReturnGoodsOrderForm.form).map(([key, value]) => {
return (
@ -457,39 +302,282 @@ const saleStatistic = () => {
</View>
</ToolTip>
}
desc={value.value}
desc={value.value.num}
customDescClassName={value.value.cls}
customClassName={styles['cell-desc']}></Cell>
)
})}
</LayoutBlock>
{/* 销售排行 */}
<LayoutBlock circle flexDirection='col' customStyle={{ padding: 0 }}>
<View className={classnames(styles.rankingIndicatorTitle, 'flex-row justify-between')} style={{ position: 'relative' }}>
<View className='flex-row items-center'>
<Iconfont name='icon-paiming' size={32}></Iconfont>
<Text className={styles.title}></Text>
</View>
<View style={{ width: '90px' }}>
<SelectSaleRankingIndicators onChange={onChangeIndicators}></SelectSaleRankingIndicators>
</View>
</View>
<View style={{ padding: '0 32rpx' }}>
<Divider direction='horizontal' customStyles={{ margin: '10rpx 0 30rpx 0' }}></Divider>
<View className={styles.rankingTabs} onClick={handleClickTab}>
{tabsConfig.map(item => {
return (
<View data-key={item.key} className={classnames(styles.rankingTab, item.key === currentKey ? styles.active : '')} key={item.key}>
{item.name}
</View>
)
})}
</View>
<Table columns={examplecolumns} dataSource={exampledataSource}></Table>
</View>
</LayoutBlock>
<RankingBlock saleType={saleType} saleDepartmentId={saleDepartmentId} date_min={dateRange.date_min} date_max={dateRange.date_max}></RankingBlock>
</View>
</View>
)
}
//需要传进来的数据示例
//需要传进来的表头数据示例
const productRankingColumns = [
{
key: 'index',
title: '编号',
dataIndex: 'index',
width: '20%',
},
{
key: 'product_name',
title: '面料名称',
dataIndex: 'product_name',
width: '20%',
ellipsis: {
isEllipsis: true,
rows: 2,
},
},
{
key: 'roll',
title: '匹数',
dataIndex: 'roll',
width: '30%',
},
{
key: 'sales_amount',
title: '交易金额',
dataIndex: 'sales_amount',
width: '30%',
render: (text: string) => <Text className={styles.amount}>{text}</Text>,
},
]
//需要传进来的表头数据示例
const purchaserRankingColumns = [
{
key: 'index',
title: '编号',
dataIndex: 'index',
width: '20%',
},
{
key: 'purchaser_name',
title: '客户名称',
dataIndex: 'purchaser_name',
width: '20%',
ellipsis: {
isEllipsis: true,
rows: 2,
},
},
{
key: 'roll',
title: '交易匹数',
dataIndex: 'roll',
width: '30%',
},
{
key: 'sales_amount',
title: '交易金额',
dataIndex: 'sales_amount',
width: '30%',
render: (text: string) => <Text className={styles.amount}>{text}</Text>,
},
]
//需要传进来的表头数据示例
const salesmanRankingColumns = [
{
key: 'index',
title: '编号',
dataIndex: 'index',
width: '20%',
},
{
key: 'sale_user_name',
title: '业务员名称',
dataIndex: 'sale_user_name',
width: '25%',
ellipsis: {
isEllipsis: true,
rows: 2,
},
},
{
key: 'roll',
title: '销售匹数',
dataIndex: 'roll',
width: '25%',
},
{
key: 'sales_amount',
title: '销售金额',
dataIndex: 'sales_amount',
width: '30%',
render: (text: string) => <Text className={styles.amount}>{text}</Text>,
},
]
const tabsConfig = [
{
name: '面料',
key: 0,
},
{
name: '客户',
key: 1,
},
{
name: '业务员',
key: 2,
},
]
interface RankingBlockPropsType {
saleType?: number | null
saleDepartmentId?: number | null
date_min?: string
date_max?: string
}
// 销售排行
const RankingBlock = memo<RankingBlockPropsType>(props => {
const { saleType, saleDepartmentId, date_min, date_max } = props
const { fetchData: fetchProductRank } = ProductRankApi()
const { fetchData: fetchPurchaserRank } = PurchaserRankApi()
const { fetchData: fetchSalesmanRank } = SalesmanRankApi()
let [limit, setLimit] = useState(defaultLimit)
const [indicator, setIndicator] = useState<number | null>(null)
// 切换排行指标
const onChangeIndicators = useCallback((indicators: number) => {
console.log('indicators', indicators)
if (indicators === -1) {
setIndicator(null)
} else {
setIndicator(indicators)
}
}, [])
const [currentKey, setCurrentKey] = useState(tabsConfig[0].key)
const handleClickTab = event => {
const key = event.target.dataset.key
if (key === currentKey) return
setCurrentKey(key)
setLimit(defaultLimit)
}
const getData = useCallback(
async (tabKey: number) => {
let res: any
const payload = {
limit,
saleType,
saleDepartmentId,
date_min,
date_max,
data_form_status: indicator,
}
if (tabKey === 0) {
res = await fetchProductRank(getFilterData(payload))
} else if (tabKey === 1) {
res = await fetchPurchaserRank(getFilterData(payload))
} else {
res = await fetchSalesmanRank(getFilterData(payload))
}
if (res.data) {
console.log('排名', res.data)
if (tabKey === 0) {
setCurrentTable(() => ({
columns: productRankingColumns,
dataSource: {
list: res.data.list.map((item, index: number) => ({
key: index,
index: index + 1,
product_name: item.product_name || '--',
sales_amount: `${priceformat(item.sales_amount)}`,
roll: dataUnit(item.roll),
})),
total: res.data.total,
},
}))
} else if (tabKey === 1) {
setCurrentTable(() => ({
columns: purchaserRankingColumns,
dataSource: {
list: res.data.list.map((item, index: number) => ({
key: index,
index: index + 1,
purchaser_name: item.purchaser_name || '--',
sales_amount: `${priceformat(item.sales_amount)}`,
roll: dataUnit(item.roll),
})),
total: res.data.total,
},
}))
} else {
setCurrentTable(() => ({
columns: salesmanRankingColumns,
dataSource: {
list: res.data.list.map((item, index: number) => ({
key: index,
index: index + 1,
sale_user_name: item.sale_user_name || '--',
sales_amount: `${priceformat(item.sales_amount)}`,
roll: dataUnit(item.roll),
})),
total: res.data.total,
},
}))
}
}
},
[limit, saleType, saleDepartmentId, date_min, date_max, indicator],
)
useEffect(() => {
getData(currentKey)
}, [currentKey, getData])
const handleLoadMore = () => {
console.log('loadmore')
// TODO优化结合接口的offset 和 limit 分段请求接口然后通过 push 将旧数据和新数据拼接起来
setLimit(v => v + defaultLimit)
}
const [currentTable, setCurrentTable] = useState<TablePropsType>({
columns: productRankingColumns,
})
return (
<>
{/* 销售排行 */}
<LayoutBlock circle flexDirection='col' customStyle={{ padding: 0 }}>
<View className={classnames(styles.rankingIndicatorTitle, 'flex-row justify-between')} style={{ position: 'relative' }}>
<View className='flex-row items-center'>
<Iconfont name='icon-paiming' size={32}></Iconfont>
<Text className={styles.title}></Text>
</View>
<View style={{ width: '90px' }}>
<SelectSaleRankingIndicators onChange={onChangeIndicators}></SelectSaleRankingIndicators>
</View>
</View>
<View style={{ padding: '0 32rpx' }}>
<Divider direction='horizontal' customStyles={{ margin: '10rpx 0 30rpx 0' }}></Divider>
<View className={styles.rankingTabs} onClick={handleClickTab}>
{tabsConfig.map(item => {
return (
<View data-key={item.key} className={classnames(styles.rankingTab, item.key === currentKey ? styles.active : '')} key={item.key}>
{item.name}
</View>
)
})}
</View>
<Table columns={currentTable.columns} dataSource={currentTable.dataSource} onLoadMore={handleLoadMore}></Table>
</View>
</LayoutBlock>
</>
)
})
export default saleStatistic

View File

@ -80,3 +80,12 @@ $customTabBarHeight: 100px;
.color-white{
color: white;
}
.s-w::after {
content: 'W';
font-size: $font_size;
}
.s-e::after {
content: 'E';
font-size: $font_size;
}