diff --git a/docs/zh-CN/components/calendar.md b/docs/zh-CN/components/calendar.md index e01e34f8ff4..89d6b9fd759 100644 --- a/docs/zh-CN/components/calendar.md +++ b/docs/zh-CN/components/calendar.md @@ -220,9 +220,12 @@ order: 36 当前组件会对外派发以下事件,可以通过`onEvent`来监听这些事件,并通过`actions`来配置执行的动作,在`actions`中可以通过`${事件参数名}`来获取事件产生的数据(`< 2.3.2 及以下版本 为 ${event.data.[事件参数名]}`),详细请查看[事件动作](../../docs/concepts/event-action)。 -| 事件名称 | 事件参数 | 说明 | -| -------- | ------------------------ | ---------------- | -| change | `value: string` 组件的值 | 时间值变化时触发 | +| 事件名称 | 事件参数 | 说明 | +| ---------- | ------------------------ | ------------------ | +| change | `value: string` 组件的值 | 时间值变化时触发 | +| click | `value: string` 组件的值 | 点击日期时触发 | +| mouseenter | `value: string` 组件的值 | 鼠标移入日期时触发 | +| mouseleave | `value: string` 组件的值 | 鼠标移出日期时触发 | ## 动作表 diff --git a/packages/amis-editor/src/plugin/Calendar.tsx b/packages/amis-editor/src/plugin/Calendar.tsx new file mode 100644 index 00000000000..7f854725c60 --- /dev/null +++ b/packages/amis-editor/src/plugin/Calendar.tsx @@ -0,0 +1,195 @@ +import {registerEditorPlugin, RendererPluginEvent} from 'amis-editor-core'; +import {BaseEventContext, BasePlugin, tipedLabel} from 'amis-editor-core'; +import {defaultValue, getSchemaTpl} from 'amis-editor-core'; +import {getEventControlConfig} from '../renderer/event-control'; +import {FormulaDateType} from '../renderer/FormulaControl'; +import type {Schema} from 'amis'; + +export class CalendarPlugin extends BasePlugin { + static id = 'CalendarPlugin'; + // 关联渲染器名字 + rendererName = 'calendar'; + $schema = '/schemas/Calendar.json'; + + // 组件名称 + name = '日历日程'; + isBaseComponent = true; + icon = 'fa fa-calendar'; + pluginIcon = 'inputDatetime'; + + panelTitle = '日历日程'; + + description = '展示日历及日程。'; + docLink = '/amis/zh-CN/components/calendor'; + tags = ['展示']; + + scaffold = { + type: 'page', + body: { + type: 'calendar', + value: '' + } + }; + previewSchema = { + ...this.scaffold + }; + + // 事件定义 + events: RendererPluginEvent[] = [ + { + eventName: 'change', + eventLabel: '值变化', + description: '时间值变化时触发', + dataSchema: [ + { + type: 'object', + properties: { + data: { + type: 'object', + title: '数据', + properties: { + value: { + type: 'string', + title: '当前日期' + } + } + } + } + } + ] + }, + { + eventName: 'click', + eventLabel: '点击', + description: '点击时触发', + dataSchema: [ + { + type: 'object', + properties: { + data: { + type: 'object', + title: '数据', + properties: { + value: { + type: 'string', + title: '当前日期' + } + } + } + } + } + ] + }, + { + eventName: 'mouseenter', + eventLabel: '鼠标移入', + description: '鼠标移入时触发', + dataSchema: [ + { + type: 'object', + properties: { + data: { + type: 'object', + title: '数据', + properties: { + value: { + type: 'string', + title: '当前日期' + } + } + } + } + } + ] + }, + { + eventName: 'mouseleave', + eventLabel: '鼠标移出', + description: '鼠标移出时触发', + dataSchema: [ + { + type: 'object', + properties: { + data: { + type: 'object', + title: '数据', + properties: { + value: { + type: 'string', + title: '当前日期' + } + } + } + } + } + ] + } + ]; + + actions = [ + { + actionType: 'clear', + actionLabel: '清空', + description: '清空' + }, + { + actionType: 'reset', + actionLabel: '重置', + description: '将值重置为resetValue,若没有配置resetValue,则清空' + }, + { + actionType: 'setValue', + actionLabel: '赋值', + description: '触发组件数据更新' + } + ]; + + panelJustify = true; + panelBodyCreator = (context: BaseEventContext) => { + return [ + getSchemaTpl('tabs', [ + { + title: '属性', + body: getSchemaTpl('collapseGroup', [ + { + title: '基本', + body: [ + getSchemaTpl('valueFormula', { + rendererSchema: { + type: 'input-date' + }, + placeholder: '请选择静态值', + header: '表达式或相对值', + DateTimeType: FormulaDateType.IsDate, + label: '默认值' + }) + ] + }, + getSchemaTpl('status') + ]) + }, + + { + title: '外观', + body: getSchemaTpl('collapseGroup', [ + getSchemaTpl('style:classNames', { + isFormItem: false + }) + ]) + }, + { + title: '事件', + className: 'p-none', + body: [ + getSchemaTpl('eventControl', { + name: 'onEvent', + ...getEventControlConfig(this.manager, context) + }) + ] + } + ]) + ]; + }; +} + +registerEditorPlugin(CalendarPlugin); diff --git a/packages/amis-editor/src/plugin/index.ts b/packages/amis-editor/src/plugin/index.ts index 7001b5b6eb7..b8d1686b0a6 100644 --- a/packages/amis-editor/src/plugin/index.ts +++ b/packages/amis-editor/src/plugin/index.ts @@ -105,6 +105,7 @@ export * from './Images'; // 图片集 export * from './Time'; // 时间展示 export * from './Date'; // 日期展示 export * from './Datetime'; // 日期时间展示 +export * from './Calendar'; // 日历日程展示 export * from './Tag'; // 标签 export * from './Json'; // JSON展示 export * from './Progress'; // 进度展示 diff --git a/packages/amis-ui/src/components/DatePicker.tsx b/packages/amis-ui/src/components/DatePicker.tsx index 0bf553889b6..7e039655698 100644 --- a/packages/amis-ui/src/components/DatePicker.tsx +++ b/packages/amis-ui/src/components/DatePicker.tsx @@ -332,6 +332,9 @@ export interface DateProps extends LocaleProps, ThemeProps { isEndDate?: boolean; disabledDate?: (date: moment.Moment) => any; + onClick?: (date: moment.Moment) => any; + onMouseEnter?: (date: moment.Moment) => any; + onMouseLeave?: (date: moment.Moment) => any; } export interface DatePickerState { @@ -844,7 +847,10 @@ export class DatePicker extends React.Component { onScheduleClick, mobileCalendarMode, label, - env + env, + onClick, + onMouseEnter, + onMouseLeave } = this.props; const __ = this.props.translate; @@ -937,6 +943,9 @@ export class DatePicker extends React.Component { embed={embed} mobileUI={mobileUI} isEndDate={isEndDate} + onClick={onClick} + onMouseEnter={onMouseEnter} + onMouseLeave={onMouseLeave} /> ); @@ -1027,6 +1036,9 @@ export class DatePicker extends React.Component { maxDate={maxDate} mobileUI={mobileUI} isEndDate={isEndDate} + onClick={onClick} + onMouseEnter={onMouseEnter} + onMouseLeave={onMouseLeave} // utc={utc} /> @@ -1066,6 +1078,9 @@ export class DatePicker extends React.Component { minDate={minDate} maxDate={maxDate} mobileUI={mobileUI} + onClick={onClick} + onMouseEnter={onMouseEnter} + onMouseLeave={onMouseLeave} // utc={utc} /> diff --git a/packages/amis-ui/src/components/calendar/Calendar.tsx b/packages/amis-ui/src/components/calendar/Calendar.tsx index 50a8600d9c3..978a506bf47 100644 --- a/packages/amis-ui/src/components/calendar/Calendar.tsx +++ b/packages/amis-ui/src/components/calendar/Calendar.tsx @@ -65,6 +65,9 @@ interface BaseDatePickerProps { ) => boolean; onViewModeChange?: (type: string) => void; requiredConfirm?: boolean; + onClick?: (date: moment.Moment) => any; + onMouseEnter?: (date: moment.Moment) => any; + onMouseLeave?: (date: moment.Moment) => any; onClose?: () => void; onChange?: (value: any, viewMode?: Extract) => void; isEndDate?: boolean; @@ -351,6 +354,9 @@ class BaseDatePicker extends React.Component< : this.props.viewMode || 'time'; this.state = state; + this.onClick = this.onClick.bind(this); + this.onMouseEnter = this.onMouseEnter.bind(this); + this.onMouseLeave = this.onMouseLeave.bind(this); } getUpdateOn = (formats: any) => { @@ -385,7 +391,10 @@ class BaseDatePicker extends React.Component< 'subtractTime', 'updateSelectedDate', 'localMoment', - 'handleClickOutside' + 'handleClickOutside', + 'onClick', + 'onMouseEnter', + 'onMouseLeave' ] }; @@ -517,8 +526,7 @@ class BaseDatePicker extends React.Component< }; }; - updateSelectedDate = (e: React.MouseEvent, close?: boolean) => { - const that: any = this; + getTargetDate = (e: React.MouseEvent) => { let target = e.currentTarget, modifier = 0, viewDate = this.state.viewDate, @@ -557,6 +565,12 @@ class BaseDatePicker extends React.Component< .minutes(currentDate.minutes()) .seconds(currentDate.seconds()) .milliseconds(currentDate.milliseconds()); + return date; + }; + + updateSelectedDate = (e: React.MouseEvent, close?: boolean) => { + const that: any = this; + const date = that.getTargetDate(e); if (!this.props.value) { var open = !(this.props.closeOnSelect && close); @@ -664,6 +678,21 @@ class BaseDatePicker extends React.Component< this.props.onClose && this.props.onClose(); }; + onClick(e: React.MouseEvent) { + const date = this.getTargetDate(e); + this.props.onClick && this.props.onClick(date); + } + + onMouseEnter(e: React.MouseEvent) { + const date = this.getTargetDate(e); + this.props.onMouseEnter && this.props.onMouseEnter(date); + } + + onMouseLeave(e: React.MouseEvent) { + const date = this.getTargetDate(e); + this.props.onMouseLeave && this.props.onMouseLeave(date); + } + render() { const {viewMode, timeFormat, dateFormat, timeRangeHeader, mobileUI} = this.props; diff --git a/packages/amis-ui/src/components/calendar/DaysView.tsx b/packages/amis-ui/src/components/calendar/DaysView.tsx index 4a0df629480..412921aac6c 100644 --- a/packages/amis-ui/src/components/calendar/DaysView.tsx +++ b/packages/amis-ui/src/components/calendar/DaysView.tsx @@ -43,6 +43,9 @@ interface CustomDaysViewProps extends LocaleProps { value: moment.Moment, viewMode?: Extract ) => void; + onClick: (event: React.MouseEvent) => void; + onMouseEnter: (event: React.MouseEvent) => void; + onMouseLeave: (event: React.MouseEvent) => void; onConfirm?: (value: number[], types: DateType[]) => void; setDateTimeState: (state: any) => void; showTime: () => void; @@ -188,7 +191,18 @@ export class CustomDaysView extends React.Component { classes.includes('rdtToday') ? {todayActiveStyle} : {} ); - if (!isDisabled) (dayProps as any).onClick = this.updateSelectedDate; + if (!isDisabled) { + (dayProps as any).onClick = (event: React.MouseEvent) => { + this.props.onClick(event); + this.updateSelectedDate(event); + }; + (dayProps as any).onMouseEnter = (event: React.MouseEvent) => { + this.props.onMouseEnter(event); + }; + (dayProps as any).onMouseLeave = (event: React.MouseEvent) => { + this.props.onMouseLeave(event); + }; + } days.push(renderer(dayProps, currentDate, selected)); diff --git a/packages/amis/src/renderers/Form/InputDate.tsx b/packages/amis/src/renderers/Form/InputDate.tsx index 84397b020cd..8d726db2213 100644 --- a/packages/amis/src/renderers/Form/InputDate.tsx +++ b/packages/amis/src/renderers/Form/InputDate.tsx @@ -572,6 +572,42 @@ export default class DateControl extends React.PureComponent< this.props.onChange(nextValue); } + // 点击日期事件 + @autobind + async handleClick(date: moment.Moment) { + const {dispatchEvent, utc, valueFormat, format} = this.props; + dispatchEvent( + 'click', + resolveEventData(this.props, { + value: (utc ? moment.utc(date) : date).format(valueFormat || format) + }) + ); + } + + // 鼠标移入日期事件 + @autobind + async handleMouseEnter(date: moment.Moment) { + const {dispatchEvent, utc, valueFormat, format} = this.props; + dispatchEvent( + 'mouseenter', + resolveEventData(this.props, { + value: (utc ? moment.utc(date) : date).format(valueFormat || format) + }) + ); + } + + // 鼠标移出日期事件 + @autobind + async handleMouseLeave(date: moment.Moment) { + const {dispatchEvent, utc, valueFormat, format} = this.props; + dispatchEvent( + 'mouseleave', + resolveEventData(this.props, { + value: (utc ? moment.utc(date) : date).format(valueFormat || format) + }) + ); + } + @autobind isDisabledDate(currentDate: moment.Moment) { const {disabledDate} = this.props; @@ -647,6 +683,9 @@ export default class DateControl extends React.PureComponent< onFocus={this.dispatchEvent} onBlur={this.dispatchEvent} disabledDate={this.isDisabledDate} + onClick={this.handleClick} + onMouseEnter={this.handleMouseEnter} + onMouseLeave={this.handleMouseLeave} /> );