时间控制插件调用接口
(1)一个时间控制插件:
需求,根据时间组件选择的时间,来根据选择的这个时间段去”搞事情“;
(2)组件的代码分析:
组件的js和样式代码如下
index.js
/** * * DurationSelector * */
import React from 'react';
import { Button, DatePicker, message } from 'antd';
import moment from 'moment';
import PropTypes from 'prop-types';
import './index.scss';
moment.updateLocale('en',
{
week: {
dow: 1, // First day of week is Monday
},
});
const { RangePicker } = DatePicker;
const TODAY = moment();
// export const DEFAULT_SHORTCUTS = 'D30';
export const DEFAULT_SHORTCUTS = 'D7';
// 这里都统计截止到昨日、上周、上月的折线图数据
export const SHORTCUTMAP = {
D1: {
name: '1天',
duration: [moment().add(-1, 'd'), moment().add(-1, 'd')],
// calcDuration: momentDate => [momentDate.clone(), momentDate],
},
D7: {
name: '7天',
duration: [moment().add(-7, 'd'), moment().add(-1, 'd')],
// calcDuration: momentDate => [momentDate.clone().add(-6, 'd'), momentDate],
},
D30: {
name: '30天',
duration: [moment().add(-30, 'd'), moment().add(-1, 'd')],
// calcDuration: momentDate => [momentDate.clone().add(-29, 'd'), momentDate],
},
// WEEK: {
// name: '周',
// duration: [moment().add(-12, 'w').startOf('week'), moment().add(-1, 'w').endOf('week')],
// addition: '上周',
// calcDuration: (momentDate) => {
// const date1 = momentDate.clone().add(-11, 'w').startOf('week');
// const date2 = momentDate.clone().startOf('year').startOf('week');
// return [date1.isSameOrBefore(date2) ? date2 : date1, momentDate.endOf('week')];
// },
// },
// MONTH: {
// name: '月',
// duration: [moment().add(-12, 'M').startOf('Month'), moment().add(-1, 'M').endOf('Month')],
// addition: '上月',
// calcDuration: momentDate => [momentDate.clone().add(-11, 'M').startOf('Month'), momentDate.endOf('Month')],
// },
WHATDIDFOXSAY: {
name: '自定义',
duration: [],
},
};
// 日期空间中校验日期是否可选
const getDisabledDate = currentDate => currentDate.isSameOrAfter(TODAY, 'day') || currentDate.isBefore(moment('2019-11-11'), 'day');
// 是否是同一个时间段
const isSameDuration = (originDuration, targetDuration) => {
if (!originDuration.length) return false;
let perfectMatch = true;
for (let j = 0; j < originDuration.length; j++) {
if (!originDuration[j] || !originDuration[j].isSame(targetDuration[j], 'day')) {
perfectMatch = false;
break;
}
}
return perfectMatch;
};
// 日期和快捷方式联动
const reflectShortCuts = (duration, shortCutMap) => {
let targetKey = '';
const keys = Object.keys(shortCutMap);
for (let i = 0; i < keys.length; i++) {
const shortcutItem = shortCutMap[keys[i]];
const _isSameDuration = isSameDuration(shortcutItem.duration, duration);
if (_isSameDuration) {
targetKey = keys[i];
break;
}
}
// if (targetKey === 'D1') targetKey = 'D7'; // D7 和 D1 时间周期一样, 默认匹配给 'D7'
return targetKey || 'WHATDIDFOXSAY';
};
export default class DurationSelector extends React.Component {
static defaultProps = {
className: '',
disabled: false,
// shortCutMap: {},
dataEndDate: '',
tip: '',
};
static propTypes = {
dateChange: PropTypes.func.isRequired,
className: PropTypes.string,
disabled: PropTypes.bool,
// shortCutMap: PropTypes.object,
dataEndDate: PropTypes.string,
tip: PropTypes.string,
};
static getDerivedStateFromProps(nextProps, prevState) {
if (!prevState.duration.length) {
const duration = SHORTCUTMAP[DEFAULT_SHORTCUTS].duration;
nextProps.dateChange(duration, prevState.activeShortcuts);
return {
duration,
};
}
// if (nextProps.dataEndDate && !nextProps.disabled) {
// const calc = SHORTCUTMAP[prevState.activeShortcuts].calcDuration;
// if (!calc) return null;
// return {
// duration: calc(moment(nextProps.dataEndDate, 'YYYYMMDD')),
// };
// }
return null;
}
state = {
duration: [],
activeShortcuts: DEFAULT_SHORTCUTS,
rangePickerOpen: false,
reset: false,
};
// 选择完快捷方式,和日期联动
selectShortcuts = (e) => {
if (this.props.disabled) return;
if (!e || !e.target || !e.target.dataset || !e.target.dataset.type) return;
const type = e.target.dataset.type;
if (type === 'WHATDIDFOXSAY') {
this.setState({
rangePickerOpen: true,
});
} else {
// 非自定义的情况下
// 避免重复点击
if (type === this.state.activeShortcuts) return;
// 设置时间段
this.setState({
duration: SHORTCUTMAP[type].duration,
});
// 触发父级 dateChange 方法
this.props.dateChange(SHORTCUTMAP[type].duration, type);
}
this.setState({
activeShortcuts: type,
reset: false,
});
};
// 选择完日期,处理和快捷方式的联动
rangePickerChange = (durationList) => {
// 日期选择空间删除了日期
if (!durationList || !durationList.length) {
return this.setState({
duration: [],
reset: false,
activeShortcuts: DEFAULT_SHORTCUTS,
});
}
let start = durationList[0];
const end = durationList[1];
// 处理和快捷方式的联动
const targetKey = reflectShortCuts([start, end], SHORTCUTMAP);
this.setState({ activeShortcuts: targetKey });
if (
targetKey === 'WHATDIDFOXSAY' &&
moment.duration(end - start).asMonths() > 3
) {
message.error('自定义时间不能超过3个月');
start = end.clone().add(-3, 'M');
}
// 校验和现有的是否是同一时间段,如果是则不通知父级元素
const _isSameDuration = isSameDuration(this.state.duration, durationList);
if (!_isSameDuration) {
this.setState({ duration: [start, end], reset: false });
this.props.dateChange([start, end], targetKey);
}
};
// 日期选择框打开和关闭的回调
rangePickerOpenChange = (status) => {
this.setState({ rangePickerOpen: status });
};
// 重置选择
resetDuration = () => {
if (this.state.reset === false) {
this.setState({
duration: SHORTCUTMAP[DEFAULT_SHORTCUTS].duration,
activeShortcuts: DEFAULT_SHORTCUTS,
rangePickerOpen: false,
reset: true,
});
this.props.dateChange(SHORTCUTMAP.D7.duration, DEFAULT_SHORTCUTS);
}
};
render() {
return (
<div className={ `duration-selector ${ this.props.className}`}>
<div className="duration-main">
<span style={ { color: '#666' }}>统计时间:</span>
<RangePicker
open={ this.state.rangePickerOpen}
onOpenChange={ this.rangePickerOpenChange}
onChange={ this.rangePickerChange}
value={ this.state.duration}
style={ { width: 240 }}
disabledDate={ getDisabledDate}
/>
<span onClick={ this.selectShortcuts}>
{ Object.keys(SHORTCUTMAP).map((key) => (
<Button
key={ key}
className={ `shortcut-btn ${ this.state.activeShortcuts === key ? 'active' : '' }`}
data-type={ key}
>
{ SHORTCUTMAP[key].name}
</Button>
))}
</span>
</div>
<div className="duration-operation">
<Button
className={ `reset-btn ${ this.state.reset ? 'active' : ''}`}
onClick={ this.resetDuration}
>
重置
</Button>
</div>
{ this.props.tip && !this.props.disabled && (
<div className="duration-tip">{ this.props.tip}</div>
)}
</div>
);
}
}
index.scss
.duration-selector {
position: relative;
display: flex;
align-items: center;
justify-content: space-between;
padding: 24px 18px 24px 0; .duration-main {
.ant-calendar-picker {
margin-right: 32px;
}
.shortcut-btn {
color: #999;
border-radius: 16px; &:hover {
color: #29a2ff;
background-color: #fff;
border-color: #29a2ff;
}
&:focus, &.active {
color: #fff;
background-color: #0086ff;
border-color: #0086ff;
}
& + .shortcut-btn {
margin-left: 12px;
}
}
}
.duration-operation {
.reset-btn {
color: #999; &:hover {
color: #29a2ff;
background-color: #fff;
border-color: #29a2ff;
}
&:focus, &.active {
color: #999;
border-color: #d9d9d9;
cursor: not-allowed;
opacity: 0.5;
}
}
}
.duration-tip {
position: absolute;
bottom: 2px;
left: 0;
color: #7f7f7f;
font-size: 12px;
}
}
(3)在别的地方使用该组件
<!--引用该组件 -->
<DurationSelector
className="duration-selector-wrapper"
dateChange={ handleDurationChange}
/>
import DurationSelector, {
SHORTCUTMAP,
DEFAULT_SHORTCUTS,
} from './index.js'; // 根据自己路径引入上述时间插件
const [filterParams, setFilterParams] = useState<any>({
beginTime: new Date(date[0]).getTime(),
endTime: new Date(date[1]).getTime(),
});
useEffect(() => {
handleFetch();
}, []);
// 区间选择器
const handleDurationChange = (data): void => {
const params = {
beginTime: new Date(data[0]).getTime(),
endTime: new Date(data[1]).getTime(),
};
setFilterParams({
...filterParams,
...params,
});
};
const handleFetch = async () => {
const params = {
beginTime: filterParams.beginTime,
endTime: filterParams.endTime,
channel,
};
};
const data = await queryYourPortData(params); //或者做一些根据时间,做接口数据处理
还没有评论,来说两句吧...