feat: update calendar

pull/2682/head
tanjinzhou 2020-07-22 15:33:57 +08:00
parent afd13f908f
commit 88d3fc18c6
6 changed files with 74 additions and 65 deletions

@ -1 +1 @@
Subproject commit aae9db4ae607a00f4c8482c159bfaf71fe982595 Subproject commit e5569f28132b299accd77cbbbb7354f6308d25e5

View File

@ -1,3 +1,4 @@
import { inject } from 'vue';
import Select from '../select'; import Select from '../select';
import { Group, Button } from '../radio'; import { Group, Button } from '../radio';
import PropTypes from '../_util/vue-types'; import PropTypes from '../_util/vue-types';
@ -24,22 +25,26 @@ export const HeaderProps = {
yearSelectOffset: PropTypes.number, yearSelectOffset: PropTypes.number,
yearSelectTotal: PropTypes.number, yearSelectTotal: PropTypes.number,
type: PropTypes.string, type: PropTypes.string,
// onValueChange: PropTypes.(value: moment.Moment) => void,
// onTypeChange: PropTypes.(type: string) => void,
value: PropTypes.any, value: PropTypes.any,
validRange: PropTypes.array, validRange: PropTypes.array,
headerRender: PropTypes.func, headerRender: PropTypes.func,
onValueChange: PropTypes.func,
onTypeChange: PropTypes.func,
}; };
export default { export default {
name: 'CalendarHeader',
inheritAttrs: false,
props: initDefaultProps(HeaderProps, { props: initDefaultProps(HeaderProps, {
yearSelectOffset: 10, yearSelectOffset: 10,
yearSelectTotal: 20, yearSelectTotal: 20,
}), }),
inject: { setup() {
configProvider: { default: () => ConfigConsumerProps }, return {
configProvider: inject('configProvider', ConfigConsumerProps),
};
}, },
// private calenderHeaderNode: HTMLDivElement; // private calendarHeaderNode: HTMLDivElement;
methods: { methods: {
getYearSelectElement(prefixCls, year) { getYearSelectElement(prefixCls, year) {
const { yearSelectOffset, yearSelectTotal, locale = {}, fullscreen, validRange } = this; const { yearSelectOffset, yearSelectTotal, locale = {}, fullscreen, validRange } = this;
@ -62,7 +67,7 @@ export default {
class={`${prefixCls}-year-select`} class={`${prefixCls}-year-select`}
onChange={this.onYearChange} onChange={this.onYearChange}
value={String(year)} value={String(year)}
getPopupContainer={() => this.getCalenderHeaderNode()} getPopupContainer={() => this.calenderHeaderNode}
> >
{options} {options}
</Select> </Select>
@ -95,7 +100,7 @@ export default {
class={`${prefixCls}-month-select`} class={`${prefixCls}-month-select`}
value={String(month)} value={String(month)}
onChange={this.onMonthChange} onChange={this.onMonthChange}
getPopupContainer={() => this.getCalenderHeaderNode()} getPopupContainer={() => this.calendarHeaderNode}
> >
{options} {options}
</Select> </Select>
@ -128,16 +133,12 @@ export default {
}, },
onInternalTypeChange(e) { onInternalTypeChange(e) {
this.onTypeChange(e.target.value); this.triggerTypeChange(e.target.value);
}, },
onTypeChange(val) { triggerTypeChange(val) {
this.$emit('typeChange', val); this.$emit('typeChange', val);
}, },
getCalenderHeaderNode() {
return this.$refs.calenderHeaderNode;
},
getMonthYearSelections(getPrefixCls) { getMonthYearSelections(getPrefixCls) {
const { prefixCls: customizePrefixCls, type, value } = this.$props; const { prefixCls: customizePrefixCls, type, value } = this.$props;
@ -163,16 +164,19 @@ export default {
</Group> </Group>
); );
}, },
onValueChange() { triggerValueChange() {
this.$emit('valueChange', ...arguments); this.$emit('valueChange', ...arguments);
}, },
saveCalendarHeaderNode(node) {
this.calendarHeaderNode = node;
},
headerRenderCustom(headerRender) { headerRenderCustom(headerRender) {
const { type, value } = this.$props; const { type, value } = this.$props;
return headerRender({ return headerRender({
value, value,
type: type || 'month', type: type || 'month',
onChange: this.onValueChange, onChange: this.triggerValueChange,
onTypeChange: this.onTypeChange, onTypeChange: this.triggerTypeChange,
}); });
}, },
}, },
@ -186,7 +190,7 @@ export default {
return headerRender ? ( return headerRender ? (
this.headerRenderCustom(headerRender) this.headerRenderCustom(headerRender)
) : ( ) : (
<div class={`${prefixCls}-header`} ref="calenderHeaderNode"> <div class={`${prefixCls}-header`} ref={this.saveCalendarHeaderNode}>
{yearReactNode} {yearReactNode}
{monthReactNode} {monthReactNode}
{typeSwitch} {typeSwitch}

View File

@ -1,6 +1,7 @@
import { inject } from 'vue';
import PropTypes from '../_util/vue-types'; import PropTypes from '../_util/vue-types';
import BaseMixin from '../_util/BaseMixin'; import BaseMixin from '../_util/BaseMixin';
import { getOptionProps, hasProp, initDefaultProps, getListeners } from '../_util/props-util'; import { getOptionProps, hasProp, initDefaultProps } from '../_util/props-util';
import * as moment from 'moment'; import * as moment from 'moment';
import FullCalendar from '../vc-calendar/src/FullCalendar'; import FullCalendar from '../vc-calendar/src/FullCalendar';
import Header from './Header'; import Header from './Header';
@ -26,37 +27,38 @@ function isMomentArray(value) {
export const CalendarMode = PropTypes.oneOf(['month', 'year']); export const CalendarMode = PropTypes.oneOf(['month', 'year']);
export const CalendarProps = () => ({ export const CalendarProps = () => ({
monthCellRender: PropTypes.func,
dateCellRender: PropTypes.func,
monthFullCellRender: PropTypes.func,
dateFullCellRender: PropTypes.func,
prefixCls: PropTypes.string, prefixCls: PropTypes.string,
value: TimeType, value: TimeType,
defaultValue: TimeType, defaultValue: TimeType,
mode: CalendarMode, mode: CalendarMode,
fullscreen: PropTypes.bool, fullscreen: PropTypes.bool,
// dateCellRender: PropTypes.func,
// monthCellRender: PropTypes.func,
// dateFullCellRender: PropTypes.func,
// monthFullCellRender: PropTypes.func,
locale: PropTypes.object, locale: PropTypes.object,
// onPanelChange?: (date?: moment.Moment, mode?: CalendarMode) => void;
// onSelect?: (date?: moment.Moment) => void;
disabledDate: PropTypes.func, disabledDate: PropTypes.func,
validRange: PropTypes.custom(isMomentArray), validRange: PropTypes.custom(isMomentArray),
headerRender: PropTypes.func, headerRender: PropTypes.func,
valueFormat: PropTypes.string, valueFormat: PropTypes.string,
onPanelChange: PropTypes.func,
onSelect: PropTypes.func,
onChange: PropTypes.func,
'onUpdate:value': PropTypes.func,
}); });
const Calendar = { const Calendar = {
name: 'ACalendar', name: 'ACalendar',
inheritAttrs: false,
mixins: [BaseMixin], mixins: [BaseMixin],
props: initDefaultProps(CalendarProps(), { props: initDefaultProps(CalendarProps(), {
locale: {}, locale: {},
fullscreen: true, fullscreen: true,
}), }),
model: { setup() {
prop: 'value', return {
event: 'change', configProvider: inject('configProvider', ConfigConsumerProps),
}, };
inject: {
configProvider: { default: () => ConfigConsumerProps },
}, },
data() { data() {
const { value, defaultValue, valueFormat } = this; const { value, defaultValue, valueFormat } = this;
@ -88,17 +90,18 @@ const Calendar = {
}, },
onHeaderTypeChange(mode) { onHeaderTypeChange(mode) {
this.sMode = mode; this.sMode = mode;
this.onPanelChange(this.sValue, mode); this.triggerPanelChange(this.sValue, mode);
}, },
onPanelChange(value, mode) { triggerPanelChange(value, mode) {
const val = this.valueFormat ? momentToString(value, this.valueFormat) : value; const val = this.valueFormat ? momentToString(value, this.valueFormat) : value;
this.$emit('panelChange', val, mode); this.$emit('panelChange', val, mode);
if (value !== this.sValue) { if (value !== this.sValue) {
this.$emit('update:value', val);
this.$emit('change', val); this.$emit('change', val);
} }
}, },
onSelect(value) { triggerSelect(value) {
this.setValue(value, 'select'); this.setValue(value, 'select');
}, },
setValue(value, way) { setValue(value, way) {
@ -109,11 +112,11 @@ const Calendar = {
} }
if (way === 'select') { if (way === 'select') {
if (prevValue && prevValue.month() !== value.month()) { if (prevValue && prevValue.month() !== value.month()) {
this.onPanelChange(value, mode); this.triggerPanelChange(value, mode);
} }
this.$emit('select', valueFormat ? momentToString(value, valueFormat) : value); this.$emit('select', valueFormat ? momentToString(value, valueFormat) : value);
} else if (way === 'changePanel') { } else if (way === 'changePanel') {
this.onPanelChange(value, mode); this.triggerPanelChange(value, mode);
} }
}, },
getDateRange(validRange, disabledDate) { getDateRange(validRange, disabledDate) {
@ -141,8 +144,8 @@ const Calendar = {
return result; return result;
}, },
monthCellRender2(value) { monthCellRender2(value) {
const { _sPrefixCls, $scopedSlots } = this; const { _sPrefixCls, $slots } = this;
const monthCellRender = this.monthCellRender || $scopedSlots.monthCellRender || noop; const monthCellRender = this.monthCellRender || $slots.monthCellRender || noop;
return ( return (
<div class={`${_sPrefixCls}-month`}> <div class={`${_sPrefixCls}-month`}>
<div class={`${_sPrefixCls}-value`}>{value.localeData().monthsShort(value)}</div> <div class={`${_sPrefixCls}-value`}>{value.localeData().monthsShort(value)}</div>
@ -152,8 +155,8 @@ const Calendar = {
}, },
dateCellRender2(value) { dateCellRender2(value) {
const { _sPrefixCls, $scopedSlots } = this; const { _sPrefixCls, $slots } = this;
const dateCellRender = this.dateCellRender || $scopedSlots.dateCellRender || noop; const dateCellRender = this.dateCellRender || $slots.dateCellRender || noop;
return ( return (
<div class={`${_sPrefixCls}-date`}> <div class={`${_sPrefixCls}-date`}>
<div class={`${_sPrefixCls}-value`}>{zerofixed(value.date())}</div> <div class={`${_sPrefixCls}-value`}>{zerofixed(value.date())}</div>
@ -163,8 +166,8 @@ const Calendar = {
}, },
renderCalendar(locale, localeCode) { renderCalendar(locale, localeCode) {
const props = getOptionProps(this); const props = { ...getOptionProps(this), ...this.$attrs };
const { sValue: value, sMode: mode, $scopedSlots } = this; const { sValue: value, sMode: mode, $slots } = this;
if (value && localeCode) { if (value && localeCode) {
value.locale(localeCode); value.locale(localeCode);
} }
@ -173,8 +176,10 @@ const Calendar = {
fullscreen, fullscreen,
dateFullCellRender, dateFullCellRender,
monthFullCellRender, monthFullCellRender,
class: className,
style,
} = props; } = props;
const headerRender = this.headerRender || $scopedSlots.headerRender; const headerRender = this.headerRender || $slots.headerRender;
const getPrefixCls = this.configProvider.getPrefixCls; const getPrefixCls = this.configProvider.getPrefixCls;
const prefixCls = getPrefixCls('fullcalendar', customizePrefixCls); const prefixCls = getPrefixCls('fullcalendar', customizePrefixCls);
@ -183,15 +188,15 @@ const Calendar = {
// https://github.com/facebook/react/issues/12397 // https://github.com/facebook/react/issues/12397
this._sPrefixCls = prefixCls; this._sPrefixCls = prefixCls;
let cls = ''; let cls = className || '';
if (fullscreen) { if (fullscreen) {
cls += ` ${prefixCls}-fullscreen`; cls += ` ${prefixCls}-fullscreen`;
} }
const monthCellRender = const monthCellRender =
monthFullCellRender || $scopedSlots.monthFullCellRender || this.monthCellRender2; monthFullCellRender || $slots.monthFullCellRender || this.monthCellRender2;
const dateCellRender = const dateCellRender =
dateFullCellRender || $scopedSlots.dateFullCellRender || this.dateCellRender2; dateFullCellRender || $slots.dateFullCellRender || this.dateCellRender2;
let disabledDate = props.disabledDate; let disabledDate = props.disabledDate;
@ -199,25 +204,21 @@ const Calendar = {
disabledDate = this.getDateRange(props.validRange, disabledDate); disabledDate = this.getDateRange(props.validRange, disabledDate);
} }
const fullCalendarProps = { const fullCalendarProps = {
props: { ...props,
...props, ...this.$attrs,
Select: {}, Select: {},
locale: locale.lang, locale: locale.lang,
type: mode === 'year' ? 'month' : 'date', type: mode === 'year' ? 'month' : 'date',
prefixCls, prefixCls,
showHeader: false, showHeader: false,
value, value,
monthCellRender, monthCellRender,
dateCellRender, dateCellRender,
disabledDate, disabledDate,
}, onSelect: this.triggerSelect,
on: {
...getListeners(this),
select: this.onSelect,
},
}; };
return ( return (
<div class={cls}> <div class={cls} style={style}>
<Header <Header
fullscreen={fullscreen} fullscreen={fullscreen}
type={mode} type={mode}
@ -240,7 +241,7 @@ const Calendar = {
<LocaleReceiver <LocaleReceiver
componentName="Calendar" componentName="Calendar"
defaultLocale={this.getDefaultLocale} defaultLocale={this.getDefaultLocale}
scopedSlots={{ default: this.renderCalendar }} children={this.renderCalendar}
/> />
); );
}, },

View File

@ -34,6 +34,8 @@ const CalendarMixin = {
}, },
data() { data() {
this.onKeyDown = this.onKeyDown || noop;
this.onBlur = this.onBlur || noop;
const props = this.$props; const props = this.$props;
const sValue = props.value || props.defaultValue || getNowByCurrentStateValue(); const sValue = props.value || props.defaultValue || getNowByCurrentStateValue();
return { return {

View File

@ -4,7 +4,7 @@
</div> </div>
</template> </template>
<script> <script>
import demo from '../antdv-demo/docs/time-picker/demo/basic'; import demo from '../antdv-demo/docs/calendar/demo/basic';
export default { export default {
components: { components: {

View File

@ -34,6 +34,7 @@ import {
Slider, Slider,
Carousel, Carousel,
TimePicker, TimePicker,
Calendar,
notification, notification,
message, message,
} from 'ant-design-vue'; } from 'ant-design-vue';
@ -85,4 +86,5 @@ app
.use(Slider) .use(Slider)
.use(Carousel) .use(Carousel)
.use(TimePicker) .use(TimePicker)
.use(Calendar)
.mount('#app'); .mount('#app');