diff --git a/src/common/format.js b/src/common/format.js index 280a7d0..ff1a2e2 100644 --- a/src/common/format.js +++ b/src/common/format.js @@ -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 +} diff --git a/src/common/util.ts b/src/common/util.ts index f99bf64..4521389 100644 --- a/src/common/util.ts +++ b/src/common/util.ts @@ -117,7 +117,7 @@ function delay(delayTime = 25): Promise { }) } -function delayQuerySelector( +export function delayQuerySelector( selectorStr: string, delayTime = 500 ): Promise { @@ -170,6 +170,5 @@ export const shareShop = () => { } } } -export { - delayQuerySelector -} + + diff --git a/src/components/LoadMore/index.tsx b/src/components/LoadMore/index.tsx index 7e0ca73..d1797c2 100644 --- a/src/components/LoadMore/index.tsx +++ b/src/components/LoadMore/index.tsx @@ -29,7 +29,7 @@ const LoadMore: FC = props => { component = } else if (status === 'more') { component = ( - + {moreText} diff --git a/src/components/SelectMarketingDepartment/index.tsx b/src/components/SelectMarketingDepartment/index.tsx index 0cf05ab..27409a4 100644 --- a/src/components/SelectMarketingDepartment/index.tsx +++ b/src/components/SelectMarketingDepartment/index.tsx @@ -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 = props => { +const SelectSaleType: FC = memo((props) => { const selectName = '营销部门' @@ -64,5 +64,5 @@ const SelectSaleType: FC = props => { ) -} +}) export default SelectSaleType diff --git a/src/components/SelectSaleRankingIndicators/index.tsx b/src/components/SelectSaleRankingIndicators/index.tsx index 9417fdb..574d234 100644 --- a/src/components/SelectSaleRankingIndicators/index.tsx +++ b/src/components/SelectSaleRankingIndicators/index.tsx @@ -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 = props => { +const SelectSaleRankingIndicators: FC = memo((props) => { const selectName = '排行指标' @@ -65,5 +65,5 @@ const SelectSaleRankingIndicators: FC = props => { ) -} +}) export default SelectSaleRankingIndicators diff --git a/src/components/SelectSaleType/index.tsx b/src/components/SelectSaleType/index.tsx index 44c8e81..528034f 100644 --- a/src/components/SelectSaleType/index.tsx +++ b/src/components/SelectSaleType/index.tsx @@ -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 = props => { +const SelectSaleType: FC = 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 = props => { getData() }, []) - const [currentValue, setCurrentValue] = useState(-1) + const [currentValue, setCurrentValue] = useState(defaultValue) const handleClick = (value: ChangedValue) => { setCurrentValue(value) @@ -63,5 +63,5 @@ const SelectSaleType: FC = props => { ) -} +}) export default SelectSaleType diff --git a/src/components/SelectTimePicker/index.tsx b/src/components/SelectTimePicker/index.tsx index eed4faf..b74fd50 100644 --- a/src/components/SelectTimePicker/index.tsx +++ b/src/components/SelectTimePicker/index.tsx @@ -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 = props => { - const { onChange: change } = props +const SelectTimePicker: FC = 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 = 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 = 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 ( <> - {Object.entries(FilterTimeOptions) + {Object.entries(Options.current) .slice(0, -1) .map(([key, value]) => { return ( @@ -136,14 +143,14 @@ const SelectTimePicker: FC = props => { ) })} - - {customFilterButtonText} - + + {customFilterButtonText.current} + ) -} +}) export default SelectTimePicker diff --git a/src/components/cell/index.tsx b/src/components/cell/index.tsx index abdb217..ccea8cc 100644 --- a/src/components/cell/index.tsx +++ b/src/components/cell/index.tsx @@ -11,10 +11,11 @@ interface CellPropsType { onClick?: () => void customStyle?: React.CSSProperties customClassName?: string + customDescClassName?: string iconName?: IconNames } const Cell:FC = (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 = (props) => { {title} - {desc} + {desc} {isLink && } diff --git a/src/components/dropDown-item/index.module.scss b/src/components/dropDown-item/index.module.scss index 777b8bb..b770d80 100644 --- a/src/components/dropDown-item/index.module.scss +++ b/src/components/dropDown-item/index.module.scss @@ -3,7 +3,6 @@ &--title { position: relative; - z-index: 2000; background-color: white; display: flex; flex-flow: row nowrap; diff --git a/src/components/infiniteScroll/index.tsx b/src/components/infiniteScroll/index.tsx index 6837a7b..49bf54a 100644 --- a/src/components/infiniteScroll/index.tsx +++ b/src/components/infiniteScroll/index.tsx @@ -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 ( - <> - 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 && ( - <> - - {children} - - - )) || ( + + const component = () => { + if(enableLoadMoreStatus){ + if (!moreStatus){ + return ( + + {children} + + ) + }else{ + return ( <> {(statusMore == 2 || statusMore == 3) && ( @@ -117,9 +104,39 @@ export default memo( {statusMore == 0 && } {statusMore == 1 && } - )} + ) + } + + }else{ + return ( + + {children} + + ) + } + } - + return ( + <> + 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 && } ) diff --git a/src/components/popup/index.module.scss b/src/components/popup/index.module.scss index 61f10bb..b161411 100644 --- a/src/components/popup/index.module.scss +++ b/src/components/popup/index.module.scss @@ -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; + } } } diff --git a/src/components/popup/index.tsx b/src/components/popup/index.tsx index d2fedfe..4bbe861 100644 --- a/src/components/popup/index.tsx +++ b/src/components/popup/index.tsx @@ -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 ( - <> - - - - e.stopPropagation()}> - {showTitle && {title}} - {showIconButton && ( - - - - )} - - - {children} + + + + e.stopPropagation()}> + {showTitle && {title}} + {showIconButton && ( + + - {safeAreaInsetBottom && } + )} + + + {children} + {safeAreaInsetBottom && } - + ) }, ) diff --git a/src/components/sideBar/index.tsx b/src/components/sideBar/index.tsx index d601151..8b59141 100644 --- a/src/components/sideBar/index.tsx +++ b/src/components/sideBar/index.tsx @@ -106,7 +106,7 @@ export default memo(({list = [], } - selfOnScrolltolower?.()} refresherTriggered={refresherTriggered} refresherEnabled={true} selfOnRefresherRefresh={() => selfOnRefresherRefresh?.()}> + selfOnScrolltolower?.()} refresherTriggered={refresherTriggered} refresherEnabled={true} selfOnRefresherRefresh={() => selfOnRefresherRefresh?.()}> {children} @@ -114,4 +114,4 @@ export default memo(({list = [], ) -}) \ No newline at end of file +}) diff --git a/src/components/table/index.tsx b/src/components/table/index.tsx index 3cf8233..33d13dc 100644 --- a/src/components/table/index.tsx +++ b/src/components/table/index.tsx @@ -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 = props => { - const { columns, dataSource } = props - - - const [showMore, setShowMore] = useState(false) - - const [loadMoreStatus, setLoadMoreStatus] = useState('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 = props => { } } return columnStyle - } + }, []) + + const loadMoreComponent = useMemo(() => { + if (dataSource) { + if (dataSource.list.length < dataSource.total) { + return + } else if (dataSource.list.length >= dataSource.total) { + return + } + } else { + return + } + }, [dataSource]) const sourceContainer = () => { return ( <> - {!!dataSource.length && - dataSource.map(source => { + {!!dataSource?.list?.length && + dataSource.list.map(source => { return ( {columns.map(column => { @@ -81,9 +90,7 @@ const Table: FC = props => { ) })} - {showMore && ( - - )} + {loadMoreComponent} ) } @@ -99,7 +106,9 @@ const Table: FC = props => { ) })} - {sourceContainer()} + + {sourceContainer()} + ) } diff --git a/src/pages/saleStatistic/config.ts b/src/pages/saleStatistic/config.ts new file mode 100644 index 0000000..86b59d9 --- /dev/null +++ b/src/pages/saleStatistic/config.ts @@ -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: '', + }, + }, + }, +} + diff --git a/src/pages/saleStatistic/index.module.scss b/src/pages/saleStatistic/index.module.scss index ec45fa1..267413f 100644 --- a/src/pages/saleStatistic/index.module.scss +++ b/src/pages/saleStatistic/index.module.scss @@ -87,3 +87,5 @@ page { .amount { color: $color_main; } + + diff --git a/src/pages/saleStatistic/index.tsx b/src/pages/saleStatistic/index.tsx index 965a2de..0ae2601 100644 --- a/src/pages/saleStatistic/index.tsx +++ b/src/pages/saleStatistic/index.tsx @@ -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}, + '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(null) + const [saleType, setSaleType] = useState(0) const [saleDepartmentId, setSaleDepartmentId] = useState(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 ( {/* */} - + @@ -343,8 +177,11 @@ const saleStatistic = () => { - {OrderForm.summary.value} - (共 {OrderForm.summary.total} 匹) + {OrderForm.summary.value.num} + + (共 {OrderForm.summary.total.num} + 匹) + {Object.entries(OrderForm.form).map(([key, value]) => { return ( @@ -358,7 +195,8 @@ const saleStatistic = () => { } - desc={value.value} + desc={value.value.num} + customDescClassName={value.value.cls} customClassName={styles['cell-desc']}> ) })} @@ -376,8 +214,10 @@ const saleStatistic = () => { - {ArrangedForm.summary.value} - (共计 {ArrangedForm.summary.total}) + {ArrangedForm.summary.value.num} + + (共计 {ArrangedForm.summary.total.num}) + {Object.entries(ArrangedForm.form).map(([key, value], index) => { return ( @@ -392,7 +232,8 @@ const saleStatistic = () => { } - desc={value.value} + desc={value.value.num} + customDescClassName={value.value.cls} customClassName={styles['cell-desc']}> {(index + 1) % 3 === 0 && } @@ -406,14 +247,15 @@ const saleStatistic = () => { - + - {paymentAmountForm.summary.summaryTitle} + {PaymentAmountForm.summary.summaryTitle} + {PaymentAmountForm.summary.value.num} - {Object.entries(paymentAmountForm.form).map(([key, value]) => { + {Object.entries(PaymentAmountForm.form).map(([key, value]) => { return ( { } - desc={value.value} + desc={value.value.num} + customDescClassName={value.value.cls} customClassName={styles['cell-desc']}> ) })} @@ -443,7 +286,9 @@ const saleStatistic = () => { - {ReturnGoodsOrderForm.summary.value} + + {ReturnGoodsOrderForm.summary.value.num} + {Object.entries(ReturnGoodsOrderForm.form).map(([key, value]) => { return ( @@ -457,39 +302,282 @@ const saleStatistic = () => { } - desc={value.value} + desc={value.value.num} + customDescClassName={value.value.cls} customClassName={styles['cell-desc']}> ) })} - {/* 销售排行 */} - - - - - 销售排行 - - - - - - - - - {tabsConfig.map(item => { - return ( - - {item.name} - - ) - })} - -
-
-
+ ) } +//需要传进来的数据示例 + +//需要传进来的表头数据示例 +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}, + }, +] + +//需要传进来的表头数据示例 +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}, + }, +] + +//需要传进来的表头数据示例 +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}, + }, +] + +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(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(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({ + columns: productRankingColumns, + }) + + return ( + <> + {/* 销售排行 */} + + + + + 销售排行 + + + + + + + + + {tabsConfig.map(item => { + return ( + + {item.name} + + ) + })} + +
+
+
+ + ) +}) + export default saleStatistic diff --git a/src/styles/common.scss b/src/styles/common.scss index 5e761aa..d9afae8 100644 --- a/src/styles/common.scss +++ b/src/styles/common.scss @@ -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; +}