✨ feat(Table|LoadMore组件): 新增Table和LoadMore组件
This commit is contained in:
parent
7bf3fedf9c
commit
3199628d4f
9
src/components/LoadMore/index.module.scss
Normal file
9
src/components/LoadMore/index.module.scss
Normal file
@ -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;
|
||||||
|
}
|
42
src/components/LoadMore/index.tsx
Normal file
42
src/components/LoadMore/index.tsx
Normal file
@ -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<LoadMorePropsType> = props => {
|
||||||
|
const { status, moreText = '查看更多', loadingText = '加载中', noMoreText = '没有更多', onClick } = props
|
||||||
|
|
||||||
|
const handleShowMore = () => {
|
||||||
|
onClick && onClick()
|
||||||
|
}
|
||||||
|
|
||||||
|
let component: JSX.Element | null = null
|
||||||
|
if (status === 'loading') {
|
||||||
|
component = <LoadingCard title={loadingText}></LoadingCard>
|
||||||
|
} else if (status === 'more') {
|
||||||
|
component = (
|
||||||
|
<View onClick={handleShowMore}>
|
||||||
|
<Text style={{ marginRight: '5px' }}>{moreText}</Text>
|
||||||
|
<Iconfont name='icon-zhankai' size={32}></Iconfont>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
component = <Text>{noMoreText}</Text>
|
||||||
|
}
|
||||||
|
return <View className={styles.loadMore}>{component}</View>
|
||||||
|
}
|
||||||
|
export default LoadMore
|
@ -2,5 +2,5 @@
|
|||||||
padding: 24px 40px;
|
padding: 24px 40px;
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-gap: 24px 24px;
|
grid-gap: 24px 24px;
|
||||||
grid-template-columns: 1fr 1fr;
|
grid-template-columns: 1fr 1fr 1fr;
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import FilterButton from '../filterButton'
|
|||||||
import { EnumMarketingDepartmentApi } from '@/api/index'
|
import { EnumMarketingDepartmentApi } from '@/api/index'
|
||||||
import { View } from '@tarojs/components'
|
import { View } from '@tarojs/components'
|
||||||
import styles from './index.module.scss'
|
import styles from './index.module.scss'
|
||||||
|
import classnames from 'classnames'
|
||||||
|
|
||||||
type ChangedValue = string | number
|
type ChangedValue = string | number
|
||||||
|
|
||||||
@ -52,7 +53,7 @@ const SelectSaleRankingIndicators: FC<SelectSaleTypeProps> = props => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<DropDownItem title={displayTitle} value={currentValue} activeColor='#337fff' showOverlay={false}>
|
<DropDownItem title={displayTitle} value={currentValue} activeColor='#337fff' showOverlay={false}>
|
||||||
<View className={styles.grid}>
|
<View className={classnames(styles.grid)}>
|
||||||
{!!enumList.length &&
|
{!!enumList.length &&
|
||||||
enumList.map((item: EnumList) => {
|
enumList.map((item: EnumList) => {
|
||||||
return (
|
return (
|
||||||
|
@ -4,12 +4,10 @@ import style from "./index.module.scss"
|
|||||||
import { memo } from "react";
|
import { memo } from "react";
|
||||||
|
|
||||||
type Params = {
|
type Params = {
|
||||||
styleLoading?: Object,
|
|
||||||
title?: string,
|
title?: string,
|
||||||
loadingIcon?: false|true
|
loadingIcon?: false|true
|
||||||
}
|
}
|
||||||
export default memo(({
|
export default memo(({
|
||||||
styleLoading = {},
|
|
||||||
title = "加载中...", //显示的文字
|
title = "加载中...", //显示的文字
|
||||||
loadingIcon = true //是否显示加载图标
|
loadingIcon = true //是否显示加载图标
|
||||||
}:Params) => {
|
}:Params) => {
|
||||||
@ -22,4 +20,4 @@ export default memo(({
|
|||||||
</View>
|
</View>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
@ -70,8 +70,9 @@ $am-ms: 200ms;
|
|||||||
bottom: 0;
|
bottom: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
min-height: 200px;
|
min-height: 200px;
|
||||||
width: 100vw;
|
width: 100%;
|
||||||
border-radius: 20px 20px 0px 0px;
|
border-radius: 20px 20px 0px 0px;
|
||||||
|
box-shadow: 1px 1px 1px 1px #f2f2f2;
|
||||||
transform: translate3d(0, 100%, 0);
|
transform: translate3d(0, 100%, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,8 +80,9 @@ $am-ms: 200ms;
|
|||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
min-height: 200px;
|
min-height: 200px;
|
||||||
width: 100vw;
|
width: 100%;
|
||||||
border-radius: 0 0 20px 20px;
|
border-radius: 0 0 20px 20px;
|
||||||
|
box-shadow: 6px 6px 5px 14px red;
|
||||||
transform: translate3d(0, -100%, 0);
|
transform: translate3d(0, -100%, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
50
src/components/table/index.module.scss
Normal file
50
src/components/table/index.module.scss
Normal file
@ -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)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
106
src/components/table/index.tsx
Normal file
106
src/components/table/index.tsx
Normal file
@ -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<TablePropsType> = props => {
|
||||||
|
const { columns, dataSource } = props
|
||||||
|
|
||||||
|
|
||||||
|
const [showMore, setShowMore] = useState(false)
|
||||||
|
|
||||||
|
const [loadMoreStatus, setLoadMoreStatus] = useState<LoadMoreStatus>('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 (
|
||||||
|
<View className={classnames(styles.tr, styles['bg-line'])} key={source.key}>
|
||||||
|
{columns.map(column => {
|
||||||
|
if (column.render) {
|
||||||
|
return (
|
||||||
|
<View className={styles.td} style={{ width: column.width }}>
|
||||||
|
{/* 判断表头是不是有render 有就执行render */}
|
||||||
|
{column.render(source[column.dataIndex])}
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<View className={classnames(styles.td, getColumnStyle(column))} style={{ width: column.width }}>
|
||||||
|
{
|
||||||
|
source[column.dataIndex] //根据表头填数据
|
||||||
|
}
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})}
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
{showMore && (
|
||||||
|
<LoadMore status={loadMoreStatus} onClick={handleShowMore}></LoadMore>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View className={styles.table}>
|
||||||
|
<View className={classnames(styles.tr, styles['bg-header'])}>
|
||||||
|
{columns.map(column => {
|
||||||
|
return (
|
||||||
|
<View className={styles.th} style={{ width: column.width }} key={column.key}>
|
||||||
|
{column.title}
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</View>
|
||||||
|
<ScrollView>{sourceContainer()}</ScrollView>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
export default Table
|
@ -51,3 +51,39 @@ page {
|
|||||||
font-size: $font_size;
|
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;
|
||||||
|
}
|
||||||
|
@ -8,6 +8,7 @@ import SelectMarketingDepartment from '@/components/SelectMarketingDepartment'
|
|||||||
import SelectSaleRankingIndicators from '@/components/SelectSaleRankingIndicators'
|
import SelectSaleRankingIndicators from '@/components/SelectSaleRankingIndicators'
|
||||||
import SelectSaleType from '@/components/SelectSaleType'
|
import SelectSaleType from '@/components/SelectSaleType'
|
||||||
import SelectTimePicker, { ChangedValue } from '@/components/SelectTimePicker'
|
import SelectTimePicker, { ChangedValue } from '@/components/SelectTimePicker'
|
||||||
|
import Table from '@/components/table'
|
||||||
import TimePicker from '@/components/timePicker'
|
import TimePicker from '@/components/timePicker'
|
||||||
import { View, Text } from '@tarojs/components'
|
import { View, Text } from '@tarojs/components'
|
||||||
import classnames from 'classnames'
|
import classnames from 'classnames'
|
||||||
@ -30,8 +31,139 @@ const saleStatistic = () => {
|
|||||||
console.log('indicators', indicators)
|
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 className={styles.amount}>{text}</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 (
|
return (
|
||||||
<View className={styles.saleStatistic}>
|
<View className={styles.saleStatistic}>
|
||||||
|
{/* <View style={{background: 'red', width: '100%', height: '200px'}}></View> */}
|
||||||
<View className={styles['saleStatistic--filterBar']}>
|
<View className={styles['saleStatistic--filterBar']}>
|
||||||
<SelectSaleType onChange={onChangeSaleType}></SelectSaleType>
|
<SelectSaleType onChange={onChangeSaleType}></SelectSaleType>
|
||||||
<SelectMarketingDepartment onChange={onChangeDepartment}></SelectMarketingDepartment>
|
<SelectMarketingDepartment onChange={onChangeDepartment}></SelectMarketingDepartment>
|
||||||
@ -234,8 +366,8 @@ const saleStatistic = () => {
|
|||||||
customClassName={styles['cell-desc']}></Cell>
|
customClassName={styles['cell-desc']}></Cell>
|
||||||
</LayoutBlock>
|
</LayoutBlock>
|
||||||
{/* 销售排行 */}
|
{/* 销售排行 */}
|
||||||
<LayoutBlock circle flexDirection='col'>
|
<LayoutBlock circle flexDirection='col' customStyle={{ padding: 0 }}>
|
||||||
<View className='flex-row justify-between'>
|
<View className={classnames(styles.rankingIndicatorTitle, 'flex-row justify-between')} style={{ position: 'relative' }}>
|
||||||
<View className='flex-row items-center'>
|
<View className='flex-row items-center'>
|
||||||
<Iconfont name='icon-paiming' size={32}></Iconfont>
|
<Iconfont name='icon-paiming' size={32}></Iconfont>
|
||||||
<Text className={styles.title}>销售排行</Text>
|
<Text className={styles.title}>销售排行</Text>
|
||||||
@ -244,10 +376,23 @@ const saleStatistic = () => {
|
|||||||
<SelectSaleRankingIndicators onChange={onChangeIndicators}></SelectSaleRankingIndicators>
|
<SelectSaleRankingIndicators onChange={onChangeIndicators}></SelectSaleRankingIndicators>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
<Divider direction='horizontal' customStyles={{ margin: '30rpx 0' }}></Divider>
|
<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>
|
</LayoutBlock>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default saleStatistic
|
export default saleStatistic
|
||||||
|
Loading…
x
Reference in New Issue
Block a user