qm-bus
Version:
千米公有云业务组件库
250 lines (229 loc) • 6.84 kB
JavaScript
import React, { Component } from 'react'
import { Input, Icon } from 'antd'
import moment, { Moment } from 'moment'
import 'moment/locale/zh-cn'
import './time-select.less'
moment.updateLocale('zh-cn', {
week: {
dow: 1, // 周一是一周的第一天
},
})
const add0 = (n) => (n < 10 ? `0${n}` : n)
/** 根据moment(xx) 返回 xxxx年xx月 第x周 和 weekList */
function _computed(date) {
const crtValue = date ? moment(date) : moment()
// 先获取到本月的第一天
let firstDay = moment(crtValue).startOf('month')
// 开始的日期
let startTime = firstDay.weekday() == 0 ? firstDay : firstDay.weekday(7)
// 如果当前比本月的第一个数组还小,退回到上一个月去计算
if (crtValue.isBefore(startTime)) {
firstDay = moment(crtValue.subtract(1, 'months')).startOf('month')
startTime = firstDay.weekday() == 0 ? firstDay : firstDay.weekday(7)
}
const weekList = []
let endTime
let weekIndex = 1
// 如果还在当前月份内
while (startTime.month() == crtValue.month()) {
endTime = moment(startTime).weekday(6)
weekList.push([moment(startTime), moment(endTime)])
if (date && !startTime.isAfter(date)) {
weekIndex = weekList.length
}
startTime.add(7, 'days')
}
const month = crtValue.format('MM')
const year = crtValue.format('YYYY')
return {
weekList,
weekIndex,
month,
year,
}
}
/** 根据xxxx年xx月 第x周 返回当前日期 如果x超过了最大 默认未最大周 */
function _getDate({ weekIndex, month, year }) {
const firstDay = moment(year + '-' + add0(month), 'YYYY-MM')
console.log(firstDay.isValid())
// 第一周初始值
let startTime = firstDay.weekday() == 0 ? firstDay : firstDay.weekday(7)
return startTime.add(weekIndex - 1, 'weeks')
}
/** 显示这里有个格式化 */
function _formatDate({ month, year, weekIndex }, format = 'YYYY-MM 第w周') {
month = Number(month)
const dateString = format.replace(
/([y]{2,4})(.+?)([m]{1,2})(.+?)([w]{1,2})(.+?)/i,
(match, y, s1, m, s2, w, s3) => {
let _y = y.length === 4 ? year : year.slice(2)
let _m = m.length === 2 ? (month >= 10 ? month : `0${month}`) : month
let _w = w.length === 2 ? `0${weekIndex}` : weekIndex
return `${_y}${s1}${_m}${s2}${_w}${s3}`
}
)
return dateString
}
export default class WeekPicker extends Component {
constructor(props) {
super(props)
this.container = null
const { weekList, weekIndex, month, year } = _computed(props.value)
this.state = {
/** 日历弹窗是否展开 */
open: false,
weekList,
weekIndex,
year,
month,
}
}
/** 显示日历弹窗 */
showPicker = () => {
const { weekList, weekIndex, month, year } = _computed(this.props.value)
this.setState({
open: true,
weekList,
weekIndex,
year,
month,
})
}
hidePicker = () => {
this.setState({
open: false,
})
}
/** 上个月 */
prevMonth = () => {
let { weekIndex } = this.state
let month = Number(this.state.month)
let year = Number(this.state.year)
if (month == 1) {
year--
month = 12
} else {
month--
}
const crtValue = _getDate({ month, year, weekIndex })
const { weekList, month: newMonth, year: newYear } = _computed(crtValue)
this.setState({
month: newMonth,
year: newYear,
weekList,
})
}
/** 下个月 */
nextMonth = () => {
let { weekIndex } = this.state
let month = Number(this.state.month)
let year = Number(this.state.year)
if (month == 12) {
year++
month = 1
} else {
month++
}
const crtValue = _getDate({ month, year, weekIndex })
const { weekList, month: newMonth, year: newYear } = _computed(crtValue)
this.setState({
month: newMonth,
year: newYear,
weekList,
})
}
/** 选择某一周 */
selectHandle = (monday) => {
const { weekList, weekIndex, month, year } = _computed(monday)
this.props.onChange(monday)
this.setState({
open: false,
weekList,
weekIndex,
month,
year,
})
}
render() {
const { open, weekList, weekIndex, year, month } = this.state
const { disabledDate, format, value } = this.props
// 这里展示的内容 应该是根据props传递过来的
const dataString = _formatDate(_computed(value), format)
return (
<span className="week-pick-box" style={this.props.style}>
<Input
placeholder="请选择日期"
value={value ? dataString : null}
onClick={this.showPicker}
/>
<Icon className="picker-suffix" type="calendar" />
{open && (
<Pick
prevMonth={this.prevMonth}
nextMonth={this.nextMonth}
disabledDate={disabledDate}
weekList={weekList}
selectHandle={this.selectHandle}
weekIndex={weekIndex}
hidePicker={this.hidePicker}
title={`${year}年${month}月`}
/>
)}
</span>
)
}
}
class Pick extends Component {
componentDidMount() {
document.addEventListener('click', this.clickOutsideHandle)
}
componentWillUnmount() {
document.removeEventListener('click', this.clickOutsideHandle)
}
// 点击其他区域 需要关闭日期选择框
clickOutsideHandle = (e) => {
if (e.target.offsetParent !== this.container) {
this.props.hidePicker()
}
}
render() {
const {
weekList,
prevMonth,
nextMonth,
selectHandle,
disabledDate,
title,
weekIndex,
} = this.props
return (
<div className="week-picker" ref={(el) => (this.container = el)}>
<div className="picker-header">
<div className="pre-month" onClick={prevMonth}>
<Icon type="double-left" />
</div>
<div className="current-month">{title}</div>
<div className="next-month" onClick={nextMonth}>
<Icon type="double-right" />
</div>
</div>
<div className="picker-body">
{weekList.map((week, index) => {
const [monday, sunday] = week
let className = weekIndex === index + 1 ? 'text current' : 'text'
const isDisabled = disabledDate(week) || false
if (isDisabled) className += ' disabled'
return (
<div className="picker-item">
<div
onClick={!isDisabled && (() => selectHandle(monday))}
className={className}>{`第${index + 1}周`}</div>
<div className="range">{`${monday.format('MM.DD')}-${sunday.format('MM.DD')}`}</div>
</div>
)
})}
</div>
</div>
)
}
}