Skip to content

Commit daf0b98

Browse files
✨ [feature] add feature of caption customized(lanjingling0510#31)
1 parent fb2c2ef commit daf0b98

8 files changed

Lines changed: 366 additions & 109 deletions

File tree

examples/basic/index.js

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -25,21 +25,6 @@ import DatePicker from '../../lib/index';
2525
}
2626

2727
render() {
28-
const monthMap = {
29-
'01': 'Jan',
30-
'02': 'Feb',
31-
'03': 'Mar',
32-
'04': 'Apr',
33-
'05': 'May',
34-
'06': 'Jun',
35-
'07': 'Jul',
36-
'08': 'Aug',
37-
'09': 'Sep',
38-
'10': 'Oct',
39-
'11': 'Nov',
40-
'12': 'Dec',
41-
};
42-
4328
return (
4429
<div className="App">
4530
<p className="select-time ">
@@ -74,11 +59,27 @@ import DatePicker from '../../lib/index';
7459
</div>
7560
<DatePicker
7661
value={this.state.time}
77-
dateSteps={[1, 1, 5]}
7862
max={new Date()}
79-
dateFormat={['YYYY', ['MM', (month) => monthMap[month]], 'DD']}
8063
theme={this.state.theme}
8164
isOpen={this.state.isOpen}
65+
showCaption
66+
dateConfig={{
67+
'year': {
68+
format: 'YYYY',
69+
caption: '年',
70+
step: 1,
71+
},
72+
'month': {
73+
format: 'M',
74+
caption: '月',
75+
step: 1,
76+
},
77+
'date': {
78+
format: 'D',
79+
caption: '日',
80+
step: 1,
81+
},
82+
}}
8283
onSelect={this.handleSelect}
8384
onCancel={this.handleToggle(false)} />
8485
</div>

lib/DatePicker.js

Lines changed: 83 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import React, { Component } from 'react';
66
import DatePickerItem from './DatePickerItem.js';
77
import PureRender from './pureRender.js';
88
import { convertDate, nextDate } from './time.js';
9+
import { dateConfigMap } from './dataSource';
910

1011
type Props = {
1112
theme: string,
@@ -14,9 +15,9 @@ type Props = {
1415
max: Object,
1516
customHeader?: React.Element<*>,
1617
showHeader: boolean,
17-
dateFormat: Array<*>,
18-
dateSteps: Array<*>,
19-
showFormat: string,
18+
showCaption: boolean,
19+
dateConfig: Object | Array<string>,
20+
headerFormat: string,
2021
confirmText: string,
2122
cancelText: string,
2223
onSelect: Function,
@@ -27,6 +28,18 @@ type State = {
2728
value: Date,
2829
}
2930

31+
/**
32+
* 大写首字母
33+
* @param {String} 字符串
34+
*/
35+
const capitalize = ([first, ...rest]) => first.toUpperCase() + rest.join('');
36+
37+
/**
38+
* 判断数组
39+
* @param {any} val
40+
*/
41+
const isArray = val => Object.prototype.toString.apply(val) === '[object Array]';
42+
3043
/**
3144
* Class DatePicker Component Class
3245
* @extends Component
@@ -38,6 +51,18 @@ class DatePicker extends Component<void, Props, State> {
3851
value: nextDate(this.props.value),
3952
};
4053

54+
if ('dateFormat' in props) {
55+
console.warn('dateFormat已经被弃用, 请使用dateConfig属性配置');
56+
}
57+
58+
if ('dateSteps' in props) {
59+
console.warn('dateSteps已经被弃用, 请使用dateConfig属性配置');
60+
}
61+
62+
if ('showFormat' in props) {
63+
console.warn('headerFormat, 请使用dateConfig属性');
64+
}
65+
4166
this.handleFinishBtnClick = this.handleFinishBtnClick.bind(this);
4267
this.handleDateSelect = this.handleDateSelect.bind(this);
4368
}
@@ -96,31 +121,79 @@ class DatePicker extends Component<void, Props, State> {
96121
this.setState({ value });
97122
}
98123

124+
/**
125+
* 格式化dateConfig
126+
* @param {*} dataConfig dateConfig属性
127+
*/
128+
normalizeDateConfig(dataConfig) {
129+
const configList = [];
130+
if (isArray(dataConfig)) {
131+
for (let i = 0; i < dataConfig.length; i++) {
132+
const value = dataConfig[i];
133+
if (typeof value === 'string') {
134+
const lowerCaseKey = value.toLocaleLowerCase();
135+
configList.push({
136+
...dateConfigMap[lowerCaseKey],
137+
type: capitalize(lowerCaseKey),
138+
});
139+
}
140+
}
141+
} else {
142+
for (const key in dataConfig) {
143+
if (dataConfig.hasOwnProperty(key)) {
144+
const lowerCaseKey = key.toLocaleLowerCase();
145+
if (dateConfigMap.hasOwnProperty(lowerCaseKey)) {
146+
configList.push({
147+
...dateConfigMap[lowerCaseKey],
148+
...dataConfig[key],
149+
type: capitalize(lowerCaseKey),
150+
});
151+
}
152+
}
153+
}
154+
}
155+
156+
return configList;
157+
}
158+
99159
/**
100160
* render函数
101161
* @return {Object} JSX对象
102162
*/
103163
render() {
104-
const { min, max, theme, dateFormat, confirmText, cancelText, showFormat, showHeader, customHeader, dateSteps } = this.props;
164+
const { min, max, theme, dateConfig, confirmText, cancelText, headerFormat, showHeader, customHeader, showCaption } = this.props;
105165
const value = this.state.value;
106166
const themeClassName =
107167
['default', 'dark', 'ios', 'android', 'android-dark'].indexOf(theme) === -1 ?
108168
'default' : theme;
109-
169+
170+
const dataConfigList = this.normalizeDateConfig(dateConfig);
171+
110172
return (
111173
<div
112174
className={`datepicker ${themeClassName}`}>
113-
{showHeader &&
114-
<div className="datepicker-header">{customHeader || convertDate(value, showFormat)}</div>}
175+
{showHeader && (
176+
<div className="datepicker-header">
177+
{customHeader || convertDate(value, headerFormat)}
178+
</div>
179+
)}
180+
{showCaption && (
181+
<div className="datepicker-caption">
182+
{dataConfigList.map((item, index) => (
183+
<div key={index} className="datepicker-caption-item">{item.caption}</div>
184+
))}
185+
</div>
186+
)}
115187
<div className="datepicker-content">
116-
{dateFormat.map((format, index) => (
188+
{dataConfigList.map((item, index) => (
117189
<DatePickerItem
118190
key={index}
119-
step={dateSteps[index] || 1}
120191
value={value}
121192
min={min}
122193
max={max}
123-
format={format}
194+
step={item.step}
195+
type={item.type}
196+
format={item.format}
124197
onSelect={this.handleDateSelect} />
125198
))}
126199
</div>

lib/DatePickerItem.js

Lines changed: 7 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -13,35 +13,8 @@ const MIDDLE_INDEX = Math.floor(DATE_LENGTH / 2); // 日期数组中间值
1313
const MIDDLE_Y = - DATE_HEIGHT * MIDDLE_INDEX; // translateY值
1414

1515
const isUndefined = val => typeof val === 'undefined';
16-
const isArray = val => Object.prototype.toString.apply(val) === '[object Array]';
1716
const isFunction = val => Object.prototype.toString.apply(val) === '[object Function]';
1817

19-
/**
20-
* 根据格式获取时间滑动的类别
21-
* @param {String} format 格式
22-
* @return {string} 类别名称
23-
*/
24-
const getTimeType = format => {
25-
const typeMap = {
26-
Y: 'Year',
27-
M: 'Month',
28-
D: 'Date',
29-
h: 'Hour',
30-
m: 'Minute',
31-
s: 'Second',
32-
};
33-
34-
for (const key in typeMap) {
35-
if (typeMap.hasOwnProperty(key)) {
36-
if (~format.indexOf(key)) {
37-
return typeMap[key]
38-
}
39-
}
40-
}
41-
42-
throw new Error('时间格式必须包含 Y, M, D, h, m 或 s字母');
43-
}
44-
4518
type Props = {
4619
value: Object,
4720
min: Object,
@@ -74,20 +47,6 @@ class DatePickerItem extends Component<void, Props, State> {
7447
marginTop: (this.currentIndex - MIDDLE_INDEX) * DATE_HEIGHT,
7548
};
7649

77-
// 设置时间选择器单元的类别
78-
if (isArray(props.format)) {
79-
this.typeName = getTimeType(props.format[0]);
80-
this.format = props.format[0];
81-
if (isFunction(props.format[1])) {
82-
this.formatTransform = props.format[1];
83-
}
84-
}
85-
86-
else {
87-
this.format = props.format;
88-
this.typeName = getTimeType(props.format);
89-
}
90-
9150
this.renderDatepickerItem = this.renderDatepickerItem.bind(this);
9251
this.handleContentTouch = this.handleContentTouch.bind(this);
9352
this.handleContentMouseDown = this.handleContentMouseDown.bind(this);
@@ -141,15 +100,15 @@ class DatePickerItem extends Component<void, Props, State> {
141100
}
142101

143102
_iniDates(date) {
144-
const typeName = this.typeName;
103+
const typeName = this.props.type;
145104
const dates = Array(...Array(DATE_LENGTH))
146105
.map((value, index) =>
147106
TimeUtil[`next${typeName}`](date, (index - MIDDLE_INDEX) * this.props.step));
148107
this.setState({ dates });
149108
}
150109

151110
_updateDates(direction) {
152-
const typeName = this.typeName;
111+
const typeName = this.props.type;
153112
const { dates } = this.state;
154113
if (direction === 1) {
155114
this.currentIndex ++;
@@ -325,9 +284,11 @@ class DatePickerItem extends Component<void, Props, State> {
325284
(date < this.props.min || date > this.props.max) ?
326285
'disabled' : '';
327286

328-
let formatDate = TimeUtil.convertDate(date, this.format);
329-
if (this.formatTransform) {
330-
formatDate = this.formatTransform(formatDate);
287+
let formatDate;
288+
if (isFunction(this.props.format)) {
289+
formatDate = this.props.format(date);
290+
} else {
291+
formatDate = TimeUtil.convertDate(date, this.props.format);
331292
}
332293

333294
return (

lib/dataSource.js

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
2+
/**
3+
* 默认属性
4+
*/
5+
export const defaultProps = {
6+
isPopup: true,
7+
isOpen: false,
8+
theme: 'default',
9+
value: new Date(),
10+
min: new Date(1970, 0, 1),
11+
max: new Date(2050, 0, 1),
12+
showHeader: true,
13+
showCaption: false,
14+
dateConfig: {
15+
'year': {
16+
format: 'YYYY',
17+
caption: 'Year',
18+
step: 1,
19+
},
20+
'month': {
21+
format: 'M',
22+
caption: 'Mon',
23+
step: 1,
24+
},
25+
'date': {
26+
format: 'D',
27+
caption: 'Day',
28+
step: 1,
29+
},
30+
},
31+
headerFormat: 'YYYY/MM/DD',
32+
confirmText: '完成',
33+
cancelText: '取消',
34+
onSelect: () => {},
35+
onCancel: () => {},
36+
};
37+
38+
/**
39+
* 日期配置
40+
*/
41+
export const dateConfigMap = {
42+
'year': {
43+
format: 'YYYY',
44+
caption: 'Year',
45+
step: 1,
46+
},
47+
'month': {
48+
format: 'M',
49+
caption: 'Mon',
50+
step: 1,
51+
},
52+
'date': {
53+
format: 'D',
54+
caption: 'Day',
55+
step: 1,
56+
},
57+
'hour': {
58+
format: 'hh',
59+
caption: 'Hour',
60+
step: 1,
61+
},
62+
'minute': {
63+
format: 'mm',
64+
caption: 'Min',
65+
step: 1,
66+
},
67+
'second': {
68+
format: 'hh',
69+
caption: 'Sec',
70+
step: 1,
71+
},
72+
};
73+
74+
75+

0 commit comments

Comments
 (0)