mirror of
https://gitee.com/baidu/amis.git
synced 2024-11-30 02:58:05 +08:00
feat:日历组件展示日程 (#3058)
* feat:日历组件展示日程 * fix: 修改schema * fix: schedule参数说明修改 * fix: 修改schedules参数描述 * fix: 代码调整 * fix: 参数color改为classname * fix: readme文档补充 * feat: 日历组件支持从上下文中获取数据 * fix: 日历组件data获取条件修改 Co-authored-by: hongyang03 <hongyang03@baidu.com>
This commit is contained in:
parent
6d5016d526
commit
eac8e7e533
@ -312,6 +312,185 @@ order: 13
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## 日历日程
|
||||||
|
|
||||||
|
```schema: scope="body"
|
||||||
|
{
|
||||||
|
"type": "input-date",
|
||||||
|
"embed": true,
|
||||||
|
"schedules": [
|
||||||
|
{
|
||||||
|
"startTime": "2021-12-11 05:14:00",
|
||||||
|
"endTime": "2021-12-11 06:14:00",
|
||||||
|
"content": "这是一个日程1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"startTime": "2021-12-21 05:14:00",
|
||||||
|
"endTime": "2021-12-22 05:14:00",
|
||||||
|
"content": "这是一个日程2"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 日历日程-自定义颜色
|
||||||
|
|
||||||
|
```schema: scope="body"
|
||||||
|
{
|
||||||
|
"type": "input-date",
|
||||||
|
"embed": true,
|
||||||
|
"schedules": [
|
||||||
|
{
|
||||||
|
"startTime": "2021-12-11 05:14:00",
|
||||||
|
"endTime": "2021-12-11 06:14:00",
|
||||||
|
"content": "这是一个日程1",
|
||||||
|
"className": "bg-success"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"startTime": "2021-12-21 05:14:00",
|
||||||
|
"endTime": "2021-12-22 05:14:00",
|
||||||
|
"content": "这是一个日程2",
|
||||||
|
"className": "bg-info"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```schema: scope="body"
|
||||||
|
{
|
||||||
|
"type": "input-date",
|
||||||
|
"embed": true,
|
||||||
|
"scheduleClassNames": ["bg-success", "bg-info"],
|
||||||
|
"schedules": [
|
||||||
|
{
|
||||||
|
"startTime": "2021-12-11 05:14:00",
|
||||||
|
"endTime": "2021-12-11 06:14:00",
|
||||||
|
"content": "这是一个日程1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"startTime": "2021-12-21 05:14:00",
|
||||||
|
"endTime": "2021-12-22 05:14:00",
|
||||||
|
"content": "这是一个日程2"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 日历日程-自定义日程展示
|
||||||
|
```schema: scope="body"
|
||||||
|
{
|
||||||
|
"type": "input-date",
|
||||||
|
"embed": true,
|
||||||
|
"schedules": [
|
||||||
|
{
|
||||||
|
"startTime": "2021-12-11 05:14:00",
|
||||||
|
"endTime": "2021-12-11 06:14:00",
|
||||||
|
"content": "这是一个日程1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"startTime": "2021-12-21 05:14:00",
|
||||||
|
"endTime": "2021-12-22 05:14:00",
|
||||||
|
"content": "这是一个日程2"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"scheduleAction": {
|
||||||
|
"actionType": "drawer",
|
||||||
|
"drawer": {
|
||||||
|
"title": "日程",
|
||||||
|
"body": {
|
||||||
|
"type": "table",
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"name": "time",
|
||||||
|
"label": "时间"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "content",
|
||||||
|
"label": "内容"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"data": "${scheduleData}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 日历日程-支持从数据源中获取日程
|
||||||
|
```schema
|
||||||
|
{
|
||||||
|
"type": "page",
|
||||||
|
"data": {
|
||||||
|
"schedules": [
|
||||||
|
{
|
||||||
|
"startTime": "2021-12-11 05:14:00",
|
||||||
|
"endTime": "2021-12-11 06:14:00",
|
||||||
|
"content": "这是一个日程1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"startTime": "2021-12-21 05:14:00",
|
||||||
|
"endTime": "2021-12-22 05:14:00",
|
||||||
|
"content": "这是一个日程2"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "input-date",
|
||||||
|
"embed": true,
|
||||||
|
"schedules": "${schedules}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 放大模式
|
||||||
|
|
||||||
|
```schema: scope="body"
|
||||||
|
{
|
||||||
|
"type": "input-date",
|
||||||
|
"embed": true,
|
||||||
|
"largeMode": true,
|
||||||
|
"schedules": [
|
||||||
|
{
|
||||||
|
"startTime": "2021-12-11 05:14:00",
|
||||||
|
"endTime": "2021-12-11 06:14:00",
|
||||||
|
"content": "这是一个日程1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"startTime": "2021-12-12 02:14:00",
|
||||||
|
"endTime": "2021-12-13 05:14:00",
|
||||||
|
"content": "这是一个日程2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"startTime": "2021-12-20 05:14:00",
|
||||||
|
"endTime": "2021-12-21 05:14:00",
|
||||||
|
"content": "这是一个日程3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"startTime": "2021-12-21 05:14:00",
|
||||||
|
"endTime": "2021-12-22 05:14:00",
|
||||||
|
"content": "这是一个日程4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"startTime": "2021-12-22 02:14:00",
|
||||||
|
"endTime": "2021-12-23 05:14:00",
|
||||||
|
"content": "这是一个日程5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"startTime": "2021-12-22 02:14:00",
|
||||||
|
"endTime": "2021-12-22 05:14:00",
|
||||||
|
"content": "这是一个日程6"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"startTime": "2021-12-22 02:14:00",
|
||||||
|
"endTime": "2021-12-22 05:14:00",
|
||||||
|
"content": "这是一个日程7"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## 原生日期组件
|
## 原生日期组件
|
||||||
|
|
||||||
原生数字日期将直接使用浏览器的实现,最终展现效果和浏览器有关,而且只支持 `min`、`max`、`step` 这几个属性设置。
|
原生数字日期将直接使用浏览器的实现,最终展现效果和浏览器有关,而且只支持 `min`、`max`、`step` 这几个属性设置。
|
||||||
@ -348,3 +527,7 @@ order: 13
|
|||||||
| clearable | `boolean` | `true` | 是否可清除 |
|
| clearable | `boolean` | `true` | 是否可清除 |
|
||||||
| embed | `boolean` | `false` | 是否内联模式 |
|
| embed | `boolean` | `false` | 是否内联模式 |
|
||||||
| timeConstraints | `object` | `true` | 请参考: [react-datetime](https://github.com/YouCanBookMe/react-datetime) |
|
| timeConstraints | `object` | `true` | 请参考: [react-datetime](https://github.com/YouCanBookMe/react-datetime) |
|
||||||
|
| schedules | `Array<{startTime: Date, endTime: Date, content: any, className?: string}> \| string` | | 日历中展示日程,可设置静态数据或从上下文中取数据,className参考[背景色](https://baidu.gitee.io/amis/zh-CN/style/background/background-color) |
|
||||||
|
| scheduleClassNames | `Array<string>` | `['bg-warning', 'bg-danger', 'bg-success', 'bg-info', 'bg-secondary']` | 日历中展示日程的颜色,参考[背景色](https://baidu.gitee.io/amis/zh-CN/style/background/background-color) |
|
||||||
|
| scheduleAction | `SchemaNode` | | 自定义日程展示 |
|
||||||
|
| largeMode | `boolean` | `false` | 放大模式 |
|
||||||
|
81
scss/components/_calendar.scss
Normal file
81
scss/components/_calendar.scss
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
|
||||||
|
.#{$ns}ScheduleCalendar {
|
||||||
|
&-icon {
|
||||||
|
position: absolute;
|
||||||
|
bottom: var(--Calendar-icon-bottom);
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
display: block;
|
||||||
|
width: var(--Calendar-icon-width);
|
||||||
|
height: var(--Calendar-icon-height);
|
||||||
|
border-radius: 50%;
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
&-action {
|
||||||
|
display: block;
|
||||||
|
padding: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
border: none;
|
||||||
|
background: transparent;
|
||||||
|
color: inherit;
|
||||||
|
&:not(:disabled):not(.is-disabled):hover {
|
||||||
|
color: inherit;
|
||||||
|
background: transparent;
|
||||||
|
border-color: transparent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.rdtDay {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-text-overflow {
|
||||||
|
white-space:nowrap;
|
||||||
|
overflow:hidden;
|
||||||
|
text-overflow:ellipsis;
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.#{$ns}ScheduleCalendar-large {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
.rdtPicker {
|
||||||
|
width: 100%;
|
||||||
|
table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
border-spacing: 0;
|
||||||
|
td {
|
||||||
|
border: var(--Calendar-borderWidth) solid var(--borderColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.rdtDay {
|
||||||
|
height: var(--Calendar-rdt-day);
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
.#{$ns}ScheduleCalendar-large-day-wrap {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
min-width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
.#{$ns}ScheduleCalendar-large-schedule-content {
|
||||||
|
position: relative;
|
||||||
|
z-index: 10;
|
||||||
|
border-radius: var(--borderRadius);
|
||||||
|
text-align: left;
|
||||||
|
padding: var(--Calendar-schedule-content-padding);
|
||||||
|
height: var(--Calendar-schedule-content-height);
|
||||||
|
color: var(--Calendar-schedule-content-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.#{$ns}ScheduleCalendar-action {
|
||||||
|
z-index: 20;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
}
|
@ -37,6 +37,7 @@
|
|||||||
@import '../components/button-group';
|
@import '../components/button-group';
|
||||||
@import '../components/dropdown';
|
@import '../components/dropdown';
|
||||||
@import '../components/each';
|
@import '../components/each';
|
||||||
|
@import '../components/calendar';
|
||||||
@import '../components/collapse';
|
@import '../components/collapse';
|
||||||
@import '../components/collapse-group';
|
@import '../components/collapse-group';
|
||||||
@import '../components/color';
|
@import '../components/color';
|
||||||
|
@ -221,6 +221,15 @@ $L1: 0px 4px 6px 0px rgba(8, 14, 26, 0.06),
|
|||||||
--Switch-onDisabled-color: #{$G11};
|
--Switch-onDisabled-color: #{$G11};
|
||||||
// --Switch-onDisabled-circle-BackgroundColor: #fff;
|
// --Switch-onDisabled-circle-BackgroundColor: #fff;
|
||||||
|
|
||||||
|
--Calendar-icon-bottom: #{px2rem(-4px)};
|
||||||
|
--Calendar-icon-width: #{px2rem(10px)};
|
||||||
|
--Calendar-icon-height: #{px2rem(10px)};
|
||||||
|
--Calendar-borderWidth: #{px2rem(1px)};
|
||||||
|
--Calendar-rdt-day: #{px2rem(100px)};
|
||||||
|
--Calendar-schedule-content-padding: 0 #{px2rem(4px)};
|
||||||
|
--Calendar-schedule-content-height: #{px2rem(20px)};
|
||||||
|
--Calendar-schedule-content-color: #{$white};
|
||||||
|
|
||||||
--ColorPicker-borderWidth: #{px2rem(1px)};
|
--ColorPicker-borderWidth: #{px2rem(1px)};
|
||||||
--ColorPicker-borderRadius: #{$R3};
|
--ColorPicker-borderRadius: #{$R3};
|
||||||
--ColorPicker-bg: var(--white);
|
--ColorPicker-bg: var(--white);
|
||||||
|
@ -278,6 +278,15 @@ export interface DateProps extends LocaleProps, ThemeProps {
|
|||||||
borderMode?: 'full' | 'half' | 'none';
|
borderMode?: 'full' | 'half' | 'none';
|
||||||
// 是否为内嵌模式,如果开启就不是 picker 了,直接页面点选。
|
// 是否为内嵌模式,如果开启就不是 picker 了,直接页面点选。
|
||||||
embed?: boolean;
|
embed?: boolean;
|
||||||
|
schedules?: Array<{
|
||||||
|
startTime: Date,
|
||||||
|
endTime: Date,
|
||||||
|
content: any,
|
||||||
|
className?: string
|
||||||
|
}>;
|
||||||
|
scheduleClassNames?: Array<string>;
|
||||||
|
largeMode?: boolean;
|
||||||
|
onScheduleClick?: (scheduleData: any) => void;
|
||||||
|
|
||||||
// 下面那个千万不要写,写了就会导致 keyof DateProps 得到的结果是 string | number;
|
// 下面那个千万不要写,写了就会导致 keyof DateProps 得到的结果是 string | number;
|
||||||
// [propName: string]: any;
|
// [propName: string]: any;
|
||||||
@ -302,7 +311,8 @@ export class DatePicker extends React.Component<DateProps, DatePickerState> {
|
|||||||
viewMode: 'days' as 'years' | 'months' | 'days' | 'time',
|
viewMode: 'days' as 'years' | 'months' | 'days' | 'time',
|
||||||
shortcuts: '',
|
shortcuts: '',
|
||||||
closeOnSelect: true,
|
closeOnSelect: true,
|
||||||
overlayPlacement: 'auto'
|
overlayPlacement: 'auto',
|
||||||
|
scheduleClassNames: ['bg-warning', 'bg-danger', 'bg-success', 'bg-info', 'bg-secondary']
|
||||||
};
|
};
|
||||||
state: DatePickerState = {
|
state: DatePickerState = {
|
||||||
isOpened: false,
|
isOpened: false,
|
||||||
@ -546,7 +556,11 @@ export class DatePicker extends React.Component<DateProps, DatePickerState> {
|
|||||||
format,
|
format,
|
||||||
borderMode,
|
borderMode,
|
||||||
embed,
|
embed,
|
||||||
minDate
|
minDate,
|
||||||
|
schedules,
|
||||||
|
largeMode,
|
||||||
|
scheduleClassNames,
|
||||||
|
onScheduleClick
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
const __ = this.props.translate;
|
const __ = this.props.translate;
|
||||||
@ -554,12 +568,33 @@ export class DatePicker extends React.Component<DateProps, DatePickerState> {
|
|||||||
let date: moment.Moment | undefined = this.state.value;
|
let date: moment.Moment | undefined = this.state.value;
|
||||||
|
|
||||||
if (embed) {
|
if (embed) {
|
||||||
|
let schedulesData: DateProps['schedules'] = undefined;
|
||||||
|
if (schedules && Array.isArray(schedules)) {
|
||||||
|
// 设置日程颜色
|
||||||
|
let index = 0;
|
||||||
|
schedulesData = schedules.map((schedule: any) => {
|
||||||
|
let className = schedule.className;
|
||||||
|
if (!className && scheduleClassNames) {
|
||||||
|
className = scheduleClassNames[index];
|
||||||
|
index++;
|
||||||
|
if (index >= scheduleClassNames.length) {
|
||||||
|
index = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
...schedule,
|
||||||
|
className
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={cx(
|
className={cx(
|
||||||
`DateCalendar`,
|
`DateCalendar`,
|
||||||
{
|
{
|
||||||
'is-disabled': disabled
|
'is-disabled': disabled,
|
||||||
|
'ScheduleCalendar': schedulesData,
|
||||||
|
'ScheduleCalendar-large': largeMode
|
||||||
},
|
},
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
@ -578,6 +613,9 @@ export class DatePicker extends React.Component<DateProps, DatePickerState> {
|
|||||||
locale={locale}
|
locale={locale}
|
||||||
minDate={minDate}
|
minDate={minDate}
|
||||||
// utc={utc}
|
// utc={utc}
|
||||||
|
schedules={schedulesData}
|
||||||
|
largeMode={largeMode}
|
||||||
|
onScheduleClick={onScheduleClick}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -28,6 +28,14 @@ interface BaseDatePickerProps
|
|||||||
year?: number,
|
year?: number,
|
||||||
date?: moment.Moment
|
date?: moment.Moment
|
||||||
) => JSX.Element;
|
) => JSX.Element;
|
||||||
|
schedules?: Array<{
|
||||||
|
startTime: Date;
|
||||||
|
endTime: Date;
|
||||||
|
content: string | React.ReactElement;
|
||||||
|
color?: string;
|
||||||
|
}>;
|
||||||
|
largeMode?: boolean;
|
||||||
|
onScheduleClick?: (scheduleData: any) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
class BaseDatePicker extends ReactDatePicker {
|
class BaseDatePicker extends ReactDatePicker {
|
||||||
@ -82,7 +90,10 @@ class BaseDatePicker extends ReactDatePicker {
|
|||||||
'nextIcon',
|
'nextIcon',
|
||||||
'isEndDate',
|
'isEndDate',
|
||||||
'classnames',
|
'classnames',
|
||||||
'minDate'
|
'minDate',
|
||||||
|
'schedules',
|
||||||
|
'largeMode',
|
||||||
|
'onScheduleClick'
|
||||||
].forEach(key => (props[key] = (this.props as any)[key]));
|
].forEach(key => (props[key] = (this.props as any)[key]));
|
||||||
|
|
||||||
return props;
|
return props;
|
||||||
|
@ -5,6 +5,7 @@ import React from 'react';
|
|||||||
import Downshift from 'downshift';
|
import Downshift from 'downshift';
|
||||||
import {LocaleProps, localeable} from '../../locale';
|
import {LocaleProps, localeable} from '../../locale';
|
||||||
import {ClassNamesFn} from '../../theme';
|
import {ClassNamesFn} from '../../theme';
|
||||||
|
import find from 'lodash/find';
|
||||||
|
|
||||||
interface CustomDaysViewProps extends LocaleProps {
|
interface CustomDaysViewProps extends LocaleProps {
|
||||||
classPrefix?: string;
|
classPrefix?: string;
|
||||||
@ -39,6 +40,14 @@ interface CustomDaysViewProps extends LocaleProps {
|
|||||||
updateSelectedDate: (event: React.MouseEvent<any>, close?: boolean) => void;
|
updateSelectedDate: (event: React.MouseEvent<any>, close?: boolean) => void;
|
||||||
handleClickOutside: () => void;
|
handleClickOutside: () => void;
|
||||||
classnames: ClassNamesFn;
|
classnames: ClassNamesFn;
|
||||||
|
schedules?: Array<{
|
||||||
|
startTime: Date,
|
||||||
|
endTime: Date,
|
||||||
|
content: any,
|
||||||
|
className?: string
|
||||||
|
}>;
|
||||||
|
largeMode?: boolean;
|
||||||
|
onScheduleClick?: (scheduleData: any) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class CustomDaysView extends DaysView {
|
export class CustomDaysView extends DaysView {
|
||||||
@ -117,6 +126,86 @@ export class CustomDaysView extends DaysView {
|
|||||||
};
|
};
|
||||||
|
|
||||||
renderDay = (props: any, currentDate: moment.Moment) => {
|
renderDay = (props: any, currentDate: moment.Moment) => {
|
||||||
|
if (this.props.schedules) {
|
||||||
|
let schedule: any[] = [];
|
||||||
|
this.props.schedules.forEach((item: any) => {
|
||||||
|
if (currentDate.isSameOrAfter(moment(item.startTime).subtract(1, 'days')) && currentDate.isSameOrBefore(item.endTime)) {
|
||||||
|
schedule.push(item);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (schedule.length > 0) {
|
||||||
|
const cx = this.props.classnames;
|
||||||
|
const __ = this.props.translate;
|
||||||
|
// 日程数据
|
||||||
|
const scheduleData = {
|
||||||
|
scheduleData: schedule.map((item: any) => {
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
time: moment(item.startTime).format('YYYY-MM-DD HH:mm:ss') + ' - ' + moment(item.endTime).format('YYYY-MM-DD HH:mm:ss'),
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
currentDate
|
||||||
|
};
|
||||||
|
|
||||||
|
// 放大模式
|
||||||
|
if (this.props.largeMode) {
|
||||||
|
let showSchedule: any[] = [];
|
||||||
|
for (let i = 0; i < schedule.length; i++) {
|
||||||
|
if (showSchedule.length > 3) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (moment(schedule[i].startTime).isSame(currentDate, 'day')) {
|
||||||
|
showSchedule.push(schedule[i]);
|
||||||
|
}
|
||||||
|
else if (currentDate.weekday() === 0) {
|
||||||
|
// 周一重新设置日程
|
||||||
|
showSchedule.push({
|
||||||
|
...schedule[i],
|
||||||
|
width: moment(schedule[i].endTime).date() - currentDate.date()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[0, 1, 2].forEach((i: number) => {
|
||||||
|
const findSchedule = find(schedule, (item: any) => item.height === i);
|
||||||
|
if (findSchedule && findSchedule !== showSchedule[i] && currentDate.weekday() !== 0) {
|
||||||
|
// 生成一个空白格占位
|
||||||
|
showSchedule.splice(i, 0, {
|
||||||
|
width: 1,
|
||||||
|
className: 'bg-transparent',
|
||||||
|
content: ''
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
showSchedule[i] && (showSchedule[i].height = i);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// 最多展示3个
|
||||||
|
showSchedule = showSchedule.slice(0, 3);
|
||||||
|
const scheduleDiv = showSchedule.map((item: any, index: number) => {
|
||||||
|
const width = item.width || Math.min(moment(item.endTime).diff(moment(item.startTime), 'days') + 1, 7 - moment(item.startTime).weekday());
|
||||||
|
return <div key={props.key + 'content' + index}
|
||||||
|
className={cx('ScheduleCalendar-large-schedule-content', item.className)}
|
||||||
|
style={{width: width + '00%'}}>
|
||||||
|
<div className={cx('ScheduleCalendar-text-overflow')}>{item.content}</div>
|
||||||
|
</div>;
|
||||||
|
});
|
||||||
|
return <td {...props} onClick={() => this.props.onScheduleClick && this.props.onScheduleClick(scheduleData)}>
|
||||||
|
<div className={cx('ScheduleCalendar-large-day-wrap')}>
|
||||||
|
<div className={cx('ScheduleCalendar-large-schedule-header')}>{currentDate.date()}</div>
|
||||||
|
{scheduleDiv}
|
||||||
|
{schedule.length > 3 && <div className={cx('ScheduleCalendar-large-schedule-footer')}>{schedule.length - 3} {__('more')}</div>}
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
}
|
||||||
|
|
||||||
|
// 正常模式
|
||||||
|
const ScheduleIcon = <span className={cx('ScheduleCalendar-icon', schedule[0].className)}></span>;
|
||||||
|
return <td {...props} onClick={() => this.props.onScheduleClick && this.props.onScheduleClick(scheduleData)}>
|
||||||
|
{currentDate.date()}
|
||||||
|
{ScheduleIcon}
|
||||||
|
</td>;
|
||||||
|
}
|
||||||
|
}
|
||||||
return <td {...props}>{currentDate.date()}</td>;
|
return <td {...props}>{currentDate.date()}</td>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {FormItem, FormControlProps, FormBaseControl} from './Item';
|
import {FormItem, FormControlProps, FormBaseControl} from './Item';
|
||||||
import cx from 'classnames';
|
import cx from 'classnames';
|
||||||
import {filterDate} from '../../utils/tpl-builtin';
|
import {filterDate, isPureVariable, resolveVariableAndFilter} from '../../utils/tpl-builtin';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import 'moment/locale/zh-cn';
|
import 'moment/locale/zh-cn';
|
||||||
import DatePicker from '../../components/DatePicker';
|
import DatePicker from '../../components/DatePicker';
|
||||||
|
import {SchemaObject} from '../../Schema';
|
||||||
|
import {createObject, anyChanged} from '../../utils/helper';
|
||||||
|
|
||||||
export interface InputDateBaseControlSchema extends FormBaseControl {
|
export interface InputDateBaseControlSchema extends FormBaseControl {
|
||||||
/**
|
/**
|
||||||
@ -85,6 +87,24 @@ export interface DateControlSchema extends InputDateBaseControlSchema {
|
|||||||
* 限制最大日期
|
* 限制最大日期
|
||||||
*/
|
*/
|
||||||
maxDate?: string;
|
maxDate?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 日程
|
||||||
|
*/
|
||||||
|
schedules?: Array<{
|
||||||
|
startTime: Date,
|
||||||
|
endTime: Date,
|
||||||
|
content: any,
|
||||||
|
className?: string
|
||||||
|
}> | string;
|
||||||
|
/**
|
||||||
|
* 日程显示颜色自定义
|
||||||
|
*/
|
||||||
|
scheduleClassNames?: Array<string>;
|
||||||
|
/**
|
||||||
|
* 日程点击展示
|
||||||
|
*/
|
||||||
|
scheduleAction?: SchemaObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -267,6 +287,12 @@ export interface DateProps extends FormControlProps {
|
|||||||
interface DateControlState {
|
interface DateControlState {
|
||||||
minDate?: moment.Moment;
|
minDate?: moment.Moment;
|
||||||
maxDate?: moment.Moment;
|
maxDate?: moment.Moment;
|
||||||
|
schedules?: Array<{
|
||||||
|
startTime: Date,
|
||||||
|
endTime: Date,
|
||||||
|
content: any,
|
||||||
|
className?: string
|
||||||
|
}>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class DateControl extends React.PureComponent<
|
export default class DateControl extends React.PureComponent<
|
||||||
@ -304,9 +330,18 @@ export default class DateControl extends React.PureComponent<
|
|||||||
setPrinstineValue((utc ? moment.utc(date) : date).format(format));
|
setPrinstineValue((utc ? moment.utc(date) : date).format(format));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let schedulesData = props.schedules;
|
||||||
|
if (typeof schedulesData === 'string') {
|
||||||
|
const resolved = resolveVariableAndFilter(schedulesData, data, '| raw');
|
||||||
|
if (Array.isArray(resolved)) {
|
||||||
|
schedulesData = resolved;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
minDate: minDate ? filterDate(minDate, data, format) : undefined,
|
minDate: minDate ? filterDate(minDate, data, format) : undefined,
|
||||||
maxDate: maxDate ? filterDate(maxDate, data, format) : undefined
|
maxDate: maxDate ? filterDate(maxDate, data, format) : undefined,
|
||||||
|
schedules: schedulesData
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -334,6 +369,47 @@ export default class DateControl extends React.PureComponent<
|
|||||||
: undefined
|
: undefined
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (anyChanged(['schedules', 'data'], prevProps, props)
|
||||||
|
&& (typeof props.schedules === 'string' && isPureVariable(props.schedules))
|
||||||
|
) {
|
||||||
|
const schedulesData = resolveVariableAndFilter(props.schedules, props.data, '| raw');
|
||||||
|
const preSchedulesData = resolveVariableAndFilter(prevProps.schedules, prevProps.data, '| raw');
|
||||||
|
if (Array.isArray(schedulesData) && preSchedulesData !== schedulesData) {
|
||||||
|
this.setState({
|
||||||
|
schedules: schedulesData
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 日程点击事件
|
||||||
|
onScheduleClick(scheduleData: any) {
|
||||||
|
const {scheduleAction, onAction, data, translate: __} = this.props;
|
||||||
|
const defaultscheduleAction = {
|
||||||
|
actionType: 'dialog',
|
||||||
|
dialog: {
|
||||||
|
title: __('Schedule'),
|
||||||
|
actions: [],
|
||||||
|
body: {
|
||||||
|
type: 'table',
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
name: 'time',
|
||||||
|
label: __('Time')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'content',
|
||||||
|
label: __('Content')
|
||||||
|
}
|
||||||
|
],
|
||||||
|
data: '${scheduleData}'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
onAction && onAction(null, scheduleAction || defaultscheduleAction, createObject(data, scheduleData));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
@ -348,6 +424,8 @@ export default class DateControl extends React.PureComponent<
|
|||||||
format,
|
format,
|
||||||
timeFormat,
|
timeFormat,
|
||||||
valueFormat,
|
valueFormat,
|
||||||
|
largeMode,
|
||||||
|
render,
|
||||||
...rest
|
...rest
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
@ -363,6 +441,9 @@ export default class DateControl extends React.PureComponent<
|
|||||||
format={valueFormat || format}
|
format={valueFormat || format}
|
||||||
{...this.state}
|
{...this.state}
|
||||||
classnames={cx}
|
classnames={cx}
|
||||||
|
schedules={this.state.schedules}
|
||||||
|
largeMode={largeMode}
|
||||||
|
onScheduleClick={this.onScheduleClick.bind(this)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
Loading…
Reference in New Issue
Block a user