✨ feat(销售统计): 时间选择器组件
This commit is contained in:
parent
82c87b75d9
commit
b878c5ea9d
@ -1,4 +1,6 @@
|
|||||||
|
// 关于登录
|
||||||
export { LoginApi } from './login/index'
|
export { LoginApi } from './login/index'
|
||||||
|
|
||||||
export {
|
export {
|
||||||
productabsorbcontrast,
|
productabsorbcontrast,
|
||||||
SelectProductListApi,
|
SelectProductListApi,
|
||||||
@ -9,8 +11,10 @@ export {
|
|||||||
FindColorListApi,
|
FindColorListApi,
|
||||||
} from './product/index'
|
} from './product/index'
|
||||||
|
|
||||||
|
// 关于购物页面
|
||||||
export { ShoppingCartUpdateApi, ShoppingCartDeleteApi, ShoppingCartListApi } from './shopping/index'
|
export { ShoppingCartUpdateApi, ShoppingCartDeleteApi, ShoppingCartListApi } from './shopping/index'
|
||||||
|
|
||||||
|
// 关于发货列表
|
||||||
export {
|
export {
|
||||||
DeliverNoticeOrderList,
|
DeliverNoticeOrderList,
|
||||||
DeliverNoticeOrder,
|
DeliverNoticeOrder,
|
||||||
@ -21,6 +25,7 @@ export {
|
|||||||
EnumSaleorderStatus,
|
EnumSaleorderStatus,
|
||||||
} from './delivery/index'
|
} from './delivery/index'
|
||||||
|
|
||||||
|
// 关于提货列表
|
||||||
export {
|
export {
|
||||||
EnumTakeGoodsOrderStatus,
|
EnumTakeGoodsOrderStatus,
|
||||||
EnumTakeGoodsOrderTypeList,
|
EnumTakeGoodsOrderTypeList,
|
||||||
@ -32,6 +37,9 @@ export {
|
|||||||
GenBarCodeOrQrCode,
|
GenBarCodeOrQrCode,
|
||||||
} from './takeDelivery/index'
|
} from './takeDelivery/index'
|
||||||
|
|
||||||
|
// 关于销售统计
|
||||||
|
export { EnumMarketingDepartmentApi, EnumSalesTypeApi, SalesmanRankApi, ProductRankApi, PurchaserRankApi, SupplierRankApi, CensusApi } from './statistic/index'
|
||||||
|
|
||||||
import { useRequest } from '@/use/useHttp'
|
import { useRequest } from '@/use/useHttp'
|
||||||
/**
|
/**
|
||||||
* 系列列表
|
* 系列列表
|
||||||
|
23
src/api/statistic/enum.ts
Normal file
23
src/api/statistic/enum.ts
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import { useRequest } from "@/use/useHttp"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 销售类型下拉列表
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export const EnumSalesTypeApi = () => {
|
||||||
|
return useRequest({
|
||||||
|
url: `/v1/mp/enum/saleType`,
|
||||||
|
method: 'get',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 营销部门下拉列表
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export const EnumMarketingDepartmentApi = () => {
|
||||||
|
return useRequest({
|
||||||
|
url: `/v1/mp/enum/saleDepartment/list`,
|
||||||
|
method: "get"
|
||||||
|
})
|
||||||
|
}
|
2
src/api/statistic/index.ts
Normal file
2
src/api/statistic/index.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export { EnumSalesTypeApi, EnumMarketingDepartmentApi } from './enum'
|
||||||
|
export { CensusApi, ProductRankApi, PurchaserRankApi, SupplierRankApi, SalesmanRankApi } from './saleStatistic'
|
56
src/api/statistic/saleStatistic.ts
Normal file
56
src/api/statistic/saleStatistic.ts
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
import { useRequest } from '@/use/useHttp'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户列表
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export const CensusApi = () => {
|
||||||
|
return useRequest({
|
||||||
|
url: `/v1/mp/saleOrderDataForm`,
|
||||||
|
method: "get"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 面料销售排行
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export const ProductRankApi = () => {
|
||||||
|
return useRequest({
|
||||||
|
url: `/v1/mp/saleOrderDataForm/product/list`,
|
||||||
|
method: 'get',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户销售排行
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export const PurchaserRankApi = () => {
|
||||||
|
return useRequest({
|
||||||
|
url: `/v1/mp/saleOrderDataForm/purchaser/list`,
|
||||||
|
method: 'get',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 经销商销售排行
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export const SupplierRankApi = () => {
|
||||||
|
return useRequest({
|
||||||
|
url: `/v1/mp/saleOrderDataForm/supplier/list`,
|
||||||
|
method: 'get',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 业务员销售排行
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export const SalesmanRankApi = () => {
|
||||||
|
return useRequest({
|
||||||
|
url: `/v1/mp/saleOrderDataForm/saleUser/list`,
|
||||||
|
method: 'get',
|
||||||
|
})
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
export const BASE_URL = CURRENT_BASE_URL
|
// export const BASE_URL = CURRENT_BASE_URL
|
||||||
// export const BASE_URL = `http://192.168.0.75:50001/lymarket`
|
// export const BASE_URL = `http://192.168.0.75:50001/lymarket`
|
||||||
// export const BASE_URL = `http://192.168.0.89:50001/lymarket`
|
// export const BASE_URL = `http://192.168.0.89:50001/lymarket`
|
||||||
// export const BASE_URL = `http://10.0.0.5:50001/lymarket`
|
// export const BASE_URL = `http://10.0.0.5:50001/lymarket`
|
||||||
@ -12,7 +12,7 @@ export const BASE_URL = CURRENT_BASE_URL
|
|||||||
// export const BASE_URL = `https://dev.zzfzyc.com/lymarket` // 开发环境
|
// export const BASE_URL = `https://dev.zzfzyc.com/lymarket` // 开发环境
|
||||||
// export const BASE_URL = `https://www.zzfzyc.com/lymarket` // 正式环境
|
// export const BASE_URL = `https://www.zzfzyc.com/lymarket` // 正式环境
|
||||||
// export const BASE_URL = `http://192.168.1.5:40001/lymarket` // 王霞
|
// export const BASE_URL = `http://192.168.1.5:40001/lymarket` // 王霞
|
||||||
// export const BASE_URL = `http://192.168.1.7:50002/lymarket` // 添
|
export const BASE_URL = `http://192.168.1.7:50002/lymarket` // 添
|
||||||
// export const BASE_URL = `http://192.168.1.42:50001/lymarket` // 杰
|
// export const BASE_URL = `http://192.168.1.42:50001/lymarket` // 杰
|
||||||
// export const BASE_URL = `http://192.168.1.95:40001/lymarket` // 华
|
// export const BASE_URL = `http://192.168.1.95:40001/lymarket` // 华
|
||||||
|
|
||||||
|
@ -0,0 +1,6 @@
|
|||||||
|
.grid {
|
||||||
|
padding: 24px 40px;
|
||||||
|
display: grid;
|
||||||
|
grid-gap: 24px 24px;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
}
|
68
src/components/SelectMarketingDepartment/index.tsx
Normal file
68
src/components/SelectMarketingDepartment/index.tsx
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
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'
|
||||||
|
|
||||||
|
type ChangedValue = string | number
|
||||||
|
|
||||||
|
interface SelectSaleTypeProps {
|
||||||
|
onChange?: (value: ChangedValue) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
type EnumList = {
|
||||||
|
id: number
|
||||||
|
code: string
|
||||||
|
name: string
|
||||||
|
}
|
||||||
|
// 营销部门
|
||||||
|
const SelectSaleType: FC<SelectSaleTypeProps> = 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<EnumList[]>([])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getData()
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const [currentValue, setCurrentValue] = useState<ChangedValue>(-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 (
|
||||||
|
<DropDownItem title={displayTitle} value={currentValue} activeColor='#337fff'>
|
||||||
|
<View className={styles.grid}>
|
||||||
|
{!!enumList.length &&
|
||||||
|
enumList.map((item: EnumList) => {
|
||||||
|
return (
|
||||||
|
<FilterButton isActive={item.id === currentValue} onClick={() => handleClick(item.id)}>
|
||||||
|
{item.name}
|
||||||
|
</FilterButton>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</View>
|
||||||
|
</DropDownItem>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
export default SelectSaleType
|
6
src/components/SelectSaleType/index.module.scss
Normal file
6
src/components/SelectSaleType/index.module.scss
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
.grid {
|
||||||
|
padding: 24px 40px;
|
||||||
|
display: grid;
|
||||||
|
grid-gap: 24px 24px;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
}
|
67
src/components/SelectSaleType/index.tsx
Normal file
67
src/components/SelectSaleType/index.tsx
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
import { FC, useEffect, useMemo, useState } from 'react'
|
||||||
|
import DropDownItem from '../dropDown-item'
|
||||||
|
import FilterButton from '../filterButton'
|
||||||
|
import { EnumSalesTypeApi } from '@/api/index'
|
||||||
|
import { View } from '@tarojs/components'
|
||||||
|
import styles from './index.module.scss'
|
||||||
|
|
||||||
|
type ChangedValue = string | number
|
||||||
|
|
||||||
|
interface SelectSaleTypeProps {
|
||||||
|
onChange?: (value: ChangedValue) => void
|
||||||
|
defaultValue?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
type EnumList = {
|
||||||
|
id: number
|
||||||
|
code: string
|
||||||
|
name: string
|
||||||
|
}
|
||||||
|
// 销售类型
|
||||||
|
const SelectSaleType: FC<SelectSaleTypeProps> = props => {
|
||||||
|
const selectName = '销售类型'
|
||||||
|
const { onChange } = props
|
||||||
|
console.log(props)
|
||||||
|
const { fetchData } = EnumSalesTypeApi()
|
||||||
|
|
||||||
|
const getData = async () => {
|
||||||
|
const res = await fetchData()
|
||||||
|
setEnumList([{ id: -1, code: '', name: '全部' }, ...res.data.list])
|
||||||
|
}
|
||||||
|
|
||||||
|
const [enumList, setEnumList] = useState<EnumList[]>([])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getData()
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const [currentValue, setCurrentValue] = useState<ChangedValue>(-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 (
|
||||||
|
<DropDownItem title={displayTitle} value={currentValue} activeColor='#337fff'>
|
||||||
|
<View className={styles.grid}>
|
||||||
|
{!!enumList.length &&
|
||||||
|
enumList.map((item: EnumList) => {
|
||||||
|
return (
|
||||||
|
<FilterButton isActive={item.id === currentValue} onClick={() => handleClick(item.id)}>
|
||||||
|
{item.name}
|
||||||
|
</FilterButton>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</View>
|
||||||
|
</DropDownItem>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
export default SelectSaleType
|
13
src/components/SelectTimePicker/index.module.scss
Normal file
13
src/components/SelectTimePicker/index.module.scss
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
.grid {
|
||||||
|
padding: 24px 40px;
|
||||||
|
display: grid;
|
||||||
|
grid-gap: 24px 24px;
|
||||||
|
grid-template-columns: 1fr 1fr 1fr;
|
||||||
|
}
|
||||||
|
.customFilterTime{
|
||||||
|
grid-column-start: span 3;
|
||||||
|
display: flex;
|
||||||
|
flex-flow: row nowrap;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
113
src/components/SelectTimePicker/index.tsx
Normal file
113
src/components/SelectTimePicker/index.tsx
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
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 styles from './index.module.scss'
|
||||||
|
|
||||||
|
type ChangedValue = string | number
|
||||||
|
|
||||||
|
interface SelectSaleTypeProps {
|
||||||
|
onChange?: (value: ChangedValue) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
const FilterTimeOptions = {
|
||||||
|
'0': {
|
||||||
|
name: '全部',
|
||||||
|
date_min: undefined,
|
||||||
|
date_max: undefined,
|
||||||
|
},
|
||||||
|
'1': {
|
||||||
|
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`,
|
||||||
|
},
|
||||||
|
'2': {
|
||||||
|
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`,
|
||||||
|
},
|
||||||
|
'3': {
|
||||||
|
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`,
|
||||||
|
},
|
||||||
|
'4': {
|
||||||
|
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`,
|
||||||
|
},
|
||||||
|
'5': {
|
||||||
|
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`,
|
||||||
|
},
|
||||||
|
} as const
|
||||||
|
|
||||||
|
type Key = keyof typeof FilterTimeOptions
|
||||||
|
type Value = (typeof FilterTimeOptions)[Key]
|
||||||
|
|
||||||
|
const SelectTimePicker: FC<SelectSaleTypeProps> = props => {
|
||||||
|
const { onChange: change } = props
|
||||||
|
const [currentValue, setCurrentValue] = useState('0')
|
||||||
|
|
||||||
|
const [currentDate, setCurrentDate] = useState({
|
||||||
|
start: new Date(),
|
||||||
|
end: new Date(),
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const onSelectDate = time => {
|
||||||
|
console.log(time)
|
||||||
|
change?.(time)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleClick = (key: Key) => {
|
||||||
|
setCurrentValue(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<DropDownItem title='查询日期' direction='down' value={currentValue} activeColor='#337fff'>
|
||||||
|
<View className={styles.grid} style={{ paddingBottom: '24rpx' }}>
|
||||||
|
{Object.entries(FilterTimeOptions).map(([key, value]) => {
|
||||||
|
return (
|
||||||
|
<FilterButton isActive={key === currentValue} onClick={() => handleClick(key as Key)}>
|
||||||
|
{value.name}
|
||||||
|
</FilterButton>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
<FilterButton customClassName={styles.customFilterTime} isActive={'6' === currentValue} onClick={() => handleClick('6' as Key)}>
|
||||||
|
<Text>自定义时间</Text>
|
||||||
|
<IconFont name='icon-chakanquanbukehu' color={'6' === currentValue ? '#3983ff' : '#7f7f7f'}></IconFont>
|
||||||
|
</FilterButton>
|
||||||
|
</View>
|
||||||
|
<View style={{ paddingBottom: '24rpx' }}>
|
||||||
|
<TimePicker start={currentDate.start} end={currentDate.end} onSelectDate={onSelectDate}></TimePicker>
|
||||||
|
</View>
|
||||||
|
</DropDownItem>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
export default SelectTimePicker
|
@ -1,7 +1,7 @@
|
|||||||
.dropDownItem{
|
.dropDownItem {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
&--title{
|
&--title {
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 2000;
|
z-index: 2000;
|
||||||
background-color: white;
|
background-color: white;
|
||||||
@ -10,9 +10,14 @@
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 24px 0;
|
padding: 24px 0;
|
||||||
&--text{
|
color: #8c8c8c;
|
||||||
|
font-size: 28px;
|
||||||
|
&--text {
|
||||||
display: block;
|
display: block;
|
||||||
margin-right: 12px;
|
margin-right: 12px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
&Options {
|
||||||
|
padding: 24px 40px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import { View, Text } from '@tarojs/components'
|
import { View, Text } from '@tarojs/components'
|
||||||
import { useCallback, useEffect, useMemo, useRef, useState, memo } from 'react'
|
import { useEffect, useMemo, useRef, useState } from 'react'
|
||||||
import styles from './index.module.scss'
|
import styles from './index.module.scss'
|
||||||
import classnames from 'classnames'
|
import Iconfont from '../iconfont/iconfont'
|
||||||
import Iconfont, { IconNames } from '../iconfont/iconfont'
|
|
||||||
import Popup from '../popup'
|
import Popup from '../popup'
|
||||||
import FilterButton from '../filterButton'
|
import Cell from '../cell'
|
||||||
|
import Taro from '@tarojs/taro'
|
||||||
// 弹窗选择向上弹窗还是向下弹窗
|
// 弹窗选择向上弹窗还是向下弹窗
|
||||||
type Direction = 'up' | 'down'
|
type Direction = 'up' | 'down'
|
||||||
// 配置 菜单可选项
|
// 配置 菜单可选项
|
||||||
@ -14,42 +14,42 @@ export type DropDownOptions = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface DropDownEvent {
|
interface DropDownEvent {
|
||||||
change?: (value: DropDownOptions['value']) => void // value 变化时触发
|
change?: (value: DropDownOptions['value']) => void // value 变化时触发
|
||||||
}
|
}
|
||||||
|
|
||||||
interface PropsType extends DropDownEvent{
|
interface PropsType extends DropDownEvent {
|
||||||
direction?: Direction
|
direction?: Direction
|
||||||
title: string // 已选中的菜单标题
|
|
||||||
options?: DropDownOptions[]
|
options?: DropDownOptions[]
|
||||||
value?: number | string // 当前选中的值
|
title?: string
|
||||||
|
value: number | string // 当前选中的值
|
||||||
children?: React.ReactNode
|
children?: React.ReactNode
|
||||||
activeColor?: string
|
activeColor?: string
|
||||||
|
showOverlay?: boolean
|
||||||
|
customClassName?: string
|
||||||
|
customStyle?: React.CSSProperties
|
||||||
}
|
}
|
||||||
|
|
||||||
export default (props: PropsType) => {
|
export default (props: PropsType) => {
|
||||||
const { children, direction = 'down', title, value, options, change, activeColor } = props
|
const { children, direction = 'down', title = '', value, options = [], change, activeColor, showOverlay = true } = props
|
||||||
|
|
||||||
const [showPopup, setShowPopup] = useState(false)
|
const [showPopup, setShowPopup] = useState(false)
|
||||||
|
|
||||||
const handleClickOption = (value: DropDownOptions['value']) => {
|
const handleClickOption = (value: DropDownOptions['value']) => {
|
||||||
|
|
||||||
change?.(value)
|
change?.(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const [text, setText] = useState(options?.[0]?.text || '')
|
||||||
|
|
||||||
const defaultOptions = useMemo(() => {
|
const defaultOptions = useMemo(() => {
|
||||||
const currentValue = value
|
const currentValue = value
|
||||||
return options?.map(({text, value})=>{
|
return options?.map(({ text, value }) => {
|
||||||
return (
|
currentValue === value && setText(text)
|
||||||
<FilterButton isActive={currentValue === value} onClick={() => handleClickOption(value)}>
|
return <Cell title={text} desc='' isLink onClick={() => handleClickOption(value)}></Cell>
|
||||||
{text}
|
|
||||||
</FilterButton>
|
|
||||||
)
|
|
||||||
|
|
||||||
})
|
})
|
||||||
}, [value])
|
}, [value])
|
||||||
|
|
||||||
const getIconName = () => {
|
const getIconName = () => {
|
||||||
if(direction === 'up'){
|
if (direction === 'up') {
|
||||||
return showPopup ? 'icon-zhankai1' : 'icon-shouqi1'
|
return showPopup ? 'icon-zhankai1' : 'icon-shouqi1'
|
||||||
}
|
}
|
||||||
// down
|
// down
|
||||||
@ -64,23 +64,58 @@ export default (props: PropsType) => {
|
|||||||
setShowPopup(false)
|
setShowPopup(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const [overlayOffsetTop, setOverlayOffsetTop] = useState('unset')
|
||||||
|
// 获取遮罩层的样式
|
||||||
|
const getOverlayStyle = (): React.CSSProperties => {
|
||||||
|
return { position: 'absolute', top: 0 }
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取整个页面的完整高度
|
||||||
|
const [scrollHeight, setScrollHeight] = useState(0)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const query = Taro.createSelectorQuery()
|
||||||
|
query.select('#DropDownItem').boundingClientRect()
|
||||||
|
query.selectViewport().scrollOffset()
|
||||||
|
query.exec(res => {
|
||||||
|
console.log('res==>', res)
|
||||||
|
setScrollHeight(res[1].scrollHeight)
|
||||||
|
if (direction === 'down') {
|
||||||
|
setOverlayOffsetTop(res[0].bottom + 'px')
|
||||||
|
} else {
|
||||||
|
setOverlayOffsetTop(res[0].top + 'px')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
// 获取样式
|
||||||
|
const getCustomStyle: React.CSSProperties = useMemo(() => {
|
||||||
|
if (direction === 'up') {
|
||||||
|
return { position: 'absolute', top: 0, height: overlayOffsetTop }
|
||||||
|
} else {
|
||||||
|
return { position: 'absolute', top: overlayOffsetTop, height: `calc(${scrollHeight + 'px'} - ${overlayOffsetTop})` }
|
||||||
|
}
|
||||||
|
}, [overlayOffsetTop])
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View className={styles.dropDownItem}>
|
<View className={styles.dropDownItem} id='DropDownItem'>
|
||||||
<View className={styles['dropDownItem--title']} onClick={handleClickTitle}>
|
<View className={styles['dropDownItem--title']} onClick={handleClickTitle}>
|
||||||
<Text className={styles['dropDownItem--title--text']} style={{ color: activeColor }}>
|
<Text className={styles['dropDownItem--title--text']} style={showPopup ? { color: activeColor } : {}}>
|
||||||
{title}
|
{title ? title : text}
|
||||||
</Text>
|
</Text>
|
||||||
<Iconfont name={getIconName()} size={20} color={value !== options![0].value ? activeColor : '#333'}></Iconfont>
|
<Iconfont name={getIconName()} size={20} color={showPopup ? activeColor : '#7f7f7f'}></Iconfont>
|
||||||
</View>
|
</View>
|
||||||
<Popup
|
<Popup
|
||||||
onClose={handleClosePopup}
|
onClose={handleClosePopup}
|
||||||
|
showOverLay={showOverlay}
|
||||||
show={showPopup}
|
show={showPopup}
|
||||||
showTitle={false}
|
showTitle={false}
|
||||||
safeAreaInsetBottom={false}
|
safeAreaInsetBottom={false}
|
||||||
customStyle={{ position: 'absolute', top: 'unset' }}
|
customStyle={getCustomStyle}
|
||||||
overlayStyle={{ position: 'absolute', top: 'unset' }}
|
overlayStyle={getOverlayStyle()}
|
||||||
position={direction === 'down' ? 'top' : 'bottom'}>
|
position={direction === 'down' ? 'top' : 'bottom'}>
|
||||||
{children ? children : defaultOptions}
|
{children ? children : <View className={styles.dropDownItemOptions}>{defaultOptions}</View>}
|
||||||
</Popup>
|
</Popup>
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
|
@ -15,6 +15,9 @@ $am-ms: 200ms;
|
|||||||
&_active {
|
&_active {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
&--hidden {
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.drawer_main {
|
.drawer_main {
|
||||||
@ -32,7 +35,7 @@ $am-ms: 200ms;
|
|||||||
z-index: 1000;
|
z-index: 1000;
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
transition: visibility $am-ms ease-in-out;
|
transition: visibility $am-ms ease-in-out;
|
||||||
|
overflow: hidden;
|
||||||
.drawer_container {
|
.drawer_container {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
@ -22,6 +22,7 @@ export interface Params extends PopupEvent {
|
|||||||
customStyle?: React.CSSProperties
|
customStyle?: React.CSSProperties
|
||||||
overlayStyle?: React.CSSProperties
|
overlayStyle?: React.CSSProperties
|
||||||
safeAreaInsetBottom?: boolean // 是否为iphoneX提供小黑条适配
|
safeAreaInsetBottom?: boolean // 是否为iphoneX提供小黑条适配
|
||||||
|
showOverLay?: boolean // 是否显示遮罩层
|
||||||
}
|
}
|
||||||
export default memo(
|
export default memo(
|
||||||
({
|
({
|
||||||
@ -36,6 +37,7 @@ export default memo(
|
|||||||
animationEnd,
|
animationEnd,
|
||||||
customStyle,
|
customStyle,
|
||||||
safeAreaInsetBottom = true,
|
safeAreaInsetBottom = true,
|
||||||
|
showOverLay = true,
|
||||||
overlayStyle,
|
overlayStyle,
|
||||||
}: Params) => {
|
}: Params) => {
|
||||||
const animationTime = useRef<any>(null)
|
const animationTime = useRef<any>(null)
|
||||||
@ -60,9 +62,12 @@ export default memo(
|
|||||||
<>
|
<>
|
||||||
<View className={style.drawer_main}>
|
<View className={style.drawer_main}>
|
||||||
<View catchMove={true} className={classnames(style.drawer, show ? style.drawer_active : '')} style={customStyle}>
|
<View catchMove={true} className={classnames(style.drawer, show ? style.drawer_active : '')} style={customStyle}>
|
||||||
<View className={classnames(style.drawer_mask, { [style.drawer_mask_active]: show })} onClick={onClose} style={overlayStyle}></View>
|
|
||||||
<View
|
<View
|
||||||
style={{ position: `${isFixed == true ? 'fixed' : 'absolute'}`, }}
|
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 })}
|
className={classnames(style.drawer_container, style['drawer_container_' + position], { [style.drawer_container_active]: show })}
|
||||||
onClick={e => e.stopPropagation()}>
|
onClick={e => e.stopPropagation()}>
|
||||||
{showTitle && <View className={style.drawer_container_title}>{title}</View>}
|
{showTitle && <View className={style.drawer_container_title}>{title}</View>}
|
||||||
|
@ -7,15 +7,13 @@ import dayjs from 'dayjs'
|
|||||||
|
|
||||||
type DateArg = string | number | Date
|
type DateArg = string | number | Date
|
||||||
interface Props {
|
interface Props {
|
||||||
showTime: boolean
|
|
||||||
closePopup?: () => void
|
|
||||||
end?: DateArg
|
end?: DateArg
|
||||||
start?: DateArg
|
start?: DateArg
|
||||||
onSelectDate?: (any) => void
|
onSelectDate?: (any) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export default memo((props: Props) => {
|
export default memo((props: Props) => {
|
||||||
let { showTime = false, closePopup, start = '', end = '', onSelectDate } = props
|
let { start = '', end = '', onSelectDate } = props
|
||||||
const [time, setTime] = useState<any>({})
|
const [time, setTime] = useState<any>({})
|
||||||
|
|
||||||
const handTime = (e) => {
|
const handTime = (e) => {
|
||||||
@ -33,7 +31,7 @@ export default memo((props: Props) => {
|
|||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Popup title={'选择时间'} show={showTime} onClose={() => closePopup?.()}>
|
<>
|
||||||
<View className='time-box'>
|
<View className='time-box'>
|
||||||
<AtCalendar
|
<AtCalendar
|
||||||
isMultiSelect
|
isMultiSelect
|
||||||
@ -48,6 +46,6 @@ export default memo((props: Props) => {
|
|||||||
<View className='sure-box' onClick={() => onSelectDate?.(time)}>
|
<View className='sure-box' onClick={() => onSelectDate?.(time)}>
|
||||||
确认
|
确认
|
||||||
</View>
|
</View>
|
||||||
</Popup>
|
</>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
19
src/components/timePickerPopup/index.scss
Normal file
19
src/components/timePickerPopup/index.scss
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
|
||||||
|
|
||||||
|
.time-box {
|
||||||
|
padding: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sure-box {
|
||||||
|
// padding: 16px 102px 30px 102px;
|
||||||
|
margin-left: 102px;
|
||||||
|
margin-right: 102px;
|
||||||
|
height: 80px;
|
||||||
|
background: #337FFF;
|
||||||
|
border-radius: 44px;
|
||||||
|
font-size: 28px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #FFFFFF;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 80px;
|
||||||
|
}
|
24
src/components/timePickerPopup/index.tsx
Normal file
24
src/components/timePickerPopup/index.tsx
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import Popup from '@/components/popup'
|
||||||
|
import { memo } from 'react'
|
||||||
|
import './index.scss'
|
||||||
|
import TimePicker from '../timePicker'
|
||||||
|
|
||||||
|
type DateArg = string | number | Date
|
||||||
|
interface Props {
|
||||||
|
showTime: boolean
|
||||||
|
closePopup?: () => void
|
||||||
|
end?: DateArg
|
||||||
|
start?: DateArg
|
||||||
|
onSelectDate?: (any) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export default memo((props: Props) => {
|
||||||
|
let { showTime = false, closePopup, start = '', end = '', onSelectDate } = props
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Popup title={'选择时间'} show={showTime} onClose={() => closePopup?.()}>
|
||||||
|
<TimePicker start={start} end={end} onSelectDate={onSelectDate}></TimePicker>
|
||||||
|
</Popup>
|
||||||
|
)
|
||||||
|
})
|
@ -13,7 +13,7 @@ import ItemList from './components/ItemList'
|
|||||||
import DeliveryStatusList from './components/DeliveryStatusList'
|
import DeliveryStatusList from './components/DeliveryStatusList'
|
||||||
import Popup from '@/components/popup'
|
import Popup from '@/components/popup'
|
||||||
import DeliveryFilter, { SearchField } from './components/Filter'
|
import DeliveryFilter, { SearchField } from './components/Filter'
|
||||||
import TimePicker from '@/components/timePicker'
|
import TimePickerPopup from '@/components/timePickerPopup'
|
||||||
|
|
||||||
type SearchData = {
|
type SearchData = {
|
||||||
delivery_notice_order_no?: string // 发货单号
|
delivery_notice_order_no?: string // 发货单号
|
||||||
@ -196,7 +196,7 @@ const Delivery: FC = () => {
|
|||||||
<Popup show={showFilter} title='筛选列表' onClose={handlePopupClose}>
|
<Popup show={showFilter} title='筛选列表' onClose={handlePopupClose}>
|
||||||
<DeliveryFilter onSearchTime={handleSearchTime} onConfirm={handleConfirm} onReset={handleReset} />
|
<DeliveryFilter onSearchTime={handleSearchTime} onConfirm={handleConfirm} onReset={handleReset} />
|
||||||
</Popup>
|
</Popup>
|
||||||
<TimePicker start={start} end={end} showTime={showTime} closePopup={handClose} onSelectDate={(e) => handTime(e)}></TimePicker>
|
<TimePickerPopup start={start} end={end} showTime={showTime} closePopup={handClose} onSelectDate={(e) => handTime(e)}></TimePickerPopup>
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ import { formatDateTime, formatHashTag, formatImgUrl, formatPriceDiv, formatWeig
|
|||||||
import {
|
import {
|
||||||
mpcashManagementOrderlist
|
mpcashManagementOrderlist
|
||||||
} from "@/api/newCollection"
|
} from "@/api/newCollection"
|
||||||
import TimePicker from "@/components/timePicker"
|
import TimePickerPopup from '@/components/timePickerPopup'
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
import IconFont from '@/components/iconfont/iconfont'
|
import IconFont from '@/components/iconfont/iconfont'
|
||||||
|
|
||||||
@ -294,13 +294,13 @@ export default () => {
|
|||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
</Popup>
|
</Popup>
|
||||||
<TimePicker
|
<TimePickerPopup
|
||||||
start={start}
|
start={start}
|
||||||
end={end}
|
end={end}
|
||||||
showTime={showTime}
|
showTime={showTime}
|
||||||
closePopup={handClose}
|
closePopup={handClose}
|
||||||
onSelectDate={(e) => handTime(e)}
|
onSelectDate={(e) => handTime(e)}
|
||||||
></TimePicker>
|
></TimePickerPopup>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ import {
|
|||||||
mpenumreturnType
|
mpenumreturnType
|
||||||
} from "@/api/refound"
|
} from "@/api/refound"
|
||||||
import Tabs from "./components/tabs"
|
import Tabs from "./components/tabs"
|
||||||
import TimePicker from "@/components/timePicker"
|
import TimePickerPopup from '@/components/timePickerPopup'
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
import IconFont from '@/components/iconfont/iconfont'
|
import IconFont from '@/components/iconfont/iconfont'
|
||||||
export default () => {
|
export default () => {
|
||||||
@ -395,13 +395,13 @@ export default () => {
|
|||||||
{/* <View className={styles.areaBox}></View> */}
|
{/* <View className={styles.areaBox}></View> */}
|
||||||
</View>
|
</View>
|
||||||
</Popup>
|
</Popup>
|
||||||
<TimePicker
|
<TimePickerPopup
|
||||||
start={start}
|
start={start}
|
||||||
end={end}
|
end={end}
|
||||||
showTime={showTime}
|
showTime={showTime}
|
||||||
closePopup={handClose}
|
closePopup={handClose}
|
||||||
onSelectDate={(e) => handTime(e)}
|
onSelectDate={(e) => handTime(e)}
|
||||||
></TimePicker>
|
></TimePickerPopup>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,12 @@
|
|||||||
|
import AtCalendar from '@/components/calendar'
|
||||||
import DropDownItem, { DropDownOptions } from '@/components/dropDown-item'
|
import DropDownItem, { DropDownOptions } from '@/components/dropDown-item'
|
||||||
|
import SelectMarketingDepartment from '@/components/SelectMarketingDepartment'
|
||||||
|
import SelectSaleType from '@/components/SelectSaleType'
|
||||||
|
import SelectTimePicker from '@/components/SelectTimePicker'
|
||||||
|
import TimePicker from '@/components/timePicker'
|
||||||
import { View } from '@tarojs/components'
|
import { View } from '@tarojs/components'
|
||||||
|
import classnames from 'classnames'
|
||||||
|
import dayjs from 'dayjs'
|
||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
import styles from './index.module.scss'
|
import styles from './index.module.scss'
|
||||||
|
|
||||||
@ -17,13 +24,30 @@ const saleStatistic = () => {
|
|||||||
text: 'name2',
|
text: 'name2',
|
||||||
value: 2,
|
value: 2,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
text: 'name3',
|
||||||
|
value: 3,
|
||||||
|
},
|
||||||
])
|
])
|
||||||
|
|
||||||
|
const onChangeTimePicker = (value) => {
|
||||||
|
console.log(value)
|
||||||
|
}
|
||||||
|
const onChangeSaleType = (saleType) => {
|
||||||
|
console.log(saleType)
|
||||||
|
|
||||||
|
}
|
||||||
|
const onChangeDepartment = (department) => {
|
||||||
|
console.log(department)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View className={styles.saleStatistic}>
|
<View className={styles.saleStatistic}>
|
||||||
<View className={styles['saleStatistic--filterBar']}>
|
<View className={styles['saleStatistic--filterBar']}>
|
||||||
<View>sdflkajsfdlk</View>
|
<SelectSaleType onChange={onChangeSaleType}></SelectSaleType>
|
||||||
<DropDownItem title='name' activeColor='#337fff' options={options}></DropDownItem>
|
<SelectMarketingDepartment onChange={onChangeDepartment}></SelectMarketingDepartment>
|
||||||
|
<SelectTimePicker onChange={onChangeTimePicker}></SelectTimePicker>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
|
@ -13,7 +13,7 @@ import ItemList from './components/ItemList'
|
|||||||
import DeliveryStatusList from './components/DeliveryStatusList'
|
import DeliveryStatusList from './components/DeliveryStatusList'
|
||||||
import Popup from '@/components/popup'
|
import Popup from '@/components/popup'
|
||||||
import DeliveryFilter, { SearchField } from './components/Filter'
|
import DeliveryFilter, { SearchField } from './components/Filter'
|
||||||
import TimePicker from '@/components/timePicker'
|
import TimePickerPopup from '@/components/timePickerPopup'
|
||||||
|
|
||||||
type SearchData = {
|
type SearchData = {
|
||||||
take_goods_order_no?: string // 提货单号
|
take_goods_order_no?: string // 提货单号
|
||||||
@ -191,7 +191,7 @@ const Delivery: FC = () => {
|
|||||||
<Popup show={showFilter} title='筛选列表' onClose={handlePopupClose}>
|
<Popup show={showFilter} title='筛选列表' onClose={handlePopupClose}>
|
||||||
<DeliveryFilter onSearchTime={handleSearchTime} onConfirm={handleConfirm} onReset={handleReset} />
|
<DeliveryFilter onSearchTime={handleSearchTime} onConfirm={handleConfirm} onReset={handleReset} />
|
||||||
</Popup>
|
</Popup>
|
||||||
<TimePicker start={start} end={end} showTime={showTime} closePopup={handClose} onSelectDate={(e) => handTime(e)}></TimePicker>
|
<TimePickerPopup start={start} end={end} showTime={showTime} closePopup={handClose} onSelectDate={(e) => handTime(e)}></TimePickerPopup>
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user