@wangxinowo/vue-datepicker-next 1.0.3 → 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,211 +1,242 @@
1
- import PropTypes from '../../../_util/vue-types';
2
- import BaseMixin from '../../../_util/BaseMixin';
3
- import { getListeners } from '../../../_util/props-util';
4
- const ROW = 4;
5
- const COL = 3;
6
- function noop() {}
7
- function goYear(direction) {
8
- const value = this.sValue.clone();
9
- value.add(direction, 'year');
10
- this.setState({
11
- sValue: value,
12
- });
13
- // 发出 valueChange 事件,让父组件可以联动处理
14
- this.__emit('valueChange', value);
15
- }
16
-
17
- function chooseYear(year) {
18
- const value = this.sValue.clone();
19
- value.year(year);
20
- value.month(this.sValue.month());
21
- this.sValue = value;
22
- this.__emit('select', value);
23
- }
24
-
25
- // 判断是否为范围选择模式
26
- function isRangeMode(selectedValue) {
27
- return Array.isArray(selectedValue);
28
- }
29
-
30
- // 获取范围开始年份
31
- function getRangeStartYear(selectedValue) {
32
- if (!isRangeMode(selectedValue)) return null;
33
- return selectedValue[0] ? selectedValue[0].year() : null;
34
- }
35
-
36
- // 获取范围结束年份
37
- function getRangeEndYear(selectedValue) {
38
- if (!isRangeMode(selectedValue)) return null;
39
- return selectedValue[1] ? selectedValue[1].year() : null;
40
- }
41
-
42
- export default {
43
- mixins: [BaseMixin],
44
- props: {
45
- rootPrefixCls: PropTypes.string,
46
- value: PropTypes.object,
47
- defaultValue: PropTypes.object,
48
- // 支持单个值或数组(范围选择)
49
- selectedValue: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
50
- locale: PropTypes.object,
51
- renderFooter: PropTypes.func,
52
- disabledDate: PropTypes.func,
53
- },
54
- data() {
55
- this.nextDecade = goYear.bind(this, 10);
56
- this.previousDecade = goYear.bind(this, -10);
57
- return {
58
- sValue: this.value || this.defaultValue,
59
- };
60
- },
61
- watch: {
62
- value(val) {
63
- this.sValue = val;
64
- },
65
- },
66
- methods: {
67
- years() {
68
- const value = this.sValue;
69
- const currentYear = value.year();
70
- const startYear = parseInt(currentYear / 10, 10) * 10;
71
- const previousYear = startYear - 1;
72
- const years = [];
73
- let index = 0;
74
- for (let rowIndex = 0; rowIndex < ROW; rowIndex++) {
75
- years[rowIndex] = [];
76
- for (let colIndex = 0; colIndex < COL; colIndex++) {
77
- const year = previousYear + index;
78
- const content = String(year);
79
- years[rowIndex][colIndex] = {
80
- content,
81
- year,
82
- title: content,
83
- };
84
- index++;
85
- }
86
- }
87
- return years;
88
- },
89
- },
90
-
91
- render() {
92
- const { sValue: value, locale, renderFooter, $props } = this;
93
- const { selectedValue } = $props;
94
- const decadePanelShow = getListeners(this).decadePanelShow || noop;
95
- const years = this.years();
96
- const currentYear = value.year();
97
-
98
- // 判断是范围模式还是单值模式
99
- const rangeMode = isRangeMode(selectedValue);
100
- const rangeStartYear = getRangeStartYear(selectedValue);
101
- const rangeEndYear = getRangeEndYear(selectedValue);
102
-
103
- // 单值模式:只有当 selectedValue 存在时才显示选中状态
104
- const selectedYear = !rangeMode && selectedValue ? selectedValue.year() : null;
105
-
106
- const startYear = parseInt(currentYear / 10, 10) * 10;
107
- const endYear = startYear + 9;
108
- const prefixCls = `${this.rootPrefixCls}-year-panel`;
109
- const { disabledDate } = $props;
110
-
111
- const yeasEls = years.map((row, index) => {
112
- const tds = row.map(yearData => {
113
- let disabled = false;
114
- if (disabledDate) {
115
- const testValue = value.clone();
116
- testValue.year(yearData.year);
117
- disabled = disabledDate(testValue);
118
- }
119
-
120
- // 判断年份是否在当前十年范围内(不是上一十年或下一十年的预览)
121
- const isInCurrentDecade = yearData.year >= startYear && yearData.year <= endYear;
122
-
123
- // 判断是否为范围起始/结束/中间,只在当前十年范围内应用
124
- const isRangeStart = rangeMode && rangeStartYear !== null && yearData.year === rangeStartYear && isInCurrentDecade;
125
- const isRangeEnd = rangeMode && rangeEndYear !== null && yearData.year === rangeEndYear && isInCurrentDecade;
126
- const isInRange = rangeMode &&
127
- rangeStartYear !== null &&
128
- rangeEndYear !== null &&
129
- yearData.year > rangeStartYear &&
130
- yearData.year < rangeEndYear &&
131
- isInCurrentDecade;
132
-
133
- const classNameMap = {
134
- [`${prefixCls}-cell`]: 1,
135
- [`${prefixCls}-cell-disabled`]: disabled,
136
- // 单值模式的选中状态
137
- [`${prefixCls}-selected-cell`]: selectedYear !== null && yearData.year === selectedYear,
138
- // 范围模式的选中状态
139
- [`${prefixCls}-selected-start-cell`]: isRangeStart,
140
- [`${prefixCls}-selected-end-cell`]: isRangeEnd,
141
- [`${this.rootPrefixCls}-in-range-cell`]: isInRange || isRangeStart || isRangeEnd,
142
- [`${prefixCls}-last-decade-cell`]: yearData.year < startYear,
143
- [`${prefixCls}-next-decade-cell`]: yearData.year > endYear,
144
- };
145
- let clickHandler = noop;
146
- if (yearData.year < startYear) {
147
- clickHandler = this.previousDecade;
148
- } else if (yearData.year > endYear) {
149
- clickHandler = this.nextDecade;
150
- } else {
151
- clickHandler = chooseYear.bind(this, yearData.year);
152
- }
153
- return (
154
- <td
155
- role="gridcell"
156
- title={yearData.title}
157
- key={yearData.content}
158
- onClick={disabled ? noop : clickHandler}
159
- class={classNameMap}
160
- >
161
- <a class={`${prefixCls}-year`}>{yearData.content}</a>
162
- </td>
163
- );
164
- });
165
- return (
166
- <tr key={index} role="row">
167
- {tds}
168
- </tr>
169
- );
170
- });
171
- const footer = renderFooter && renderFooter('year');
172
- return (
173
- <div class={prefixCls}>
174
- <div>
175
- <div class={`${prefixCls}-header`}>
176
- <a
177
- class={`${prefixCls}-prev-decade-btn`}
178
- role="button"
179
- onClick={this.previousDecade}
180
- title={locale.previousDecade}
181
- />
182
- <a
183
- class={`${prefixCls}-decade-select`}
184
- role="button"
185
- onClick={decadePanelShow}
186
- title={locale.decadeSelect}
187
- >
188
- <span class={`${prefixCls}-decade-select-content`}>
189
- {startYear}-{endYear}
190
- </span>
191
- <span class={`${prefixCls}-decade-select-arrow`}>x</span>
192
- </a>
193
-
194
- <a
195
- class={`${prefixCls}-next-decade-btn`}
196
- role="button"
197
- onClick={this.nextDecade}
198
- title={locale.nextDecade}
199
- />
200
- </div>
201
- <div class={`${prefixCls}-body`}>
202
- <table class={`${prefixCls}-table`} cellSpacing="0" role="grid">
203
- <tbody class={`${prefixCls}-tbody`}>{yeasEls}</tbody>
204
- </table>
205
- </div>
206
- {footer && <div class={`${prefixCls}-footer`}>{footer}</div>}
207
- </div>
208
- </div>
209
- );
210
- },
211
- };
1
+ import PropTypes from '../../../_util/vue-types';
2
+ import BaseMixin from '../../../_util/BaseMixin';
3
+ import { getListeners } from '../../../_util/props-util';
4
+ const ROW = 4;
5
+ const COL = 3;
6
+ function noop() {}
7
+ function goYear(direction) {
8
+ const value = this.sValue.clone();
9
+ value.add(direction, 'year');
10
+ this.setState({
11
+ sValue: value,
12
+ });
13
+ // 发出 valueChange 事件,让父组件可以联动处理
14
+ this.__emit('valueChange', value);
15
+ }
16
+
17
+ function chooseYear(year) {
18
+ const value = this.sValue.clone();
19
+ value.year(year);
20
+ value.month(this.sValue.month());
21
+ this.sValue = value;
22
+ this.__emit('select', value);
23
+ }
24
+
25
+ // 判断是否为范围选择模式
26
+ function isRangeMode(selectedValue) {
27
+ return Array.isArray(selectedValue);
28
+ }
29
+
30
+ // 获取范围开始年份
31
+ function getRangeStartYear(value) {
32
+ if (!isRangeMode(value)) return null;
33
+ return value[0] ? value[0].year() : null;
34
+ }
35
+
36
+ // 获取范围结束年份
37
+ function getRangeEndYear(value) {
38
+ if (!isRangeMode(value)) return null;
39
+ return value[1] ? value[1].year() : null;
40
+ }
41
+
42
+ export default {
43
+ mixins: [BaseMixin],
44
+ props: {
45
+ rootPrefixCls: PropTypes.string,
46
+ value: PropTypes.object,
47
+ defaultValue: PropTypes.object,
48
+ // 支持单个值或数组(范围选择)
49
+ selectedValue: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
50
+ // hover 值,用于范围选择时的预览效果
51
+ hoverValue: PropTypes.array.def([]),
52
+ locale: PropTypes.object,
53
+ renderFooter: PropTypes.func,
54
+ disabledDate: PropTypes.func,
55
+ },
56
+ data() {
57
+ this.nextDecade = goYear.bind(this, 10);
58
+ this.previousDecade = goYear.bind(this, -10);
59
+ return {
60
+ sValue: this.value || this.defaultValue,
61
+ };
62
+ },
63
+ watch: {
64
+ value(val) {
65
+ this.sValue = val;
66
+ },
67
+ },
68
+ methods: {
69
+ years() {
70
+ const value = this.sValue;
71
+ const currentYear = value.year();
72
+ const startYear = parseInt(currentYear / 10, 10) * 10;
73
+ const previousYear = startYear - 1;
74
+ const years = [];
75
+ let index = 0;
76
+ for (let rowIndex = 0; rowIndex < ROW; rowIndex++) {
77
+ years[rowIndex] = [];
78
+ for (let colIndex = 0; colIndex < COL; colIndex++) {
79
+ const year = previousYear + index;
80
+ const content = String(year);
81
+ years[rowIndex][colIndex] = {
82
+ content,
83
+ year,
84
+ title: content,
85
+ };
86
+ index++;
87
+ }
88
+ }
89
+ return years;
90
+ },
91
+ },
92
+
93
+ render() {
94
+ const { sValue: value, locale, renderFooter, $props } = this;
95
+ const { selectedValue, hoverValue } = $props;
96
+ const decadePanelShow = getListeners(this).decadePanelShow || noop;
97
+ const yearHover = getListeners(this).yearHover || noop;
98
+ const years = this.years();
99
+ const currentYear = value.year();
100
+
101
+ // 判断是范围模式还是单值模式
102
+ const rangeMode = isRangeMode(selectedValue);
103
+
104
+ // 使用 hoverValue 进行范围预览(如果存在的话)
105
+ const rangeValue = hoverValue && hoverValue.length ? hoverValue : selectedValue;
106
+ const rangeStartYear = getRangeStartYear(rangeValue);
107
+ const rangeEndYear = getRangeEndYear(rangeValue);
108
+
109
+ // 选中值(用于显示实际选中的起始和结束)
110
+ const selectedStartYear = getRangeStartYear(selectedValue);
111
+ const selectedEndYear = getRangeEndYear(selectedValue);
112
+
113
+ // 单值模式:只有当 selectedValue 存在时才显示选中状态
114
+ const selectedYear = !rangeMode && selectedValue ? selectedValue.year() : null;
115
+
116
+ const startYear = parseInt(currentYear / 10, 10) * 10;
117
+ const endYear = startYear + 9;
118
+ const prefixCls = `${this.rootPrefixCls}-year-panel`;
119
+ const { disabledDate } = $props;
120
+
121
+ const yeasEls = years.map((row, index) => {
122
+ const tds = row.map(yearData => {
123
+ let disabled = false;
124
+ if (disabledDate) {
125
+ const testValue = value.clone();
126
+ testValue.year(yearData.year);
127
+ disabled = disabledDate(testValue);
128
+ }
129
+
130
+ // 判断年份是否在当前十年范围内(不是上一十年或下一十年的预览)
131
+ const isInCurrentDecade = yearData.year >= startYear && yearData.year <= endYear;
132
+
133
+ // 判断是否为选中的起始/结束(使用实际选中值,而非 hover 值)
134
+ const isSelectedStart = rangeMode && selectedStartYear !== null && yearData.year === selectedStartYear && isInCurrentDecade;
135
+ const isSelectedEnd = rangeMode && selectedEndYear !== null && yearData.year === selectedEndYear && isInCurrentDecade;
136
+
137
+ // 判断是否为范围起始/结束/中间(使用 rangeValue,可能是 hover 值)
138
+ const isRangeStart = rangeMode && rangeStartYear !== null && yearData.year === rangeStartYear && isInCurrentDecade;
139
+ const isRangeEnd = rangeMode && rangeEndYear !== null && yearData.year === rangeEndYear && isInCurrentDecade;
140
+ const isInRange = rangeMode &&
141
+ rangeStartYear !== null &&
142
+ rangeEndYear !== null &&
143
+ yearData.year > rangeStartYear &&
144
+ yearData.year < rangeEndYear &&
145
+ isInCurrentDecade;
146
+
147
+ // 判断是否为 hover 预览状态(有 hoverValue 时)
148
+ const isHoverRange = hoverValue && hoverValue.length > 0;
149
+
150
+ const classNameMap = {
151
+ [`${prefixCls}-cell`]: 1,
152
+ [`${prefixCls}-cell-disabled`]: disabled,
153
+ // 单值模式的选中状态
154
+ [`${prefixCls}-selected-cell`]: selectedYear !== null && yearData.year === selectedYear,
155
+ // 范围模式的选中状态(实际选中)
156
+ [`${prefixCls}-selected-start-cell`]: isSelectedStart,
157
+ [`${prefixCls}-selected-end-cell`]: isSelectedEnd,
158
+ // 范围背景(包括 hover 预览)
159
+ [`${this.rootPrefixCls}-in-range-cell`]: isInRange || isRangeStart || isRangeEnd,
160
+ // hover 预览状态(仅当有 hoverValue 时才添加 hover 样式类)
161
+ [`${this.rootPrefixCls}-in-hover-range-cell`]: isHoverRange && (isInRange || isRangeStart || isRangeEnd),
162
+ [`${prefixCls}-last-decade-cell`]: yearData.year < startYear,
163
+ [`${prefixCls}-next-decade-cell`]: yearData.year > endYear,
164
+ };
165
+ let clickHandler = noop;
166
+ if (yearData.year < startYear) {
167
+ clickHandler = this.previousDecade;
168
+ } else if (yearData.year > endYear) {
169
+ clickHandler = this.nextDecade;
170
+ } else {
171
+ clickHandler = chooseYear.bind(this, yearData.year);
172
+ }
173
+
174
+ // hover 处理函数
175
+ const hoverHandler = () => {
176
+ if (disabled || yearData.year < startYear || yearData.year > endYear) {
177
+ return;
178
+ }
179
+ const hoverTime = value.clone().year(yearData.year);
180
+ yearHover(hoverTime);
181
+ };
182
+
183
+ return (
184
+ <td
185
+ role="gridcell"
186
+ title={yearData.title}
187
+ key={yearData.content}
188
+ onClick={disabled ? noop : clickHandler}
189
+ onMouseenter={hoverHandler}
190
+ class={classNameMap}
191
+ >
192
+ <a class={`${prefixCls}-year`}>{yearData.content}</a>
193
+ </td>
194
+ );
195
+ });
196
+ return (
197
+ <tr key={index} role="row">
198
+ {tds}
199
+ </tr>
200
+ );
201
+ });
202
+ const footer = renderFooter && renderFooter('year');
203
+ return (
204
+ <div class={prefixCls}>
205
+ <div>
206
+ <div class={`${prefixCls}-header`}>
207
+ <a
208
+ class={`${prefixCls}-prev-decade-btn`}
209
+ role="button"
210
+ onClick={this.previousDecade}
211
+ title={locale.previousDecade}
212
+ />
213
+ <a
214
+ class={`${prefixCls}-decade-select`}
215
+ role="button"
216
+ onClick={decadePanelShow}
217
+ title={locale.decadeSelect}
218
+ >
219
+ <span class={`${prefixCls}-decade-select-content`}>
220
+ {startYear}-{endYear}
221
+ </span>
222
+ <span class={`${prefixCls}-decade-select-arrow`}>x</span>
223
+ </a>
224
+
225
+ <a
226
+ class={`${prefixCls}-next-decade-btn`}
227
+ role="button"
228
+ onClick={this.nextDecade}
229
+ title={locale.nextDecade}
230
+ />
231
+ </div>
232
+ <div class={`${prefixCls}-body`}>
233
+ <table class={`${prefixCls}-table`} cellSpacing="0" role="grid">
234
+ <tbody class={`${prefixCls}-tbody`}>{yeasEls}</tbody>
235
+ </table>
236
+ </div>
237
+ {footer && <div class={`${prefixCls}-footer`}>{footer}</div>}
238
+ </div>
239
+ </div>
240
+ );
241
+ },
242
+ };
package/src/index.js CHANGED
@@ -1,44 +1,48 @@
1
- /**
2
- * Vue DatePicker Next
3
- * A powerful Vue 2.x DatePicker component based on Ant Design Vue
4
- */
5
-
6
- import DatePicker from './components/date-picker';
7
- import './components/style/index.less';
8
- import './components/date-picker/style/index.less';
9
-
10
- const { RangePicker, MonthPicker, WeekPicker } = DatePicker;
11
-
12
- // 导出日期库适配器
13
- export { setGenerateConfig, getGenerateConfig } from './components/date-picker/generate';
14
- export { default as momentGenerateConfig } from './components/date-picker/generate/moment';
15
- export { default as dayjsGenerateConfig } from './components/date-picker/generate/dayjs';
16
-
17
- // 安装函数
18
- const install = function(Vue) {
19
- Vue.component(DatePicker.name, DatePicker);
20
- Vue.component('a-date-picker', DatePicker);
21
- Vue.component('a-range-picker', RangePicker);
22
- Vue.component('a-month-picker', MonthPicker);
23
- Vue.component('a-week-picker', WeekPicker);
24
- };
25
-
26
- // 自动安装(如果是在浏览器环境)
27
- if (typeof window !== 'undefined' && window.Vue) {
28
- install(window.Vue);
29
- }
30
-
31
- export {
32
- DatePicker,
33
- RangePicker,
34
- MonthPicker,
35
- WeekPicker,
36
- };
37
-
38
- export default {
39
- install,
40
- DatePicker,
41
- RangePicker,
42
- MonthPicker,
43
- WeekPicker,
44
- };
1
+ /**
2
+ * Vue DatePicker Next
3
+ * A powerful Vue 2.x DatePicker component based on Ant Design Vue
4
+ */
5
+
6
+ import DatePicker from './components/date-picker';
7
+ import antDirective from './components/_util/antDirective';
8
+ import './components/style/index.less';
9
+ import './components/date-picker/style/index.less';
10
+
11
+ const { RangePicker, MonthPicker, WeekPicker } = DatePicker;
12
+
13
+ // 导出日期库适配器
14
+ export { setGenerateConfig, getGenerateConfig } from './components/date-picker/generate';
15
+ export { default as momentGenerateConfig } from './components/date-picker/generate/moment';
16
+ export { default as dayjsGenerateConfig } from './components/date-picker/generate/dayjs';
17
+
18
+ // 安装函数
19
+ const install = function(Vue) {
20
+ // 注册所有指令 (ant-ref, ant-input, ant-decorator, ant-portal)
21
+ Vue.use(antDirective);
22
+
23
+ Vue.component(DatePicker.name, DatePicker);
24
+ Vue.component('a-date-picker', DatePicker);
25
+ Vue.component('a-range-picker', RangePicker);
26
+ Vue.component('a-month-picker', MonthPicker);
27
+ Vue.component('a-week-picker', WeekPicker);
28
+ };
29
+
30
+ // 自动安装(如果是在浏览器环境)
31
+ if (typeof window !== 'undefined' && window.Vue) {
32
+ install(window.Vue);
33
+ }
34
+
35
+ export {
36
+ DatePicker,
37
+ RangePicker,
38
+ MonthPicker,
39
+ WeekPicker,
40
+ };
41
+
42
+ export default {
43
+ install,
44
+ DatePicker,
45
+ RangePicker,
46
+ MonthPicker,
47
+ WeekPicker,
48
+ };