diff --git a/src/components/LoadMore/index.module.scss b/src/components/LoadMore/index.module.scss new file mode 100644 index 0000000..6bf198f --- /dev/null +++ b/src/components/LoadMore/index.module.scss @@ -0,0 +1,9 @@ +.loadMore{ + display: flex; + flex-flow: row nowrap; + justify-content: center; + align-items: center; + font-size: 28px; + color: $color_font_three; + padding: 24px 0; +} diff --git a/src/components/LoadMore/index.tsx b/src/components/LoadMore/index.tsx new file mode 100644 index 0000000..7e0ca73 --- /dev/null +++ b/src/components/LoadMore/index.tsx @@ -0,0 +1,42 @@ +import { View, Text } from '@tarojs/components' +import { FC } from 'react' +import Iconfont from '../iconfont/iconfont' +import LoadingCard from '../loadingCard/index' +import styles from './index.module.scss' + +export type LoadMoreStatus = 'more' | 'loading' | 'noMore' + +interface LoadMoreEvent { + onClick?: () => void +} + +interface LoadMorePropsType extends LoadMoreEvent { + status: LoadMoreStatus + moreText?: string + loadingText?: string + noMoreText?: string +} + +const LoadMore: FC = props => { + const { status, moreText = '查看更多', loadingText = '加载中', noMoreText = '没有更多', onClick } = props + + const handleShowMore = () => { + onClick && onClick() + } + + let component: JSX.Element | null = null + if (status === 'loading') { + component = + } else if (status === 'more') { + component = ( + + {moreText} + + + ) + } else { + component = {noMoreText} + } + return {component} +} +export default LoadMore diff --git a/src/components/SelectSaleRankingIndicators/index.module.scss b/src/components/SelectSaleRankingIndicators/index.module.scss new file mode 100644 index 0000000..a1cb97d --- /dev/null +++ b/src/components/SelectSaleRankingIndicators/index.module.scss @@ -0,0 +1,6 @@ +.grid { + padding: 24px 40px; + display: grid; + grid-gap: 24px 24px; + grid-template-columns: 1fr 1fr 1fr; +} diff --git a/src/components/SelectSaleRankingIndicators/index.tsx b/src/components/SelectSaleRankingIndicators/index.tsx new file mode 100644 index 0000000..8770dc5 --- /dev/null +++ b/src/components/SelectSaleRankingIndicators/index.tsx @@ -0,0 +1,69 @@ +import { FC, useEffect, useMemo, useState } from 'react' +import DropDownItem from '../dropDown-item' +import FilterButton from '../filterButton' +import { EnumMarketingDepartmentApi } from '@/api/index' +import { View } from '@tarojs/components' +import styles from './index.module.scss' +import classnames from 'classnames' + +type ChangedValue = string | number + +interface SelectSaleTypeProps { + onChange?: (value: ChangedValue) => void +} + +type EnumList = { + id: number + code: string + name: string +} +// 销售排行指标 +const SelectSaleRankingIndicators: FC = props => { + + const selectName = '排行指标' + + const { onChange } = props + console.log(props) + const { fetchData } = EnumMarketingDepartmentApi() + + const getData = async () => { + const res = await fetchData() + setEnumList([{ id: -1, code: '', name: '全部' }, ...res.data.list]) + } + + const [enumList, setEnumList] = useState([]) + + useEffect(() => { + getData() + }, []) + + const [currentValue, setCurrentValue] = useState(-1) + + const handleClick = (value: ChangedValue) => { + setCurrentValue(value) + onChange?.(value) + } + + const displayTitle = useMemo(() => { + if (currentValue === -1) { + return selectName + } + return !!enumList.length ? enumList.filter(option => option.id === currentValue)?.[0]?.name : selectName + }, [enumList, currentValue]) + + return ( + + + {!!enumList.length && + enumList.map((item: EnumList) => { + return ( + handleClick(item.id)}> + {item.name} + + ) + })} + + + ) +} +export default SelectSaleRankingIndicators diff --git a/src/components/SelectTimePicker/index.tsx b/src/components/SelectTimePicker/index.tsx index 3b0cc80..eed4faf 100644 --- a/src/components/SelectTimePicker/index.tsx +++ b/src/components/SelectTimePicker/index.tsx @@ -1,13 +1,14 @@ +import { formatDateTime } from '@/common/format' import { View, Text } from '@tarojs/components' import dayjs from 'dayjs' import { FC, useState } from 'react' import DropDownItem from '../dropDown-item' import FilterButton from '../filterButton' import IconFont from '../iconfont/iconfont' -import TimePicker from '../timePicker' +import TimePickerPopup from '../timePickerPopup' import styles from './index.module.scss' -type ChangedValue = string | number +export type ChangedValue = string[] interface SelectSaleTypeProps { onChange?: (value: ChangedValue) => void @@ -16,8 +17,8 @@ interface SelectSaleTypeProps { const FilterTimeOptions = { '0': { name: '全部', - date_min: undefined, - date_max: undefined, + date_min: '', + date_max: '', }, '1': { name: '今天', @@ -64,50 +65,85 @@ const FilterTimeOptions = { .add(0, 'day') .format('YYYY-MM-DD')} 00:00:00`, }, -} as const + '6': { + name: '自定义时间', + date_min: '', + date_max: '', + }, +} type Key = keyof typeof FilterTimeOptions -type Value = (typeof FilterTimeOptions)[Key] +type Value = typeof FilterTimeOptions[Key] const SelectTimePicker: FC = props => { const { onChange: change } = props + const [currentValue, setCurrentValue] = useState('0') const [currentDate, setCurrentDate] = useState({ - start: new Date(), - end: new Date(), + start: new Date().toLocaleDateString(), + end: '', }) - + // 展示时间筛选 + const [showTime, setShowTime] = useState(false) + + // 点击关闭时间筛选 + const handClose = () => { + setShowTime(false) - const onSelectDate = time => { - console.log(time) - change?.(time) } const handleClick = (key: Key) => { setCurrentValue(key) + change?.([FilterTimeOptions[key].date_min, FilterTimeOptions[key].date_max]) + setCustomFilterButtonText('自定义时间') + } + // 选择时间 + const onSelectDate = event => { + console.log(event?.value, 'event?.value?.start') + setCurrentDate({ + start: event?.value?.start, + end: event?.value?.end, + }) + setShowTime(false) + setCustomFilterButtonText(`${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 handleCustomTime = () => { + setCurrentValue('6') + setShowTime(true) } return ( - - - {Object.entries(FilterTimeOptions).map(([key, value]) => { - return ( - handleClick(key as Key)}> - {value.name} - - ) - })} - handleClick('6' as Key)}> - 自定义时间 - - - - - - - + <> + + + {Object.entries(FilterTimeOptions) + .slice(0, -1) + .map(([key, value]) => { + return ( + handleClick(key as Key)}> + {value.name} + + ) + })} + + {customFilterButtonText} + + + + + + ) } export default SelectTimePicker diff --git a/src/components/cell/index.tsx b/src/components/cell/index.tsx index f5c65ee..abdb217 100644 --- a/src/components/cell/index.tsx +++ b/src/components/cell/index.tsx @@ -5,7 +5,7 @@ import IconFont, { IconNames } from "../iconfont/iconfont" import styles from './index.module.scss' interface CellPropsType { - title: string + title: string | React.ReactNode desc: string isLink?: boolean onClick?: () => void @@ -28,7 +28,7 @@ const Cell:FC = (props) => { {iconName && } - {title} + {title} {desc} diff --git a/src/components/dropDown-item/index.tsx b/src/components/dropDown-item/index.tsx index 3586ad4..ba2bc2c 100644 --- a/src/components/dropDown-item/index.tsx +++ b/src/components/dropDown-item/index.tsx @@ -1,3 +1,7 @@ +/** + * 注意:需要在父节点设置 position: relative; + */ + import { View, Text } from '@tarojs/components' import { useEffect, useMemo, useRef, useState } from 'react' import styles from './index.module.scss' diff --git a/src/components/loadingCard/index.tsx b/src/components/loadingCard/index.tsx index 6d4ff3e..0053f4a 100644 --- a/src/components/loadingCard/index.tsx +++ b/src/components/loadingCard/index.tsx @@ -4,12 +4,10 @@ import style from "./index.module.scss" import { memo } from "react"; type Params = { - styleLoading?: Object, title?: string, loadingIcon?: false|true } export default memo(({ - styleLoading = {}, title = "加载中...", //显示的文字 loadingIcon = true //是否显示加载图标 }:Params) => { @@ -22,4 +20,4 @@ export default memo(({ ) -}) \ No newline at end of file +}) diff --git a/src/components/popup/index.module.scss b/src/components/popup/index.module.scss index 88cf2d4..61f10bb 100644 --- a/src/components/popup/index.module.scss +++ b/src/components/popup/index.module.scss @@ -70,8 +70,9 @@ $am-ms: 200ms; bottom: 0; left: 0; min-height: 200px; - width: 100vw; + width: 100%; border-radius: 20px 20px 0px 0px; + box-shadow: 1px ​1px 1px 1px #f2f2f2; transform: translate3d(0, 100%, 0); } @@ -79,8 +80,9 @@ $am-ms: 200ms; top: 0; left: 0; min-height: 200px; - width: 100vw; + width: 100%; border-radius: 0 0 20px 20px; + box-shadow: 6px ​6px 5px 14px red; transform: translate3d(0, -100%, 0); } diff --git a/src/components/table/index.module.scss b/src/components/table/index.module.scss new file mode 100644 index 0000000..d048d3e --- /dev/null +++ b/src/components/table/index.module.scss @@ -0,0 +1,50 @@ +.table { + border: 0px solid darkgray; + border-radius: 5px; + font-size: 22px; + color: #333; +} + +.tr { + display: flex; + width: 100%; + justify-content: center; + align-items: center; + padding: 24px 0; + border-bottom: 1px solid #f7f7f7; +} + +.td { + justify-content: center; + text-align: center; + align-items: center; + display: flex; + font-size: 26px; +} + +.th{ + font-size: 26px; +} + +.bg-line { + background: #fff; +} + +.bg-header { + justify-content: center; + background: #f6f7fb; + color: $color_font_three; + display: flex; + align-items: center; + text-align: center; + border-radius: 8px; +} + +.ellipsis_1{ + @include common_ellipsis(1) +} +.ellipsis_2{ + @include common_ellipsis(2) +} + + diff --git a/src/components/table/index.tsx b/src/components/table/index.tsx new file mode 100644 index 0000000..3cf8233 --- /dev/null +++ b/src/components/table/index.tsx @@ -0,0 +1,106 @@ +import { ScrollView, View, Text } from '@tarojs/components' +import classnames from 'classnames' +import { FC, 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 = { + title: string + dataIndex: string + width: string + key: string + render?: (text?: string, record?: RecordType, index?: number) => React.ReactNode + ellipsis?: boolean | { isEllipsis: boolean; rows: number } +} + +type RecordType = { + key: string + [Property: string]: any +} + +interface TablePropsType { + columns: ColumnsType[] + dataSource: RecordType[] +} + +const Table: FC = props => { + const { columns, dataSource } = props + + + const [showMore, setShowMore] = useState(false) + + const [loadMoreStatus, setLoadMoreStatus] = useState('loading') + + const handleShowMore = () => { + + } + + const getColumnStyle = (columnConfig: ColumnsType) => { + const columnStyle = {} + if (typeof columnConfig.ellipsis === 'boolean' && columnConfig.ellipsis) { + columnStyle[styles.ellipsis_1] = true + } + if (typeof columnConfig.ellipsis === 'object' && columnConfig.ellipsis.isEllipsis) { + const rows = columnConfig.ellipsis.rows + if (rows === 2) { + columnStyle[styles.ellipsis_2] = true + } else { + columnStyle[styles.ellipsis_1] = true + } + } + return columnStyle + } + + const sourceContainer = () => { + return ( + <> + {!!dataSource.length && + dataSource.map(source => { + return ( + + {columns.map(column => { + if (column.render) { + return ( + + {/* 判断表头是不是有render 有就执行render */} + {column.render(source[column.dataIndex])} + + ) + } else { + return ( + + { + source[column.dataIndex] //根据表头填数据 + } + + ) + } + })} + + ) + })} + {showMore && ( + + )} + + ) + } + + return ( + + + {columns.map(column => { + return ( + + {column.title} + + ) + })} + + {sourceContainer()} + + ) +} +export default Table diff --git a/src/components/toolTips/index.module.scss b/src/components/toolTips/index.module.scss new file mode 100644 index 0000000..311ceef --- /dev/null +++ b/src/components/toolTips/index.module.scss @@ -0,0 +1,50 @@ +.mark { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: transparent; +} +.tooltip { + &-container{ + position: relative; + } + position: absolute; + left: 0; + top: 0; + user-select: text; + color: white; + &-inner { + position: absolute; + background-color: #333333; + font-size: $font_size; + box-shadow: 0 0 30px 0 rgba(51, 51, 51, 0.2); + border-radius: 8px; + &-content { + padding: 8px 12px; + white-space: nowrap; + } + } + &-hidden { + display: none; + } +} +.arrowIcon { + position: absolute; + display: flex; + justify-content: center; + align-items: center; + &-top { + transform: rotate(0deg); + } + &-left { + transform: rotate(270deg); + } + &-right { + transform: rotate(90deg); + } + &-bottom { + transform: rotate(180deg); + } +} diff --git a/src/components/toolTips/index.tsx b/src/components/toolTips/index.tsx new file mode 100644 index 0000000..c8fc8f2 --- /dev/null +++ b/src/components/toolTips/index.tsx @@ -0,0 +1,216 @@ +import { View } from '@tarojs/components' +import Taro from '@tarojs/taro' +import classNames from 'classnames' +import { forwardRef, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react' +import IconFont from '../iconfont/iconfont' +import styles from './index.module.scss' + +const SystemWidth = Taro.getSystemInfoSync().windowWidth + +const arrowSize = 32 + +// 由于taro自动把px编译成rpx,所以这里需要把单位处理一下 转成真正的px +const convertPx = (px: number) => { + const realPx = (px / 750) * SystemWidth + return realPx +} + +type Placement = 'top' | 'right' | 'bottom' | 'left' + +interface ToolTipEvent { + onVisibleChange?: (visible?: boolean) => void +} + +interface ToolTipPropsType extends ToolTipEvent { + defaultVisible?: boolean + content: React.ReactNode + placement?: Placement + children?: React.ReactNode + customClassName?: string + customStyle?: React.CSSProperties + customContentStyle?: React.CSSProperties +} + +interface ToolTipRef { + show: () => void + hide: () => void + visible: boolean +} + +const popoverStyle = { + color: '#333333', +} + +const ToolTip = forwardRef((props, ref) => { + const { placement = 'top', defaultVisible = false, onVisibleChange, children, content = '请填入提示信息', customClassName, customStyle, customContentStyle } = props + + if (!content){ + throw new Error('tooltip: content 不能为空') + } + + const [visible, setVisible] = useState(defaultVisible) + + const onVisibleChangeRef = useRef(onVisibleChange) + onVisibleChangeRef.current = onVisibleChange + + // 暴露方法给外部 + useImperativeHandle( + ref, + () => { + return { + show: () => setVisible(true), + hide: () => setVisible(false), + visible, + } + }, + [visible], + ) + + const handleClick = useCallback(() => { + setVisible(v => { + onVisibleChangeRef.current?.(!v) + return !v + }) + }, []) + + const handleClickMark = useCallback(() => { + setVisible(false) + onVisibleChangeRef.current?.(false) + }, []) + + const getArrowSide = useMemo(() => { + const side = placement.split('-')[0] as string // placement = 'top-start' 取 'top' + + const arrowSide = { + top: 'bottom', + right: 'left', + bottom: 'top', + left: 'right', + }[side] as string + return arrowSide + }, [placement]) + + const [childrenRect, setChildrenRect] = useState({}) + const childrenRectRef = useRef(childrenRect) + childrenRectRef.current = childrenRect + + const [viewport, setViewport] = useState({}) + const viewportRef = useRef(viewport) + viewportRef.current = viewport + + useEffect(() => { + console.log('useLayoutEffect') + const query = Taro.createSelectorQuery() + query.select('#children').boundingClientRect() + query.selectViewport().scrollOffset() + query.exec(res => { + console.log(res[0]) + console.log(res[1]) + setChildrenRect(res[0]) + childrenRectRef.current = res[0] + setViewport(res[1]) + viewportRef.current = res[1] + }) + }, []) + + // 箭头 坐标 + const arrowCoords = useMemo(() => { + console.log('getArrowSide==>', getArrowSide, childrenRectRef.current) + switch (getArrowSide) { + case 'bottom': // 下箭头 + return { + left: childrenRectRef.current.width / 2 - convertPx(arrowSize) / 2, + top: -convertPx(arrowSize), + right: '', + bottom: '', + } + case 'left': // 左箭头 + return { + left: childrenRectRef.current.width, + right: '', + top: childrenRectRef.current.height / 2 - convertPx(arrowSize) / 2, + bottom: '', + } + case 'top': // 上箭头 + return { + left: childrenRectRef.current.width / 2 - convertPx(arrowSize) / 2, + right: '', + top: childrenRectRef.current.height, + bottom: '', + } + case 'right': // 右箭头 + return { + left: -convertPx(arrowSize), + right: '', + top: childrenRectRef.current.height / 2 - convertPx(arrowSize) / 2, + bottom: '', + } + } + }, [getArrowSide, childrenRectRef.current]) + + // content 坐标 + const contentCoords = useMemo(() => { + switch (getArrowSide) { + case 'bottom': // 下箭头 + return { + left: 0, + top: '', + right: '', + bottom: convertPx(arrowSize) - 5, + } + case 'left': // 左箭头 + return { + left: childrenRectRef.current.width + convertPx(arrowSize) - 5, + top: 0, + right: '', + bottom: '', + } + case 'top': // 上箭头 + return { + left: 0, + top: childrenRectRef.current.height + convertPx(arrowSize) - 5, + right: '', + bottom: '', + } + case 'right': // 右箭头 + return { + left: '', + top: 0, + right: convertPx(arrowSize) - 5, + bottom: '', + } + } + }, [getArrowSide, childrenRectRef.current]) + + const ContentComponent = useMemo(() => { + console.log('执行完') + + return ( + + {/* 箭头 */} + + + + {/* content */} + + {content} + + + ) + }, [content, getArrowSide, visible, arrowCoords, contentCoords]) + + return ( + <> + {/* 遮罩层 */} + + + + {children} + + {ContentComponent} + + + ) +}) + +export default ToolTip diff --git a/src/pages/saleStatistic/index.module.scss b/src/pages/saleStatistic/index.module.scss index 2f4d103..ec45fa1 100644 --- a/src/pages/saleStatistic/index.module.scss +++ b/src/pages/saleStatistic/index.module.scss @@ -1,4 +1,11 @@ +page { + height: 100%; + overflow: hidden; +} .saleStatistic { + display: flex; + flex-flow: column nowrap; + height: 100%; &--filterBar { display: flex; flex-flow: row nowrap; @@ -7,4 +14,76 @@ width: 100%; background-color: white; } + &--content { + flex: 1 1 auto; + padding-top: 24px; + overflow-y: scroll; + } +} +.title { + margin: 0 10px; + font-size: $font_size; + color: $color_font_one; +} +.cell-desc { + font-weight: 550; + color: $color_font_one; + font-size: 34px; +} +.totalSummary { + display: flex; + flex-flow: column nowrap; + justify-content: center; + align-items: center; + padding: 24px 0; + &--title { + font-size: $font_size; + margin: 0 10px; + color: $color_font_three; + } + &--current { + color: $color_main; + font-size: 42px; + font-weight: 550; + } + &--totalNum { + color: $color_font_three; + font-size: $font_size; + } +} + +.rankingIndicatorTitle { + position: 'relative'; + padding: 0 32px; +} + +.rankingTabs { + position: relative; + background-color: #f5f5f5; + box-sizing: border-box; + border-radius: 8px; + margin-bottom: 24px; + width: 100%; + display: flex; + flex-flow: row nowrap; + justify-content: space-between; + align-items: center; + .rankingTab { + flex: 1; + padding: 15px; + color: $color_font_one; + background-color: transparent; + text-align: center; + font-size: $font_size; + transition: all 0.1s; + } + .active { + color: white; + border-radius: 8px; + background-color: $color_main; + } +} + +.amount { + color: $color_main; } diff --git a/src/pages/saleStatistic/index.tsx b/src/pages/saleStatistic/index.tsx index 07652e3..9a93d48 100644 --- a/src/pages/saleStatistic/index.tsx +++ b/src/pages/saleStatistic/index.tsx @@ -1,55 +1,401 @@ import AtCalendar from '@/components/calendar' +import Cell from '@/components/cell' +import Divider from '@/components/Divider' import DropDownItem, { DropDownOptions } from '@/components/dropDown-item' +import Iconfont from '@/components/iconfont/iconfont' +import LayoutBlock from '@/components/layoutBlock' import SelectMarketingDepartment from '@/components/SelectMarketingDepartment' +import SelectSaleRankingIndicators from '@/components/SelectSaleRankingIndicators' import SelectSaleType from '@/components/SelectSaleType' -import SelectTimePicker from '@/components/SelectTimePicker' +import SelectTimePicker, { ChangedValue } from '@/components/SelectTimePicker' +import Table from '@/components/table' import TimePicker from '@/components/timePicker' -import { View } from '@tarojs/components' +import ToolTip from '@/components/toolTips' +import { View, Text } from '@tarojs/components' import classnames from 'classnames' import dayjs from 'dayjs' import { useState } from 'react' import styles from './index.module.scss' const saleStatistic = () => { - const [options, setOptions] = useState([ - { - text: 'name', - value: 0, - }, - { - text: 'name1', - value: 1, - }, - { - text: 'name2', - value: 2, - }, - { - text: 'name3', - value: 3, - }, - ]) - - const onChangeTimePicker = (value) => { + const onChangeTimePicker = (value: ChangedValue) => { console.log(value) } - const onChangeSaleType = (saleType) => { - console.log(saleType) - + const onChangeSaleType = (saleType: number) => { + console.log('saleType', saleType) + } + const onChangeDepartment = (department: number) => { + console.log('department', department) } - const onChangeDepartment = (department) => { - console.log(department) + const onChangeIndicators = (indicators: number) => { + console.log('indicators', indicators) + } + + //需要传进来的数据示例 + 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 examplecolumns = [ + { + key: 'username', + title: '编号', + dataIndex: 'username', + width: '20%', + }, + { + key: 'count', + title: '面料名称', + dataIndex: 'count', + width: '20%', + ellipsis: { + isEllipsis: true, + rows: 2, + }, + }, + { + key: 'gb', + title: '匹数', + dataIndex: 'gb', + width: '30%', + }, + { + key: 'dbd', + title: '交易金额', + dataIndex: 'dbd', + width: '30%', + render: (text: string) => {text}, + }, + ] + + 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 ( + {/* */} + + + + + 订单 + + + + + + 订单总数 + + + + 3425 + (共432423匹) + + + 待配布订单 + + + } + desc={'323'} + customClassName={styles['cell-desc']}> + + 已配布订单 + + + } + desc={'2972'} + customClassName={styles['cell-desc']}> + + + + + 配布 + + + + + 已配布匹数 + + + 3425 + (共计 ¥231.23w) + + + 待收款单数 + + + } + desc={'323'} + customClassName={styles['cell-desc']}> + + 待收款匹数 + + + } + desc={'2972'} + customClassName={styles['cell-desc']}> + + 待收款金额 + + + } + desc={'2972'} + customClassName={styles['cell-desc']}> + + + 待发货单数 + + + } + desc={'323'} + customClassName={styles['cell-desc']}> + + 待发货匹数 + + + } + desc={'2972'} + customClassName={styles['cell-desc']}> + + 待发货金额 + + + } + desc={'2972'} + customClassName={styles['cell-desc']}> + + + 已发货单数 + + + } + desc={'2972'} + customClassName={styles['cell-desc']}> + + 已发货匹数 + + + } + desc={'2972'} + customClassName={styles['cell-desc']}> + + 已发货金额 + + + } + desc={'2972'} + customClassName={styles['cell-desc']}> + + + + + 货款 + + + + + 货款金额 + + + 56133.32 + + + 未收金额 + + + } + desc={'2972'} + customClassName={styles['cell-desc']}> + + 已收金额 + + + } + desc={'2972'} + customClassName={styles['cell-desc']}> + + + + + 退货 + + + + + 退货单数 + + + 42 + + + 退货匹数 + + + } + desc={'2972'} + customClassName={styles['cell-desc']}> + + 退货金额 + + + } + desc={'2972'} + customClassName={styles['cell-desc']}> + + {/* 销售排行 */} + + + + + 销售排行 + + + + + + + + + {tabsConfig.map(item => { + return ( + + {item.name} + + ) + })} + +
+
+
+ ) } + export default saleStatistic