add calendar
parent
cee7acf327
commit
2cdffdc6b4
|
@ -0,0 +1,4 @@
|
||||||
|
// https://github.com/moment/moment/issues/3650
|
||||||
|
export default function callMoment (moment, ...args) {
|
||||||
|
return (moment.default || moment)(...args)
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
export const PREFIX_CLS = 'ant-fullcalendar'
|
|
@ -0,0 +1,130 @@
|
||||||
|
<script>
|
||||||
|
import { PREFIX_CLS } from './Constants'
|
||||||
|
import Select from '../select'
|
||||||
|
import { Group, Button } from '../radio'
|
||||||
|
import PropTypes from '@/components/_util/vue-types'
|
||||||
|
import { initDefaultProps } from '@/components/_util/props-util'
|
||||||
|
const Option = Select.Option
|
||||||
|
|
||||||
|
export const HeaderProps = {
|
||||||
|
prefixCls: PropTypes.string,
|
||||||
|
locale: PropTypes.any,
|
||||||
|
fullscreen: PropTypes.boolean,
|
||||||
|
yearSelectOffset: PropTypes.number,
|
||||||
|
yearSelectTotal: PropTypes.number,
|
||||||
|
type: PropTypes.string,
|
||||||
|
// onValueChange: PropTypes.(value: moment.Moment) => void,
|
||||||
|
// onTypeChange: PropTypes.(type: string) => void,
|
||||||
|
value: PropTypes.any,
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: initDefaultProps(HeaderProps, {
|
||||||
|
prefixCls: `${PREFIX_CLS}-header`,
|
||||||
|
yearSelectOffset: 10,
|
||||||
|
yearSelectTotal: 20,
|
||||||
|
}),
|
||||||
|
|
||||||
|
// private calenderHeaderNode: HTMLDivElement;
|
||||||
|
methods: {
|
||||||
|
getYearSelectElement (year) {
|
||||||
|
const { yearSelectOffset, yearSelectTotal, locale, prefixCls, fullscreen } = this
|
||||||
|
const start = year - yearSelectOffset
|
||||||
|
const end = start + yearSelectTotal
|
||||||
|
const suffix = locale.year === '年' ? '年' : ''
|
||||||
|
|
||||||
|
const options = []
|
||||||
|
for (let index = start; index < end; index++) {
|
||||||
|
options.push(<Option key={`${index}`}>{index + suffix}</Option>)
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<Select
|
||||||
|
size={fullscreen ? 'default' : 'small'}
|
||||||
|
dropdownMatchSelectWidth={false}
|
||||||
|
class={`${prefixCls}-year-select`}
|
||||||
|
onChange={this.onYearChange}
|
||||||
|
value={String(year)}
|
||||||
|
getPopupContainer={() => this.calenderHeaderNode}
|
||||||
|
>
|
||||||
|
{options}
|
||||||
|
</Select>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
|
||||||
|
getMonthsLocale (value) {
|
||||||
|
const current = value.clone()
|
||||||
|
const localeData = value.localeData()
|
||||||
|
const months = []
|
||||||
|
for (let i = 0; i < 12; i++) {
|
||||||
|
current.month(i)
|
||||||
|
months.push(localeData.monthsShort(current))
|
||||||
|
}
|
||||||
|
return months
|
||||||
|
},
|
||||||
|
|
||||||
|
getMonthSelectElement (month, months) {
|
||||||
|
const { prefixCls, fullscreen } = this
|
||||||
|
const options = []
|
||||||
|
|
||||||
|
for (let index = 0; index < 12; index++) {
|
||||||
|
options.push(<Option key={`${index}`}>{months[index]}</Option>)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Select
|
||||||
|
size={fullscreen ? 'default' : 'small'}
|
||||||
|
dropdownMatchSelectWidth={false}
|
||||||
|
class={`${prefixCls}-month-select`}
|
||||||
|
value={String(month)}
|
||||||
|
onChange={this.onMonthChange}
|
||||||
|
getPopupContainer={() => this.getCalenderHeaderNode}
|
||||||
|
>
|
||||||
|
{options}
|
||||||
|
</Select>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
|
||||||
|
onYearChange (year) {
|
||||||
|
const newValue = this.value.clone()
|
||||||
|
newValue.year(parseInt(year, 10))
|
||||||
|
this.$emit('valueChange', newValue)
|
||||||
|
},
|
||||||
|
|
||||||
|
onMonthChange (month) {
|
||||||
|
const newValue = this.value.clone()
|
||||||
|
newValue.month(parseInt(month, 10))
|
||||||
|
this.$emit('valueChange', newValue)
|
||||||
|
},
|
||||||
|
|
||||||
|
onTypeChange (e) {
|
||||||
|
this.$emit('typeChange', e.target.value)
|
||||||
|
},
|
||||||
|
|
||||||
|
getCalenderHeaderNode () {
|
||||||
|
return this.$refs.calenderHeaderNode
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
render () {
|
||||||
|
const { type, value, prefixCls, locale, fullscreen } = this
|
||||||
|
const yearSelect = this.getYearSelectElement(value.year())
|
||||||
|
const monthSelect = type === 'date'
|
||||||
|
? this.getMonthSelectElement(value.month(), this.getMonthsLocale(value)) : null
|
||||||
|
const size = fullscreen ? 'default' : 'small'
|
||||||
|
const typeSwitch = (
|
||||||
|
<Group onChange={this.onTypeChange} value={type} size={size}>
|
||||||
|
<Button value='date'>{locale.month}</Button>
|
||||||
|
<Button value='month'>{locale.year}</Button>
|
||||||
|
</Group>
|
||||||
|
)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div class={`${prefixCls}-header`} ref='calenderHeaderNode'>
|
||||||
|
{yearSelect}
|
||||||
|
{monthSelect}
|
||||||
|
{typeSwitch}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -0,0 +1,26 @@
|
||||||
|
---
|
||||||
|
order: 0
|
||||||
|
title:
|
||||||
|
zh-CN: 基本
|
||||||
|
en-US: Basic
|
||||||
|
---
|
||||||
|
|
||||||
|
## zh-CN
|
||||||
|
|
||||||
|
一个通用的日历面板,支持年/月切换。
|
||||||
|
|
||||||
|
## en-US
|
||||||
|
|
||||||
|
A basic calendar component with Year/Month switch.
|
||||||
|
|
||||||
|
````jsx
|
||||||
|
import { Calendar } from 'antd';
|
||||||
|
|
||||||
|
function onPanelChange(value, mode) {
|
||||||
|
console.log(value, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
ReactDOM.render(
|
||||||
|
<Calendar onPanelChange={onPanelChange} />
|
||||||
|
, mountNode);
|
||||||
|
````
|
|
@ -0,0 +1,28 @@
|
||||||
|
---
|
||||||
|
order: 2
|
||||||
|
title:
|
||||||
|
zh-CN: 卡片模式
|
||||||
|
en-US: Card
|
||||||
|
---
|
||||||
|
|
||||||
|
## zh-CN
|
||||||
|
|
||||||
|
用于嵌套在空间有限的容器中。
|
||||||
|
|
||||||
|
## en-US
|
||||||
|
|
||||||
|
Nested inside a container element for rendering in limited space.
|
||||||
|
|
||||||
|
````jsx
|
||||||
|
import { Calendar } from 'antd';
|
||||||
|
|
||||||
|
function onPanelChange(value, mode) {
|
||||||
|
console.log(value, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
ReactDOM.render(
|
||||||
|
<div style={{ width: 300, border: '1px solid #d9d9d9', borderRadius: 4 }}>
|
||||||
|
<Calendar fullscreen={false} onPanelChange={onPanelChange} />
|
||||||
|
</div>
|
||||||
|
, mountNode);
|
||||||
|
````
|
|
@ -0,0 +1,103 @@
|
||||||
|
---
|
||||||
|
order: 1
|
||||||
|
title:
|
||||||
|
zh-CN: 通知事项日历
|
||||||
|
en-US: Notice Calendar
|
||||||
|
---
|
||||||
|
|
||||||
|
## zh-CN
|
||||||
|
|
||||||
|
一个复杂的应用示例,用 `dateCellRender` 和 `monthCellRender` 函数来自定义需要渲染的数据。
|
||||||
|
|
||||||
|
## en-US
|
||||||
|
|
||||||
|
This component can be rendered by using `dateCellRender` and `monthCellRender` with the data you need.
|
||||||
|
|
||||||
|
````jsx
|
||||||
|
import { Calendar, Badge } from 'antd';
|
||||||
|
|
||||||
|
function getListData(value) {
|
||||||
|
let listData;
|
||||||
|
switch (value.date()) {
|
||||||
|
case 8:
|
||||||
|
listData = [
|
||||||
|
{ type: 'warning', content: 'This is warning event.' },
|
||||||
|
{ type: 'success', content: 'This is usual event.' },
|
||||||
|
]; break;
|
||||||
|
case 10:
|
||||||
|
listData = [
|
||||||
|
{ type: 'warning', content: 'This is warning event.' },
|
||||||
|
{ type: 'success', content: 'This is usual event.' },
|
||||||
|
{ type: 'error', content: 'This is error event.' },
|
||||||
|
]; break;
|
||||||
|
case 15:
|
||||||
|
listData = [
|
||||||
|
{ type: 'warning', content: 'This is warning event' },
|
||||||
|
{ type: 'success', content: 'This is very long usual event。。....' },
|
||||||
|
{ type: 'error', content: 'This is error event 1.' },
|
||||||
|
{ type: 'error', content: 'This is error event 2.' },
|
||||||
|
{ type: 'error', content: 'This is error event 3.' },
|
||||||
|
{ type: 'error', content: 'This is error event 4.' },
|
||||||
|
]; break;
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
return listData || [];
|
||||||
|
}
|
||||||
|
|
||||||
|
function dateCellRender(value) {
|
||||||
|
const listData = getListData(value);
|
||||||
|
return (
|
||||||
|
<ul className="events">
|
||||||
|
{
|
||||||
|
listData.map(item => (
|
||||||
|
<li key={item.content}>
|
||||||
|
<Badge status={item.type} text={item.content} />
|
||||||
|
</li>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</ul>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getMonthData(value) {
|
||||||
|
if (value.month() === 8) {
|
||||||
|
return 1394;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function monthCellRender(value) {
|
||||||
|
const num = getMonthData(value);
|
||||||
|
return num ? (
|
||||||
|
<div className="notes-month">
|
||||||
|
<section>{num}</section>
|
||||||
|
<span>Backlog number</span>
|
||||||
|
</div>
|
||||||
|
) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReactDOM.render(
|
||||||
|
<Calendar dateCellRender={dateCellRender} monthCellRender={monthCellRender} />
|
||||||
|
, mountNode);
|
||||||
|
````
|
||||||
|
|
||||||
|
````css
|
||||||
|
.events {
|
||||||
|
list-style: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
.events .ant-badge-status {
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
width: 100%;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
.notes-month {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 28px;
|
||||||
|
}
|
||||||
|
.notes-month section {
|
||||||
|
font-size: 28px;
|
||||||
|
}
|
||||||
|
````
|
|
@ -0,0 +1,46 @@
|
||||||
|
---
|
||||||
|
order: 3
|
||||||
|
title:
|
||||||
|
zh-CN: 选择功能
|
||||||
|
en-US: Selectable Calendar
|
||||||
|
---
|
||||||
|
|
||||||
|
## zh-CN
|
||||||
|
|
||||||
|
一个通用的日历面板,支持年/月切换。
|
||||||
|
|
||||||
|
## en-US
|
||||||
|
|
||||||
|
A basic calendar component with Year/Month switch.
|
||||||
|
|
||||||
|
````jsx
|
||||||
|
import { Calendar, Alert } from 'antd';
|
||||||
|
import moment from 'moment';
|
||||||
|
|
||||||
|
class App extends React.Component {
|
||||||
|
state = {
|
||||||
|
value: moment('2017-01-25'),
|
||||||
|
selectedValue: moment('2017-01-25'),
|
||||||
|
}
|
||||||
|
onSelect = (value) => {
|
||||||
|
this.setState({
|
||||||
|
value,
|
||||||
|
selectedValue: value,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
onPanelChange = (value) => {
|
||||||
|
this.setState({ value });
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
const { value, selectedValue } = this.state;
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Alert message={`You selected date: ${selectedValue && selectedValue.format('YYYY-MM-DD')}`} />
|
||||||
|
<Calendar value={value} onSelect={this.onSelect} onPanelChange={this.onPanelChange} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ReactDOM.render(<App />, mountNode);
|
||||||
|
````
|
|
@ -0,0 +1,45 @@
|
||||||
|
---
|
||||||
|
category: Components
|
||||||
|
type: Data Display
|
||||||
|
cols: 1
|
||||||
|
title: Calendar
|
||||||
|
---
|
||||||
|
|
||||||
|
Container for displaying data in calendar form.
|
||||||
|
|
||||||
|
## When To Use
|
||||||
|
|
||||||
|
When data is in the form of dates, such as schedules, timetables, prices calendar, lunar calendar. This component also supports Year/Month switch.
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
**Note:** Part of the Calendar's locale is read from `value`. So, please set the locale of `moment` correctly.
|
||||||
|
|
||||||
|
```jsx
|
||||||
|
// The default locale is en-US, if you want to use other locale, just set locale in entry file globaly.
|
||||||
|
// import moment from 'moment';
|
||||||
|
// import 'moment/locale/zh-cn';
|
||||||
|
// moment.locale('zh-cn');
|
||||||
|
|
||||||
|
<Calendar
|
||||||
|
dateCellRender={dateCellRender}
|
||||||
|
monthCellRender={monthCellRender}
|
||||||
|
onPanelChange={onPanelChange}
|
||||||
|
onSelect={onSelect}
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
| Property | Description | Type | Default |
|
||||||
|
| -------- | ----------- | ---- | ------- |
|
||||||
|
| dateCellRender | Customize the display of the date cell, the returned content will be appended to the cell | function(date: moment): ReactNode | - |
|
||||||
|
| dateFullCellRender | Customize the display of the date cell, the returned content will override the cell | function(date: moment): ReactNode | - |
|
||||||
|
| defaultValue | The date selected by default | [moment](http://momentjs.com/) | default date |
|
||||||
|
| disabledDate | Function that specifies the dates that cannot be selected | (currentDate: moment) => boolean | - |
|
||||||
|
| fullscreen | Whether to display in full-screen | boolean | `true` |
|
||||||
|
| locale | The calendar's locale | object | [default](https://github.com/ant-design/ant-design/blob/master/components/date-picker/locale/example.json) |
|
||||||
|
| mode | The display mode of the calendar | `month` \| `year` | `month` |
|
||||||
|
| monthCellRender | Customize the display of the month cell, the returned content will be appended to the cell | function(date: moment): ReactNode | - |
|
||||||
|
| monthFullCellRender | Customize the display of the month cell, the returned content will override the cell | function(date: moment): ReactNode | - |
|
||||||
|
| value | The current selected date | [moment](http://momentjs.com/) | current date |
|
||||||
|
| onPanelChange | Callback for when panel changes | function(date: moment, mode: string) | - |
|
||||||
|
| onSelect | Callback for when a date is selected | function(date: moment) | - |
|
|
@ -0,0 +1,204 @@
|
||||||
|
<script>
|
||||||
|
import PropTypes from '@/components/_util/vue-types'
|
||||||
|
import BaseMixin from '@/components/_util/BaseMixin'
|
||||||
|
import { getOptionProps, hasProp, initDefaultProps } from '@/components/_util/props-util'
|
||||||
|
import * as moment from 'moment'
|
||||||
|
import FullCalendar from '../vc-calendar/src/FullCalendar'
|
||||||
|
import LocaleReceiver from '../locale-provider/LocaleReceiver'
|
||||||
|
import { PREFIX_CLS } from './Constants'
|
||||||
|
import Header from './Header'
|
||||||
|
import callMoment from '../_util/callMoment'
|
||||||
|
import enUS from './locale/en_US'
|
||||||
|
|
||||||
|
export { HeaderProps } from './Header'
|
||||||
|
|
||||||
|
function noop () { return null }
|
||||||
|
|
||||||
|
function zerofixed (v) {
|
||||||
|
if (v < 10) {
|
||||||
|
return `0${v}`
|
||||||
|
}
|
||||||
|
return `${v}`
|
||||||
|
}
|
||||||
|
export const MomentType = {
|
||||||
|
type: Object,
|
||||||
|
validator: function (value) {
|
||||||
|
return moment.isMoment(value)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
export const CalendarMode = PropTypes.oneOf(['month', 'year'])
|
||||||
|
|
||||||
|
export const CalendarProps = () => ({
|
||||||
|
prefixCls: PropTypes.string,
|
||||||
|
value: MomentType,
|
||||||
|
defaultValue: MomentType,
|
||||||
|
mode: CalendarMode,
|
||||||
|
fullscreen: PropTypes.bool,
|
||||||
|
dateCellRender: PropTypes.func,
|
||||||
|
monthCellRender: PropTypes.func,
|
||||||
|
dateFullCellRender: PropTypes.func,
|
||||||
|
monthFullCellRender: PropTypes.func,
|
||||||
|
locale: PropTypes.any,
|
||||||
|
// onPanelChange?: (date?: moment.Moment, mode?: CalendarMode) => void;
|
||||||
|
// onSelect?: (date?: moment.Moment) => void;
|
||||||
|
disabledDate: PropTypes.func,
|
||||||
|
})
|
||||||
|
|
||||||
|
export default {
|
||||||
|
mixins: [BaseMixin],
|
||||||
|
props: initDefaultProps(CalendarProps(), {
|
||||||
|
locale: {},
|
||||||
|
fullscreen: true,
|
||||||
|
prefixCls: PREFIX_CLS,
|
||||||
|
mode: 'month',
|
||||||
|
}),
|
||||||
|
|
||||||
|
data () {
|
||||||
|
const value = this.value || this.defaultValue || callMoment(moment)
|
||||||
|
if (!moment.isMoment(value)) {
|
||||||
|
throw new Error(
|
||||||
|
'The value/defaultValue of Calendar must be a moment object, ',
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
sValue: value,
|
||||||
|
sMode: this.mode,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
value (val) {
|
||||||
|
this.setState({
|
||||||
|
sValue: val,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
mode (val) {
|
||||||
|
this.setState({
|
||||||
|
sMode: val,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
monthCellRender (value) {
|
||||||
|
const { prefixCls, monthCellRender = noop } = this
|
||||||
|
return (
|
||||||
|
<div class={`${prefixCls}-month`}>
|
||||||
|
<div class={`${prefixCls}-value`}>
|
||||||
|
{value.localeData().monthsShort(value)}
|
||||||
|
</div>
|
||||||
|
<div class={`${prefixCls}-content`}>
|
||||||
|
{monthCellRender(value)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
|
||||||
|
dateCellRender (value) {
|
||||||
|
const { prefixCls, dateCellRender = noop } = this
|
||||||
|
return (
|
||||||
|
<div class={`${prefixCls}-date`}>
|
||||||
|
<div class={`${prefixCls}-value`}>
|
||||||
|
{zerofixed(value.date())}
|
||||||
|
</div>
|
||||||
|
<div class={`${prefixCls}-content`}>
|
||||||
|
{dateCellRender(value)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
|
||||||
|
setValue (value, way) {
|
||||||
|
if (!hasProp(this, 'value')) {
|
||||||
|
this.setState({ sValue: value })
|
||||||
|
}
|
||||||
|
if (way === 'select') {
|
||||||
|
this.$emit('select', value)
|
||||||
|
} else if (way === 'changePanel') {
|
||||||
|
this.$emit('panelChange', value, this.sMode)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
setType (type) {
|
||||||
|
const mode = (type === 'date') ? 'month' : 'year'
|
||||||
|
if (this.sMode !== mode) {
|
||||||
|
this.setState({ sMode: mode })
|
||||||
|
this.$emit('panelChange', this.sValue, this.sMode)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
onHeaderValueChange (value) {
|
||||||
|
this.setValue(value, 'changePanel')
|
||||||
|
},
|
||||||
|
|
||||||
|
onHeaderTypeChange (type) {
|
||||||
|
this.setType(type)
|
||||||
|
},
|
||||||
|
|
||||||
|
onPanelChange (value, mode) {
|
||||||
|
this.$emit('panelChange', value, mode)
|
||||||
|
},
|
||||||
|
|
||||||
|
onSelect (value) {
|
||||||
|
this.setValue(value, 'select')
|
||||||
|
},
|
||||||
|
|
||||||
|
renderCalendar (locale, localeCode) {
|
||||||
|
const props = getOptionProps(this)
|
||||||
|
const { sValue: value, sMode: mode, $listeners } = this
|
||||||
|
if (value && localeCode) {
|
||||||
|
value.locale(localeCode)
|
||||||
|
}
|
||||||
|
const { prefixCls, fullscreen, dateFullCellRender, monthFullCellRender } = props
|
||||||
|
const type = (mode === 'year') ? 'month' : 'date'
|
||||||
|
|
||||||
|
let cls = ''
|
||||||
|
if (fullscreen) {
|
||||||
|
cls += (` ${prefixCls}-fullscreen`)
|
||||||
|
}
|
||||||
|
|
||||||
|
const monthCellRender = monthFullCellRender || this.monthCellRender
|
||||||
|
const dateCellRender = dateFullCellRender || this.dateCellRender
|
||||||
|
const fullCalendarProps = {
|
||||||
|
props: {
|
||||||
|
...props,
|
||||||
|
Select: noop,
|
||||||
|
locale: locale.lang,
|
||||||
|
type: type,
|
||||||
|
prefixCls: prefixCls,
|
||||||
|
showHeader: false,
|
||||||
|
value: value,
|
||||||
|
monthCellRender: monthCellRender,
|
||||||
|
dateCellRender: dateCellRender,
|
||||||
|
},
|
||||||
|
on: {
|
||||||
|
...$listeners,
|
||||||
|
select: this.onSelect,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div class={cls}>
|
||||||
|
<Header
|
||||||
|
fullscreen={fullscreen}
|
||||||
|
type={type}
|
||||||
|
value={value}
|
||||||
|
locale={locale.lang}
|
||||||
|
prefixCls={prefixCls}
|
||||||
|
onTypeChange={this.onHeaderTypeChange}
|
||||||
|
onValueChange={this.onHeaderValueChange}
|
||||||
|
/>
|
||||||
|
<FullCalendar {...fullCalendarProps}/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
render () {
|
||||||
|
return (
|
||||||
|
<LocaleReceiver
|
||||||
|
componentName='Calendar'
|
||||||
|
defaultLocale={enUS}
|
||||||
|
children={this.renderCalendar}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -0,0 +1,46 @@
|
||||||
|
---
|
||||||
|
category: Components
|
||||||
|
type: Data Display
|
||||||
|
subtitle: 日历
|
||||||
|
cols: 1
|
||||||
|
title: Calendar
|
||||||
|
---
|
||||||
|
|
||||||
|
按照日历形式展示数据的容器。
|
||||||
|
|
||||||
|
## 何时使用
|
||||||
|
|
||||||
|
当数据是日期或按照日期划分时,例如日程、课表、价格日历等,农历等。目前支持年/月切换。
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
**注意:**Calendar 部分 locale 是从 value 中读取,所以请先正确设置 moment 的 locale。
|
||||||
|
|
||||||
|
```jsx
|
||||||
|
// 默认语言为 en-US,所以如果需要使用其他语言,推荐在入口文件全局设置 locale
|
||||||
|
// import moment from 'moment';
|
||||||
|
// import 'moment/locale/zh-cn';
|
||||||
|
// moment.locale('zh-cn');
|
||||||
|
|
||||||
|
<Calendar
|
||||||
|
dateCellRender={dateCellRender}
|
||||||
|
monthCellRender={monthCellRender}
|
||||||
|
onPanelChange={onPanelChange}
|
||||||
|
onSelect={onSelect}
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
| 参数 | 说明 | 类型 | 默认值 |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| dateCellRender | 自定义渲染日期单元格,返回内容会被追加到单元格 | function(date: moment): ReactNode | 无 |
|
||||||
|
| dateFullCellRender | 自定义渲染日期单元格,返回内容覆盖单元格 | function(date: moment): ReactNode | 无 |
|
||||||
|
| defaultValue | 默认展示的日期 | [moment](http://momentjs.com/) | 默认日期 |
|
||||||
|
| disabledDate | 不可选择的日期 | (currentDate: moment) => boolean | 无 |
|
||||||
|
| fullscreen | 是否全屏显示 | boolean | true |
|
||||||
|
| locale | 国际化配置 | object | [默认配置](https://github.com/ant-design/ant-design/blob/master/components/date-picker/locale/example.json) |
|
||||||
|
| mode | 初始模式,`month/year` | string | month |
|
||||||
|
| monthCellRender | 自定义渲染月单元格,返回内容会被追加到单元格 | function(date: moment): ReactNode | 无 |
|
||||||
|
| monthFullCellRender | 自定义渲染月单元格,返回内容覆盖单元格 | function(date: moment): ReactNode | 无 |
|
||||||
|
| value | 展示日期 | [moment](http://momentjs.com/) | 当前日期 |
|
||||||
|
| onPanelChange | 日期面板变化回调 | function(date: moment, mode: string) | 无 |
|
||||||
|
| onSelect | 点击选择日期回调 | function(date: moment) | 无 |
|
|
@ -0,0 +1,2 @@
|
||||||
|
import ar_EG from '../../date-picker/locale/ar_EG';
|
||||||
|
export default ar_EG;
|
|
@ -0,0 +1,2 @@
|
||||||
|
import bg_BG from '../../date-picker/locale/bg_BG';
|
||||||
|
export default bg_BG;
|
|
@ -0,0 +1,2 @@
|
||||||
|
import ca_ES from '../../date-picker/locale/ca_ES';
|
||||||
|
export default ca_ES;
|
|
@ -0,0 +1,2 @@
|
||||||
|
import cs_CZ from '../../date-picker/locale/cs_CZ';
|
||||||
|
export default cs_CZ;
|
|
@ -0,0 +1,2 @@
|
||||||
|
import de_DE from '../../date-picker/locale/de_DE';
|
||||||
|
export default de_DE;
|
|
@ -0,0 +1,2 @@
|
||||||
|
import el_GR from '../../date-picker/locale/el_GR';
|
||||||
|
export default el_GR;
|
|
@ -0,0 +1,2 @@
|
||||||
|
import en_GB from '../../date-picker/locale/en_GB';
|
||||||
|
export default en_GB;
|
|
@ -0,0 +1,2 @@
|
||||||
|
import en_US from '../../date-picker/locale/en_US';
|
||||||
|
export default en_US;
|
|
@ -0,0 +1,2 @@
|
||||||
|
import es_ES from '../../date-picker/locale/es_ES';
|
||||||
|
export default es_ES;
|
|
@ -0,0 +1,2 @@
|
||||||
|
import et_EE from '../../date-picker/locale/et_EE';
|
||||||
|
export default et_EE;
|
|
@ -0,0 +1,2 @@
|
||||||
|
import fa_IR from '../../date-picker/locale/fa_IR';
|
||||||
|
export default fa_IR;
|
|
@ -0,0 +1,2 @@
|
||||||
|
import fi_FI from '../../date-picker/locale/fi_FI';
|
||||||
|
export default fi_FI;
|
|
@ -0,0 +1,2 @@
|
||||||
|
import fr_BE from '../../date-picker/locale/fr_BE';
|
||||||
|
export default fr_BE;
|
|
@ -0,0 +1,2 @@
|
||||||
|
import fr_FR from '../../date-picker/locale/fr_FR';
|
||||||
|
export default fr_FR;
|
|
@ -0,0 +1,2 @@
|
||||||
|
import is_IS from '../../date-picker/locale/is_IS';
|
||||||
|
export default is_IS;
|
|
@ -0,0 +1,2 @@
|
||||||
|
import it_IT from '../../date-picker/locale/it_IT';
|
||||||
|
export default it_IT;
|
|
@ -0,0 +1,2 @@
|
||||||
|
import ja_JP from '../../date-picker/locale/ja_JP';
|
||||||
|
export default ja_JP;
|
|
@ -0,0 +1,2 @@
|
||||||
|
import ko_KR from '../../date-picker/locale/ko_KR';
|
||||||
|
export default ko_KR;
|
|
@ -0,0 +1,2 @@
|
||||||
|
import ku_IQ from '../../date-picker/locale/ku_IQ';
|
||||||
|
export default ku_IQ;
|
|
@ -0,0 +1,2 @@
|
||||||
|
import nb_NO from '../../date-picker/locale/nb_NO';
|
||||||
|
export default nb_NO;
|
|
@ -0,0 +1,2 @@
|
||||||
|
import nl_BE from '../../date-picker/locale/nl_BE';
|
||||||
|
export default nl_BE;
|
|
@ -0,0 +1,2 @@
|
||||||
|
import nl_NL from '../../date-picker/locale/nl_NL';
|
||||||
|
export default nl_NL;
|
|
@ -0,0 +1,2 @@
|
||||||
|
import pl_PL from '../../date-picker/locale/pl_PL';
|
||||||
|
export default pl_PL;
|
|
@ -0,0 +1,2 @@
|
||||||
|
import pt_BR from '../../date-picker/locale/pt_BR';
|
||||||
|
export default pt_BR;
|
|
@ -0,0 +1,2 @@
|
||||||
|
import pt_PT from '../../date-picker/locale/pt_PT';
|
||||||
|
export default pt_PT;
|
|
@ -0,0 +1,2 @@
|
||||||
|
import ru_RU from '../../date-picker/locale/ru_RU';
|
||||||
|
export default ru_RU;
|
|
@ -0,0 +1,2 @@
|
||||||
|
import sk_SK from '../../date-picker/locale/sk_SK';
|
||||||
|
export default sk_SK;
|
|
@ -0,0 +1,2 @@
|
||||||
|
import sr_RS from '../../date-picker/locale/sr_RS';
|
||||||
|
export default sr_RS;
|
|
@ -0,0 +1,2 @@
|
||||||
|
import sv_SE from '../../date-picker/locale/sv_SE';
|
||||||
|
export default sv_SE;
|
|
@ -0,0 +1,2 @@
|
||||||
|
import th_TH from '../../date-picker/locale/th_TH';
|
||||||
|
export default th_TH;
|
|
@ -0,0 +1,2 @@
|
||||||
|
import tr_TR from '../../date-picker/locale/tr_TR';
|
||||||
|
export default tr_TR;
|
|
@ -0,0 +1,2 @@
|
||||||
|
import uk_UA from '../../date-picker/locale/uk_UA';
|
||||||
|
export default uk_UA;
|
|
@ -0,0 +1,2 @@
|
||||||
|
import vi_VN from '../../date-picker/locale/vi_VN';
|
||||||
|
export default vi_VN;
|
|
@ -0,0 +1,2 @@
|
||||||
|
import zh_CN from '../../date-picker/locale/zh_CN';
|
||||||
|
export default zh_CN;
|
|
@ -0,0 +1,2 @@
|
||||||
|
import zh_TW from '../../date-picker/locale/zh_TW';
|
||||||
|
export default zh_TW;
|
|
@ -0,0 +1,6 @@
|
||||||
|
import '../../style/index.less'
|
||||||
|
import './index.less'
|
||||||
|
|
||||||
|
// style dependencies
|
||||||
|
import '../../select/style'
|
||||||
|
import '../../radio/style'
|
|
@ -0,0 +1,266 @@
|
||||||
|
@import "../../style/themes/default";
|
||||||
|
@import "../../style/mixins/index";
|
||||||
|
|
||||||
|
@full-calendar-prefix-cls: ~"@{ant-prefix}-fullcalendar";
|
||||||
|
|
||||||
|
.@{full-calendar-prefix-cls} {
|
||||||
|
.reset-component;
|
||||||
|
outline: none;
|
||||||
|
border-top: @border-width-base @border-style-base @border-color-base;
|
||||||
|
|
||||||
|
&-month-select {
|
||||||
|
margin-left: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-header {
|
||||||
|
padding: 11px 16px 11px 0;
|
||||||
|
text-align: right;
|
||||||
|
|
||||||
|
.@{ant-prefix}-select-dropdown {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.@{ant-prefix}-radio-group {
|
||||||
|
margin-left: 8px;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
label.@{ant-prefix}-radio-button {
|
||||||
|
height: 22px;
|
||||||
|
line-height: 20px;
|
||||||
|
padding: 0 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-date-panel {
|
||||||
|
position: relative;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-calendar-body {
|
||||||
|
padding: 8px 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
max-width: 100%;
|
||||||
|
background-color: transparent;
|
||||||
|
width: 100%;
|
||||||
|
height: 256px;
|
||||||
|
}
|
||||||
|
|
||||||
|
table,
|
||||||
|
th,
|
||||||
|
td {
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
td {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-calendar-table {
|
||||||
|
border-spacing: 0;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-column-header {
|
||||||
|
line-height: 18px;
|
||||||
|
padding: 0;
|
||||||
|
width: 33px;
|
||||||
|
text-align: center;
|
||||||
|
.@{full-calendar-prefix-cls}-column-header-inner {
|
||||||
|
display: block;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-week-number-header {
|
||||||
|
.@{full-calendar-prefix-cls}-column-header-inner {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-month,
|
||||||
|
&-date {
|
||||||
|
text-align: center;
|
||||||
|
transition: all .3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-value {
|
||||||
|
display: block;
|
||||||
|
margin: 0 auto;
|
||||||
|
color: @text-color;
|
||||||
|
border-radius: @border-radius-sm;
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
padding: 0;
|
||||||
|
background: transparent;
|
||||||
|
line-height: 24px;
|
||||||
|
transition: all .3s;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: @item-hover-bg;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
background: @primary-color;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-month-panel-cell &-value {
|
||||||
|
width: 48px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-today &-value,
|
||||||
|
&-month-panel-current-cell &-value {
|
||||||
|
box-shadow: 0 0 0 1px @primary-color inset;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-selected-day &-value,
|
||||||
|
&-month-panel-selected-cell &-value {
|
||||||
|
background: @primary-color;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-disabled-cell-first-of-row &-value {
|
||||||
|
border-top-left-radius: @border-radius-base;
|
||||||
|
border-bottom-left-radius: @border-radius-base;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-disabled-cell-last-of-row &-value {
|
||||||
|
border-top-right-radius: @border-radius-base;
|
||||||
|
border-bottom-right-radius: @border-radius-base;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-last-month-cell &-value,
|
||||||
|
&-next-month-btn-day &-value {
|
||||||
|
color: @disabled-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-month-panel-table {
|
||||||
|
table-layout: fixed;
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: separate;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-content {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
left: 0;
|
||||||
|
bottom: -9px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-fullscreen {
|
||||||
|
border-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-fullscreen &-table {
|
||||||
|
table-layout: fixed;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-fullscreen &-header {
|
||||||
|
.@{ant-prefix}-radio-group {
|
||||||
|
margin-left: 16px;
|
||||||
|
}
|
||||||
|
label.@{ant-prefix}-radio-button {
|
||||||
|
height: @input-height-base;
|
||||||
|
line-height: @input-height-base - 2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-fullscreen &-month,
|
||||||
|
&-fullscreen &-date {
|
||||||
|
text-align: left;
|
||||||
|
margin: 0 4px;
|
||||||
|
display: block;
|
||||||
|
color: @text-color;
|
||||||
|
height: 116px;
|
||||||
|
padding: 4px 8px;
|
||||||
|
border-top: 2px solid @border-color-split;
|
||||||
|
transition: background .3s;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: @item-hover-bg;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
background: @primary-2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-fullscreen &-column-header {
|
||||||
|
text-align: right;
|
||||||
|
padding-right: 12px;
|
||||||
|
padding-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-fullscreen &-value {
|
||||||
|
text-align: right;
|
||||||
|
background: transparent;
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-fullscreen &-today &-value {
|
||||||
|
color: @text-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-fullscreen &-month-panel-current-cell &-month,
|
||||||
|
&-fullscreen &-today &-date {
|
||||||
|
border-top-color: @primary-color;
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-fullscreen &-month-panel-current-cell &-value,
|
||||||
|
&-fullscreen &-today &-value {
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-fullscreen &-month-panel-selected-cell &-month,
|
||||||
|
&-fullscreen &-selected-day &-date {
|
||||||
|
background: @primary-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-fullscreen &-month-panel-selected-cell &-value,
|
||||||
|
&-fullscreen &-selected-day &-value {
|
||||||
|
color: @primary-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-fullscreen &-last-month-cell &-date,
|
||||||
|
&-fullscreen &-next-month-btn-day &-date {
|
||||||
|
color: @disabled-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-fullscreen &-content {
|
||||||
|
height: 90px;
|
||||||
|
overflow-y: auto;
|
||||||
|
position: static;
|
||||||
|
width: auto;
|
||||||
|
left: auto;
|
||||||
|
bottom: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-disabled-cell &-date {
|
||||||
|
&,
|
||||||
|
&:hover {
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-disabled-cell:not(&-today) &-date {
|
||||||
|
&,
|
||||||
|
&:hover {
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-disabled-cell &-value {
|
||||||
|
color: @disabled-color;
|
||||||
|
border-radius: 0;
|
||||||
|
width: auto;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue