组件
index.js
import React from 'react';
import { Radio } from 'antd';
import 'moment/locale/zh-cn';
import moment from 'moment';
import dayjs from 'dayjs';
export { default as DatePageChange } from './DatePageChange';
export { default as DateInfoChange } from './DateInfoChange';
const GRadio = Radio.Group;
const BRadio = Radio.Button;
export default ({ dateType, dateTypeConfig, handleCustomClick = () => {} }) => {
const onChangeGRadio = value => {
let date = null;
switch (value) {
case dateTypeConfig.DAILY:
date = [moment().format('YYYY-MM-DD'), moment().format('YYYY-MM-DD')];
break;
case dateTypeConfig.WEEKLY:
date = [
moment()
?.week(moment()?.week())
.startOf('week')
.format('YYYY-MM-DD'),
moment()
?.week(moment()?.week())
.endOf('week')
.format('YYYY-MM-DD'),
];
break;
case dateTypeConfig.MONTHLY:
date = [
moment()
?.month(moment()?.month())
.startOf('month')
.format('YYYY-MM-DD'),
moment()
?.month(moment()?.month())
.endOf('month')
.format('YYYY-MM-DD'),
];
break;
case dateTypeConfig.YEARLY:
date = [`${dayjs().format('YYYY')}-01-01`, `${dayjs().format('YYYY')}-12-31`];
break;
case dateTypeConfig.CUSTOM:
date = [
moment().format('YYYY-MM-DD'),
moment()
?.endOf('month')
?.format('YYYY-MM-DD'),
];
break;
default:
date = [
moment().format('YYYY-MM-DD'),
moment()
?.endOf('month')
?.format('YYYY-MM-DD'),
];
break;
}
handleCustomClick({
start_date: date && date?.[0] ? date?.[0] : null,
end_date: date && date?.[1] ? date?.[1] : null,
dateType: value,
});
};
return (
<div style={{ display: 'flex' }}>
<GRadio value={dateType} onChange={e => onChangeGRadio(e?.target?.value)}>
<BRadio value={dateTypeConfig.DAILY} style={{ width: '60px', textAlign: 'center' }}>
日
</BRadio>
<BRadio value={dateTypeConfig.WEEKLY} style={{ width: '60px', textAlign: 'center' }}>
周
</BRadio>
<BRadio value={dateTypeConfig.MONTHLY} style={{ width: '60px', textAlign: 'center' }}>
月
</BRadio>
<BRadio value={dateTypeConfig.YEARLY} style={{ width: '60px', textAlign: 'center' }}>
年
</BRadio>
<BRadio value={dateTypeConfig.CUSTOM} style={{ minWidth: '60px', textAlign: 'center' }}>
自定义
</BRadio>
</GRadio>
</div>
);
};
DateInfoChange.jsx
import React, { useState, useEffect, useMemo } from 'react';
import { DatePicker, message } from 'antd';
import locale from 'antd/es/date-picker/locale/zh_CN';
import 'moment/locale/zh-cn';
import moment from 'moment';
const { RangePicker } = DatePicker;
export default ({
dateType,
dateTypeConfig,
currentDateInfo,
handleCustomDateClick = () => {},
customDisabled = 90,
}) => {
const [time, setTime] = useState(moment());
const [customTime, setCustomTime] = useState([moment(), moment()?.endOf('month')]);
useEffect(() => {
const end_date = currentDateInfo?.end_date ? moment(currentDateInfo?.end_date) : null;
const start_date = currentDateInfo?.start_date ? moment(currentDateInfo?.start_date) : null;
const datas = [start_date, end_date];
const dateValue = currentDateInfo?.start_date ? moment(currentDateInfo?.start_date) : null;
switch (dateType) {
case dateTypeConfig.DAILY:
case dateTypeConfig.WEEKLY:
case dateTypeConfig.MONTHLY:
case dateTypeConfig.YEARLY:
setTime(dateValue);
break;
case dateTypeConfig.CUSTOM:
setCustomTime(datas);
break;
default:
break;
}
}, [currentDateInfo, dateType, setTime, dateTypeConfig]);
const dataPicker = useMemo(() => {
const onValueChange = value => {
let params = {};
switch (dateType) {
case dateTypeConfig.DAILY:
params = {
start_date: value ? value.format('YYYY-MM-DD') : null,
end_date: value ? value.format('YYYY-MM-DD') : null,
};
break;
case dateTypeConfig.WEEKLY:
params = {
start_date: value
? value
?.week(value?.week())
.startOf('week')
.format('YYYY-MM-DD')
: null,
end_date: value
? value
?.week(value?.week())
.endOf('week')
.format('YYYY-MM-DD')
: null,
};
break;
case dateTypeConfig.MONTHLY:
params = {
start_date: value
? value
?.month(value?.month())
.startOf('month')
.format('YYYY-MM-DD')
: null,
end_date: value
? value
?.month(value?.month())
.endOf('month')
.format('YYYY-MM-DD')
: null,
};
break;
case dateTypeConfig.YEARLY:
params = {
start_date: value ? moment(`${value}-01-01`)?.format('YYYY-MM-DD') : null,
end_date: value
? moment(`${value}-01-01`)
?.endOf('month')
?.format('YYYY-MM-DD')
: null,
};
break;
case dateTypeConfig.CUSTOM:
params = {
start_date: value && value[0] ? value[0].format('YYYY-MM-DD') : null,
end_date: value && value[1] ? value[1].format('YYYY-MM-DD') : null,
};
break;
default:
break;
}
const interval = moment(params.end_date).diff(params.start_date, 'days');
if (dateType === dateTypeConfig.CUSTOM && interval > customDisabled) {
message.error(`日期选择最多相差${customDisabled}天`);
return;
}
handleCustomDateClick(params);
};
switch (dateType) {
case dateTypeConfig.DAILY:
return (
<DatePicker
allowClear={false}
disabledDate={current => {
return current && current >= moment();
}}
locale={locale}
style={{ width: '100%' }}
onChange={onValueChange}
value={time}
/>
);
case dateTypeConfig.WEEKLY:
return (
<DatePicker
allowClear={false}
disabledDate={current => {
return current > moment().endOf('day');
}}
locale={locale}
style={{ width: '100%' }}
onChange={onValueChange}
picker="week"
value={time}
/>
);
case dateTypeConfig.MONTHLY:
return (
<DatePicker
allowClear={false}
disabledDate={current => {
return current > moment().endOf('day');
}}
locale={locale}
style={{ width: '100%' }}
onChange={onValueChange}
picker="month"
value={time}
/>
);
case dateTypeConfig.YEARLY:
return (
<DatePicker
allowClear={false}
disabledDate={current => {
return current > moment().endOf('day');
}}
locale={locale}
style={{ width: '100%' }}
onChange={onValueChange}
picker="year"
value={time}
/>
);
case dateTypeConfig.CUSTOM:
return (
<RangePicker
allowClear={false}
disabledDate={current => {
return current && current.valueOf() > moment().subtract(0, 'days');
}}
locale={locale}
style={{ width: '100%' }}
onChange={onValueChange}
value={customTime}
/>
);
default:
break;
}
}, [dateType, handleCustomDateClick, dateTypeConfig, time, customTime, customDisabled]);
return dataPicker;
};
DatePageChange.jsx
import React, { useMemo } from 'react';
import { Button, message } from 'antd';
import moment from 'moment';
export default ({
dateType,
dateTypeConfig,
currentDateInfo = {},
handleDatePageClick = () => {},
customDisabled = 90,
}) => {
const changeDate = useMemo(() => {
let preName = '';
let nextName = '';
switch (dateType) {
case dateTypeConfig.DAILY:
preName = '前一天';
nextName = '后一天';
break;
case dateTypeConfig.WEEKLY:
preName = '上一周';
nextName = '下一周';
break;
case dateTypeConfig.MONTHLY:
preName = '上一月';
nextName = '下一月';
break;
case dateTypeConfig.YEARLY:
preName = '上一年';
nextName = '下一年';
break;
case dateTypeConfig.CUSTOM:
preName = '前一天';
nextName = '后一天';
break;
default:
break;
}
const onChangeDatePage = flag => {
let start_date = currentDateInfo?.start_date;
let end_date = currentDateInfo?.end_date;
switch (dateType) {
case dateTypeConfig.DAILY:
if (flag) {
start_date = moment(start_date)
.subtract(1, 'days')
.format('YYYY-MM-DD');
end_date = moment(end_date)
.subtract(1, 'days')
.format('YYYY-MM-DD');
} else {
const current = moment(start_date).format('YYYY-MM-DD');
const disable_start = moment()
.endOf('days')
.format('YYYY-MM-DD');
if (moment(current).isSameOrAfter(disable_start)) return;
start_date = moment(start_date)
.add(1, 'days')
.format('YYYY-MM-DD');
end_date = moment(end_date)
.add(1, 'days')
.format('YYYY-MM-DD');
}
break;
case dateTypeConfig.WEEKLY:
if (flag) {
start_date = moment(start_date)
.subtract(1, 'weeks')
.format('YYYY-MM-DD');
end_date = moment(end_date)
.subtract(1, 'weeks')
.format('YYYY-MM-DD');
} else {
const current = moment(start_date).format('YYYY-MM-DD');
const disable_start = moment()
.endOf('weeks')
.format('YYYY-MM-DD');
if (moment(current).isSameOrAfter(disable_start)) return;
start_date = moment(start_date)
.add(1, 'weeks')
.format('YYYY-MM-DD');
end_date = moment(end_date)
.add(1, 'weeks')
.format('YYYY-MM-DD');
}
break;
case dateTypeConfig.MONTHLY:
if (flag) {
start_date = moment(start_date)
.subtract(1, 'months')
.format('YYYY-MM-DD');
end_date = moment(end_date)
.subtract(1, 'months')
.format('YYYY-MM-DD');
} else {
const current = moment(start_date).format('YYYY-MM');
const disable_start = moment()
.endOf('month')
.format('YYYY-MM');
if (moment(current).isSameOrAfter(disable_start)) return;
start_date = moment(start_date)
.add(1, 'months')
.format('YYYY-MM-DD');
end_date = moment(end_date)
.add(1, 'months')
.format('YYYY-MM-DD');
}
break;
case dateTypeConfig.YEARLY:
if (flag) {
start_date = moment(start_date)
.subtract(1, 'years')
.format('YYYY-MM-DD');
end_date = moment(end_date)
.subtract(1, 'years')
.format('YYYY-MM-DD');
} else {
const current = moment(start_date).year();
const disable_start = moment()
.endOf('year')
.format('YYYY');
if (current === Number(disable_start)) return;
start_date = moment(start_date)
.add(1, 'years')
.format('YYYY-MM-DD');
end_date = moment(end_date)
.add(1, 'years')
.format('YYYY-MM-DD');
}
break;
case dateTypeConfig.CUSTOM:
if (flag) {
start_date = moment(start_date)
.subtract(1, 'days')
.format('YYYY-MM-DD');
} else {
end_date = moment(end_date)
.add(1, 'days')
.format('YYYY-MM-DD');
}
break;
default:
break;
}
const interval = moment(end_date).diff(start_date, 'days');
if (dateType === dateTypeConfig.CUSTOM && interval > customDisabled) {
message.error(`日期选择最多相差${customDisabled}天`);
return;
}
handleDatePageClick(start_date, end_date);
};
return (
<div style={{ display: 'flex' }}>
<Button onClick={() => onChangeDatePage(true)}>{preName} </Button>
<Button onClick={() => onChangeDatePage(false)}>{nextName} </Button>
</div>
);
}, [dateType, currentDateInfo, handleDatePageClick, dateTypeConfig, customDisabled]);
return changeDate;
};
使用组件
import React, { useState, useEffect, useMemo } from 'react';
import '@ant-design/compatible/assets/index.css';
import { Button, Form, Checkbox } from 'antd';
import { DownOutlined, UpOutlined } from '@ant-design/icons';
import moment from 'moment';
import { getCombineClassName, getShowCount } from '@/utils/utils';
import ProductNameSelect from '@/components/ProductNameSelect';
import HardwareModelSelect from '@/components/HardwareModelSelect';
import WarehouseNameSelect from '@/components/WarehouseNameSelect';
import CustomDateSelect, { DateInfoChange, DatePageChange } from '@/components/CustomDateSelect';
const FormItem = Form.Item;
const dateTypeConfig = {
DAILY: 'daily',
WEEKLY: 'weekly',
MONTHLY: 'monthly',
YEARLY: 'yearly',
CUSTOM: 'custom',
};
const Filter = ({ listParams, dispatch, currentModel, dateType, isExpand, staticFilter }) => {
const [form] = Form.useForm();
const { resetFields, setFieldsValue } = form;
const [clientWidth, setClientWidth] = useState(document.body.clientWidth);
const datePickerItemParam = () => {
let lable = '';
let sourceClassName = 'three-word-padding';
let itemName = dateTypeConfig.DAILY;
switch (dateType) {
case dateTypeConfig.DAILY:
lable = '选择日';
itemName = dateTypeConfig.DAILY;
break;
case dateTypeConfig.WEEKLY:
lable = '选择周';
itemName = dateTypeConfig.WEEKLY;
break;
case dateTypeConfig.MONTHLY:
lable = '选择月';
itemName = dateTypeConfig.MONTHLY;
break;
case dateTypeConfig.YEARLY:
lable = '选择年';
itemName = dateTypeConfig.YEARLY;
break;
case dateTypeConfig.CUSTOM:
lable = '';
sourceClassName = '';
itemName = dateTypeConfig.CUSTOM;
break;
default:
break;
}
return { itemName, lable, sourceClassName };
};
useEffect(() => {
window.addEventListener('resize', () => {
setClientWidth(document.body.clientWidth);
});
}, []);
useEffect(() => {
// const end_date = listParams?.end_date ? moment(listParams?.end_date) : null;
// const start_date = listParams?.end_date ? moment(listParams?.end_date) : null;
// const datas = [start_date, end_date];
// const dateValue = listParams?.start_date ? moment(listParams?.start_date) : null;
// const name = datePickerItemParam().itemName;
setFieldsValue({
...listParams,
// [dateTypeConfig.CUSTOM]: datas,
// [name]: dateValue,
});
}, [setFieldsValue, listParams, datePickerItemParam]);
console.log(listParams);
const handleSearch = () => {
dispatch({ type: `${currentModel}/getList` });
};
const handleFormReset = () => {
dispatch({ type: `${currentModel}/resetParams` }).then(res => {
resetFields();
setFieldsValue({
dates_daily: moment(),
});
});
};
const onValuesChange = (changedValues, allValues) => {
const {
dates,
dates_daily,
start_dt_week,
end_dt_week,
start_dt_month,
end_dt_month,
start_dt_year,
change_date,
...others
} = allValues;
const params = {
page: 1,
...others,
};
dispatch({
type: `${currentModel}/updateStateProps`,
payload: {
name: 'listParams',
value: { ...params },
},
});
if (['name'].includes(Object.keys(changedValues)[0])) {
// input输入项通过回车来触发搜索
return;
}
handleSearch();
};
const onChangeCheckbox = value => {
dispatch({
type: `${currentModel}/overrideStateProps`,
payload: {
staticFilter: value,
},
});
};
const commonCustomDateProps = {
dateType,
currentDateInfo: {
start_date: listParams?.start_date || null,
end_date: listParams?.end_date || null,
},
dateTypeConfig,
customDisabled: 90,
handleCustomClick({ start_date, end_date, dateType }) {
dispatch({
type: `${currentModel}/updateStateProps`,
payload: {
name: 'listParams',
value: {
start_date: start_date || null,
end_date: end_date || null,
},
},
});
dispatch({
type: `${currentModel}/overrideStateProps`,
payload: {
dateType,
},
});
handleSearch();
},
handleDatePageClick(start_date, end_date) {
dispatch({
type: `${currentModel}/updateStateProps`,
payload: {
name: 'listParams',
value: {
start_date: start_date || null,
end_date: end_date || null,
},
},
});
setFieldsValue({
dates: [moment(start_date), moment(end_date)],
});
handleSearch();
},
handleCustomDateClick({ start_date, end_date }) {
dispatch({
type: `${currentModel}/updateStateProps`,
payload: {
name: 'listParams',
value: {
start_date: start_date || null,
end_date: end_date || null,
},
},
});
handleSearch();
},
};
return (
<Form
onFinish={handleSearch}
className="filterListForm"
form={form}
initialValues={{
name: '', // 客户名称
}}
onValuesChange={onValuesChange}
>
<FormItem
style={{ minWidth: 350 }}
className={getCombineClassName({
sourceClassName: '',
isExpand,
sort: 1,
clientWidth,
})}
>
<CustomDateSelect {...commonCustomDateProps} />
</FormItem>
<FormItem
// name="daily"
// name={datePickerItemParam().itemName}
label={datePickerItemParam().lable}
className={getCombineClassName({
sourceClassName: datePickerItemParam().sourceClassName,
isExpand,
sort: 2,
clientWidth,
})}
>
<DateInfoChange {...commonCustomDateProps} />
</FormItem>
<FormItem
name="change_date"
label=""
className={getCombineClassName({
sourceClassName: 'three-word-padding',
isExpand,
sort: 3,
clientWidth,
})}
>
<DatePageChange {...commonCustomDateProps} />
</FormItem>
<FormItem
name="operator_id"
label="仓库"
className={getCombineClassName({
sourceClassName: 'three-word-padding',
isExpand,
sort: 4,
clientWidth,
})}
>
<WarehouseNameSelect placeholder="请选择仓库" />
</FormItem>
<FormItem
name="product_name"
label="产品名称"
className={getCombineClassName({
sourceClassName: 'four-word-padding',
isExpand,
sort: 5,
clientWidth,
})}
>
<ProductNameSelect type="product" allowClear={false} hasAll="全部" />
</FormItem>
<FormItem
name="product_id"
label="硬件型号"
className={getCombineClassName({
sourceClassName: 'four-word-padding',
isExpand,
sort: 6,
clientWidth,
})}
>
<HardwareModelSelect type="product" hasAll />
</FormItem>
{/* 年后再处理 分组统计条件 */}
{false && (
<FormItem
style={{ minWidth: 600 }}
className={getCombineClassName({
sourceClassName: 'six-word-padding',
isExpand,
sort: 7,
clientWidth,
})}
label=""
>
<Checkbox.Group style={{ width: '100%' }} onChange={onChangeCheckbox} defaultValue={staticFilter}>
<span style={{ marginRight: 10 }}>分组统计条件</span>
<Checkbox value="wear_name">仓库名称</Checkbox>
<Checkbox value="name">产品名称</Checkbox>
<Checkbox value="hardware_model">硬件型号</Checkbox>
</Checkbox.Group>
</FormItem>
)}
<FormItem>
<Button type="primary" htmlType="submit">
搜索
</Button>
<Button type="default" style={{ marginLeft: 8 }} onClick={handleFormReset}>
重置
</Button>
{getShowCount(clientWidth) < 12 ? (
<Button
type="link"
onClick={() => {
dispatch({
type: `${currentModel}/overrideStateProps`,
payload: {
isExpand: !isExpand,
},
});
}}
icon={isExpand ? <DownOutlined /> : <UpOutlined />}
style={{ marginLeft: 8 }}
>
{!isExpand ? '折叠' : '展开'}
</Button>
) : null}
</FormItem>
</Form>
);
};
export default Filter;