@wangxinowo/vue-datepicker-next 1.0.2 → 1.0.3

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wangxinowo/vue-datepicker-next",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "A powerful Vue 2.x DatePicker component based on Ant Design Vue",
5
5
  "main": "dist/vue-datepicker-next.min.js",
6
6
  "module": "dist/vue-datepicker-next.min.js",
@@ -0,0 +1,2 @@
1
+ import zh_CN from '../../date-picker/locale/zh_CN';
2
+ export default zh_CN;
@@ -84,3 +84,18 @@
84
84
  cursor: pointer;
85
85
  }
86
86
  }
87
+
88
+ // 范围选择的起始/结束单元格样式
89
+ .@{calendar-prefix-cls}-month-panel-selected-start-cell,
90
+ .@{calendar-prefix-cls}-month-panel-selected-end-cell {
91
+ .@{calendar-prefix-cls}-month-panel-month {
92
+ color: @text-color-inverse;
93
+ background: @primary-color;
94
+ border-radius: @border-radius-sm;
95
+
96
+ &:hover {
97
+ color: @text-color-inverse;
98
+ background: @primary-5;
99
+ }
100
+ }
101
+ }
@@ -1,6 +1,7 @@
1
1
  @input-box-height: 34px;
2
2
 
3
3
  // Range picker input wrapper with Active Bar
4
+ // 统一样式:使用与基础 DatePicker 相同的 input 变量
4
5
  .@{calendar-prefix-cls}-range-picker-input-wrapper {
5
6
  position: relative;
6
7
  display: inline-flex;
@@ -8,8 +9,15 @@
8
9
  width: 100%;
9
10
  min-width: 280px;
10
11
  height: @input-height-base;
11
- padding: 0 @control-padding-horizontal;
12
+ // 使用与 .input() mixin 相同的 padding
13
+ padding: @input-padding-vertical-base @input-padding-horizontal-base;
14
+ // 为图标和清除按钮预留空间
15
+ padding-right: @input-padding-horizontal-base + 30px;
16
+ color: @input-color;
17
+ font-size: @font-size-base;
18
+ line-height: @line-height-base;
12
19
  background-color: @input-bg;
20
+ background-image: none;
13
21
  border: @border-width-base @border-style-base @input-border-color;
14
22
  border-radius: @border-radius-base;
15
23
  transition: all 0.3s;
@@ -31,11 +39,13 @@
31
39
  background-color: transparent;
32
40
  border: none;
33
41
  box-shadow: none;
42
+ padding-right: @input-padding-horizontal-base;
34
43
  }
35
44
 
36
45
  // 禁用状态
37
46
  &[disabled],
38
47
  .@{calendar-prefix-cls}-picker-disabled & {
48
+ color: @disabled-color;
39
49
  background-color: @input-disabled-bg;
40
50
  border-color: @input-border-color;
41
51
  cursor: not-allowed;
@@ -86,11 +96,57 @@
86
96
  border-color: @success-color;
87
97
  box-shadow: @input-outline-offset @outline-blur-size @outline-width fade(@success-color, 20%);
88
98
  }
99
+
100
+ // RangePicker 内的图标样式(与基础 DatePicker 统一)
101
+ .@{calendar-prefix-cls}-picker-icon {
102
+ position: absolute;
103
+ top: 50%;
104
+ right: @input-padding-horizontal-base;
105
+ z-index: 1;
106
+ display: inline-block;
107
+ width: 14px;
108
+ height: 14px;
109
+ margin-top: -7px;
110
+ color: @disabled-color;
111
+ font-size: @font-size-base;
112
+ line-height: 1;
113
+ transition: all 0.3s;
114
+ user-select: none;
115
+ }
116
+
117
+ // RangePicker 内的清除按钮样式(与基础 DatePicker 统一)
118
+ .@{calendar-prefix-cls}-picker-clear {
119
+ position: absolute;
120
+ top: 50%;
121
+ right: @input-padding-horizontal-base;
122
+ z-index: 2;
123
+ width: 14px;
124
+ height: 14px;
125
+ margin-top: -7px;
126
+ color: @disabled-color;
127
+ font-size: @font-size-base;
128
+ background: @input-bg;
129
+ cursor: pointer;
130
+ opacity: 0;
131
+ pointer-events: none;
132
+ transition: all 0.3s;
133
+
134
+ &:hover {
135
+ color: @text-color-secondary;
136
+ }
137
+ }
138
+
139
+ // hover 时显示清除按钮
140
+ &:hover .@{calendar-prefix-cls}-picker-clear {
141
+ opacity: 1;
142
+ pointer-events: auto;
143
+ }
89
144
  }
90
145
 
91
146
  .@{calendar-prefix-cls}-range-picker-input {
92
- width: 44%;
93
- height: 99%;
147
+ flex: 1;
148
+ min-width: 0;
149
+ height: 100%;
94
150
  text-align: center;
95
151
  background-color: transparent;
96
152
  border: 0;
@@ -128,9 +184,10 @@
128
184
  }
129
185
 
130
186
  .@{calendar-prefix-cls}-range-picker-separator {
131
- display: inline-block;
132
- min-width: 10px;
133
- height: 100%;
187
+ flex: none;
188
+ display: inline-flex;
189
+ align-items: center;
190
+ padding: 0 8px;
134
191
  color: @text-color-secondary;
135
192
  white-space: nowrap;
136
193
  text-align: center;
@@ -274,6 +331,49 @@
274
331
  }
275
332
  }
276
333
 
334
+ // 年份面板和月份面板的范围选中背景样式
335
+ .@{calendar-prefix-cls}-year-panel-cell.@{calendar-prefix-cls}-in-range-cell,
336
+ .@{calendar-prefix-cls}-month-panel-cell.@{calendar-prefix-cls}-in-range-cell {
337
+ position: relative;
338
+ border-radius: 0;
339
+
340
+ > a {
341
+ position: relative;
342
+ z-index: 1;
343
+ }
344
+
345
+ &::before {
346
+ position: absolute;
347
+ top: 4px;
348
+ right: 0;
349
+ bottom: 4px;
350
+ left: 0;
351
+ display: block;
352
+ background: @item-active-bg;
353
+ border: 0;
354
+ border-radius: 0;
355
+ content: '';
356
+ }
357
+ }
358
+
359
+ // 年份/月份范围选择的起始单元格圆角
360
+ .@{calendar-prefix-cls}-year-panel-selected-start-cell.@{calendar-prefix-cls}-in-range-cell,
361
+ .@{calendar-prefix-cls}-month-panel-selected-start-cell.@{calendar-prefix-cls}-in-range-cell {
362
+ &::before {
363
+ border-top-left-radius: @border-radius-sm;
364
+ border-bottom-left-radius: @border-radius-sm;
365
+ }
366
+ }
367
+
368
+ // 年份/月份范围选择的结束单元格圆角
369
+ .@{calendar-prefix-cls}-year-panel-selected-end-cell.@{calendar-prefix-cls}-in-range-cell,
370
+ .@{calendar-prefix-cls}-month-panel-selected-end-cell.@{calendar-prefix-cls}-in-range-cell {
371
+ &::before {
372
+ border-top-right-radius: @border-radius-sm;
373
+ border-bottom-right-radius: @border-radius-sm;
374
+ }
375
+ }
376
+
277
377
  // 悬停高亮效果 - 范围起始单元格
278
378
  .@{calendar-prefix-cls}-selected-start-date,
279
379
  .@{calendar-prefix-cls}-selected-end-date {
@@ -91,3 +91,18 @@
91
91
  user-select: none;
92
92
  }
93
93
  }
94
+
95
+ // 范围选择的起始/结束单元格样式
96
+ .@{calendar-prefix-cls}-year-panel-selected-start-cell,
97
+ .@{calendar-prefix-cls}-year-panel-selected-end-cell {
98
+ .@{calendar-prefix-cls}-year-panel-year {
99
+ color: @text-color-inverse;
100
+ background: @primary-color;
101
+ border-radius: @border-radius-sm;
102
+
103
+ &:hover {
104
+ color: @text-color-inverse;
105
+ background: @primary-5;
106
+ }
107
+ }
108
+ }
@@ -2,7 +2,7 @@ import TimePickerPanel from '../vc-time-picker/Panel';
2
2
  import classNames from 'classnames';
3
3
  import LocaleReceiver from '../locale-provider/LocaleReceiver';
4
4
  import { generateShowHourMinuteSecond } from '../time-picker';
5
- import enUS from './locale/en_US';
5
+ import zhCN from './locale/zh_CN';
6
6
  import { getOptionProps, initDefaultProps, getListeners } from '../_util/props-util';
7
7
  import { ConfigConsumerProps } from '../config-provider/configConsumerProps';
8
8
  import { checkValidate, stringToMoment, momentToString } from '../_util/moment-util';
@@ -77,7 +77,7 @@ export default function wrapPicker(Picker, props, pickerType) {
77
77
  methods: {
78
78
  getDefaultLocale() {
79
79
  const result = {
80
- ...enUS,
80
+ ...zhCN,
81
81
  ...this.locale,
82
82
  };
83
83
  result.lang = {
@@ -1,62 +1,63 @@
1
- import Pagination from '../vc-pagination/locale/en_US';
2
- import DatePicker from '../date-picker/locale/en_US';
3
- import TimePicker from '../time-picker/locale/en_US';
4
- import Calendar from '../calendar/locale/en_US';
1
+ import Pagination from '../vc-pagination/locale/zh_CN';
2
+ import DatePicker from '../date-picker/locale/zh_CN';
3
+ import TimePicker from '../time-picker/locale/zh_CN';
4
+ import Calendar from '../calendar/locale/zh_CN';
5
5
 
6
6
  export default {
7
- locale: 'en',
7
+ locale: 'zh-cn',
8
8
  Pagination,
9
9
  DatePicker,
10
10
  TimePicker,
11
11
  Calendar,
12
+ // 所有组件的本地化配置
12
13
  global: {
13
- placeholder: 'Please select',
14
+ placeholder: '请选择',
14
15
  },
15
16
  Table: {
16
- filterTitle: 'Filter menu',
17
- filterConfirm: 'OK',
18
- filterReset: 'Reset',
19
- selectAll: 'Select current page',
20
- selectInvert: 'Invert current page',
21
- sortTitle: 'Sort',
22
- expand: 'Expand row',
23
- collapse: 'Collapse row',
17
+ filterTitle: '筛选',
18
+ filterConfirm: '确定',
19
+ filterReset: '重置',
20
+ selectAll: '全选当页',
21
+ selectInvert: '反选当页',
22
+ sortTitle: '排序',
23
+ expand: '展开行',
24
+ collapse: '关闭行',
24
25
  },
25
26
  Modal: {
26
- okText: 'OK',
27
- cancelText: 'Cancel',
28
- justOkText: 'OK',
27
+ okText: '确定',
28
+ cancelText: '取消',
29
+ justOkText: '知道了',
29
30
  },
30
31
  Popconfirm: {
31
- okText: 'OK',
32
- cancelText: 'Cancel',
32
+ cancelText: '取消',
33
+ okText: '确定',
33
34
  },
34
35
  Transfer: {
35
36
  titles: ['', ''],
36
- searchPlaceholder: 'Search here',
37
- itemUnit: 'item',
38
- itemsUnit: 'items',
37
+ searchPlaceholder: '请输入搜索内容',
38
+ itemUnit: '',
39
+ itemsUnit: '',
39
40
  },
40
41
  Upload: {
41
- uploading: 'Uploading...',
42
- removeFile: 'Remove file',
43
- uploadError: 'Upload error',
44
- previewFile: 'Preview file',
45
- downloadFile: 'Download file',
42
+ uploading: '文件上传中',
43
+ removeFile: '删除文件',
44
+ uploadError: '上传错误',
45
+ previewFile: '预览文件',
46
+ downloadFile: '下载文件',
46
47
  },
47
48
  Empty: {
48
- description: 'No Data',
49
+ description: '暂无数据',
49
50
  },
50
51
  Icon: {
51
- icon: 'icon',
52
+ icon: '图标',
52
53
  },
53
54
  Text: {
54
- edit: 'Edit',
55
- copy: 'Copy',
56
- copied: 'Copied',
57
- expand: 'Expand',
55
+ edit: '编辑',
56
+ copy: '复制',
57
+ copied: '复制成功',
58
+ expand: '展开',
58
59
  },
59
60
  PageHeader: {
60
- back: 'Back',
61
+ back: '返回',
61
62
  },
62
63
  };
@@ -5,7 +5,7 @@ import BaseMixin from '../_util/BaseMixin';
5
5
  import PropTypes from '../_util/vue-types';
6
6
  import warning from '../_util/warning';
7
7
  import Icon from '../icon';
8
- import enUS from './locale/en_US';
8
+ import zhCN from './locale/zh_CN';
9
9
  import {
10
10
  initDefaultProps,
11
11
  hasProp,
@@ -139,7 +139,7 @@ const TimePicker = {
139
139
  },
140
140
  getDefaultLocale() {
141
141
  const defaultLocale = {
142
- ...enUS,
142
+ ...zhCN,
143
143
  ...this.$props.locale,
144
144
  };
145
145
  return defaultLocale;
@@ -10,7 +10,7 @@ import CalendarFooter from './calendar/CalendarFooter';
10
10
  import CalendarMixin, { getNowByCurrentStateValue } from './mixin/CalendarMixin';
11
11
  import CommonMixin from './mixin/CommonMixin';
12
12
  import DateInput from './date/DateInput';
13
- import enUs from './locale/en_US';
13
+ import zhCn from './locale/zh_CN';
14
14
  import { getTimeConfig, getTodayTime, syncTime } from './util';
15
15
  import { goStartMonth, goEndMonth, goTime } from './util/toTime';
16
16
 
@@ -24,7 +24,7 @@ const getMomentObjectIfValid = date => {
24
24
  const Calendar = {
25
25
  name: 'Calendar',
26
26
  props: {
27
- locale: PropTypes.object.def(enUs),
27
+ locale: PropTypes.object.def(zhCn),
28
28
  format: PropTypes.oneOfType([
29
29
  PropTypes.string,
30
30
  PropTypes.arrayOf(PropTypes.string),
@@ -7,11 +7,11 @@ import MonthTable from './month/MonthTable';
7
7
  import CalendarMixin, { getNowByCurrentStateValue } from './mixin/CalendarMixin';
8
8
  import CommonMixin from './mixin/CommonMixin';
9
9
  import CalendarHeader from './full-calendar/CalendarHeader';
10
- import enUs from './locale/en_US';
10
+ import zhCn from './locale/zh_CN';
11
11
  const FullCalendar = {
12
12
  name: 'FullCalendar',
13
13
  props: {
14
- locale: PropTypes.object.def(enUs),
14
+ locale: PropTypes.object.def(zhCn),
15
15
  format: PropTypes.oneOfType([PropTypes.string, PropTypes.array, PropTypes.func]),
16
16
  visible: PropTypes.bool.def(true),
17
17
  prefixCls: PropTypes.string.def('rc-calendar'),
@@ -6,11 +6,11 @@ import CalendarHeader from './calendar/CalendarHeader';
6
6
  import CalendarFooter from './calendar/CalendarFooter';
7
7
  import CalendarMixin from './mixin/CalendarMixin';
8
8
  import CommonMixin from './mixin/CommonMixin';
9
- import enUs from './locale/en_US';
9
+ import zhCn from './locale/zh_CN';
10
10
  const MonthCalendar = {
11
11
  name: 'MonthCalendar',
12
12
  props: {
13
- locale: PropTypes.object.def(enUs),
13
+ locale: PropTypes.object.def(zhCn),
14
14
  format: PropTypes.string,
15
15
  visible: PropTypes.bool.def(true),
16
16
  prefixCls: PropTypes.string.def('rc-calendar'),
@@ -14,7 +14,7 @@ import TodayButton from './calendar/TodayButton';
14
14
  import OkButton from './calendar/OkButton';
15
15
  import TimePickerButton from './calendar/TimePickerButton';
16
16
  import CommonMixin from './mixin/CommonMixin';
17
- import enUs from './locale/en_US';
17
+ import zhCn from './locale/zh_CN';
18
18
  import { syncTime, getTodayTime, isAllowedDate } from './util/';
19
19
  import { goTime, goStartMonth, goEndMonth, includesTime } from './util/toTime';
20
20
 
@@ -87,7 +87,7 @@ function onInputSelect(direction, value, cause) {
87
87
 
88
88
  const RangeCalendar = {
89
89
  props: {
90
- locale: PropTypes.object.def(enUs),
90
+ locale: PropTypes.object.def(zhCn),
91
91
  visible: PropTypes.bool.def(true),
92
92
  prefixCls: PropTypes.string.def('rc-calendar'),
93
93
  dateInputPlaceholder: PropTypes.any,
@@ -35,10 +35,13 @@ const CalendarHeader = {
35
35
  enableNext: PropTypes.any.def(1),
36
36
  disabledMonth: PropTypes.func,
37
37
  mode: PropTypes.any,
38
- selectedValue: PropTypes.object,
38
+ // 支持数组形式,用于范围选择器
39
+ selectedValue: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
39
40
  monthCellRender: PropTypes.func,
40
41
  monthCellContentRender: PropTypes.func,
41
42
  renderFooter: PropTypes.func,
43
+ // 用于范围选择器,标识是左面板还是右面板
44
+ direction: PropTypes.string,
42
45
  },
43
46
  data() {
44
47
  this.nextMonth = goMonth.bind(this, 1);
@@ -15,7 +15,8 @@ const MonthPanel = {
15
15
  props: {
16
16
  value: PropTypes.any,
17
17
  defaultValue: PropTypes.any,
18
- selectedValue: PropTypes.any,
18
+ // 支持单个值或数组(范围选择)
19
+ selectedValue: PropTypes.oneOfType([PropTypes.any, PropTypes.array]),
19
20
  cellRender: PropTypes.any,
20
21
  contentRender: PropTypes.any,
21
22
  locale: PropTypes.any,
@@ -7,6 +7,35 @@ const COL = 3;
7
7
 
8
8
  function noop() {}
9
9
 
10
+ // 判断是否为范围选择模式
11
+ function isRangeMode(selectedValue) {
12
+ return Array.isArray(selectedValue);
13
+ }
14
+
15
+ // 获取范围开始的年月
16
+ function getRangeStart(selectedValue) {
17
+ if (!isRangeMode(selectedValue) || !selectedValue[0]) return null;
18
+ return {
19
+ year: selectedValue[0].year(),
20
+ month: selectedValue[0].month(),
21
+ };
22
+ }
23
+
24
+ // 获取范围结束的年月
25
+ function getRangeEnd(selectedValue) {
26
+ if (!isRangeMode(selectedValue) || !selectedValue[1]) return null;
27
+ return {
28
+ year: selectedValue[1].year(),
29
+ month: selectedValue[1].month(),
30
+ };
31
+ }
32
+
33
+ // 比较两个年月
34
+ function compareYearMonth(year1, month1, year2, month2) {
35
+ if (year1 !== year2) return year1 - year2;
36
+ return month1 - month2;
37
+ }
38
+
10
39
  const MonthTable = {
11
40
  name: 'MonthTable',
12
41
  mixins: [BaseMixin],
@@ -14,7 +43,8 @@ const MonthTable = {
14
43
  cellRender: PropTypes.func,
15
44
  prefixCls: PropTypes.string,
16
45
  value: PropTypes.object,
17
- selectedValue: PropTypes.object,
46
+ // 支持单个值或数组(范围选择)
47
+ selectedValue: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
18
48
  locale: PropTypes.any,
19
49
  contentRender: PropTypes.any,
20
50
  disabledDate: PropTypes.func,
@@ -73,10 +103,19 @@ const MonthTable = {
73
103
  const months = this.months();
74
104
  const { prefixCls, locale, contentRender, cellRender, disabledDate } = props;
75
105
 
76
- // 只有当 selectedValue 存在且与当前面板年份相同时,才显示选中状态
77
- const hasSelectedValue = selectedValue && selectedValue.year() === value.year();
106
+ // 判断是范围模式还是单值模式
107
+ const rangeMode = isRangeMode(selectedValue);
108
+ const rangeStart = getRangeStart(selectedValue);
109
+ const rangeEnd = getRangeEnd(selectedValue);
110
+
111
+ // 单值模式:只有当 selectedValue 存在且与当前面板年份相同时,才显示选中状态
112
+ const hasSelectedValue = !rangeMode && selectedValue && selectedValue.year() === value.year();
78
113
  const selectedMonth = hasSelectedValue ? selectedValue.month() : -1;
79
114
 
115
+ // 获取根前缀类(用于 in-range-cell 类名)
116
+ const rootPrefixCls = prefixCls.replace('-month-panel', '');
117
+ const currentYear = value.year();
118
+
80
119
  const monthsEls = months.map((month, index) => {
81
120
  const tds = month.map(monthData => {
82
121
  let disabled = false;
@@ -85,10 +124,47 @@ const MonthTable = {
85
124
  testValue.month(monthData.value);
86
125
  disabled = disabledDate(testValue);
87
126
  }
127
+
128
+ // 判断当前月份是否在范围内
129
+ let isRangeStart = false;
130
+ let isRangeEnd = false;
131
+ let isInRange = false;
132
+
133
+ if (rangeMode && rangeStart && rangeEnd) {
134
+ // 当前月份的年月
135
+ const currentYearMonth = { year: currentYear, month: monthData.value };
136
+
137
+ // 判断是否为范围开始
138
+ isRangeStart = rangeStart.year === currentYear && rangeStart.month === monthData.value;
139
+
140
+ // 判断是否为范围结束
141
+ isRangeEnd = rangeEnd.year === currentYear && rangeEnd.month === monthData.value;
142
+
143
+ // 判断是否在范围中间
144
+ const compareWithStart = compareYearMonth(
145
+ currentYear,
146
+ monthData.value,
147
+ rangeStart.year,
148
+ rangeStart.month
149
+ );
150
+ const compareWithEnd = compareYearMonth(
151
+ currentYear,
152
+ monthData.value,
153
+ rangeEnd.year,
154
+ rangeEnd.month
155
+ );
156
+ isInRange = compareWithStart > 0 && compareWithEnd < 0;
157
+ }
158
+
88
159
  const classNameMap = {
89
160
  [`${prefixCls}-cell`]: 1,
90
161
  [`${prefixCls}-cell-disabled`]: disabled,
162
+ // 单值模式的选中状态
91
163
  [`${prefixCls}-selected-cell`]: monthData.value === selectedMonth,
164
+ // 范围模式的选中状态
165
+ [`${prefixCls}-selected-start-cell`]: isRangeStart,
166
+ [`${prefixCls}-selected-end-cell`]: isRangeEnd,
167
+ [`${rootPrefixCls}-in-range-cell`]: isInRange || isRangeStart || isRangeEnd,
92
168
  [`${prefixCls}-current-cell`]:
93
169
  today.year() === value.year() && monthData.value === today.month(),
94
170
  };
@@ -128,7 +128,10 @@ const CalendarPart = {
128
128
  enableNext,
129
129
  enablePrev,
130
130
  disabledMonth,
131
- selectedValue: selectedValue[index],
131
+ // 传递完整的 selectedValue 数组,让 YearPanel/MonthPanel 支持范围选中效果
132
+ selectedValue: selectedValue,
133
+ // 保留 direction 信息,用于判断是左面板还是右面板
134
+ direction,
132
135
  },
133
136
  on: {
134
137
  valueChange,
@@ -22,13 +22,31 @@ function chooseYear(year) {
22
22
  this.__emit('select', value);
23
23
  }
24
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
+
25
42
  export default {
26
43
  mixins: [BaseMixin],
27
44
  props: {
28
45
  rootPrefixCls: PropTypes.string,
29
46
  value: PropTypes.object,
30
47
  defaultValue: PropTypes.object,
31
- selectedValue: PropTypes.object,
48
+ // 支持单个值或数组(范围选择)
49
+ selectedValue: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
32
50
  locale: PropTypes.object,
33
51
  renderFooter: PropTypes.func,
34
52
  disabledDate: PropTypes.func,
@@ -76,8 +94,15 @@ export default {
76
94
  const decadePanelShow = getListeners(this).decadePanelShow || noop;
77
95
  const years = this.years();
78
96
  const currentYear = value.year();
79
- // 只有当 selectedValue 存在时才显示选中状态
80
- const selectedYear = selectedValue ? selectedValue.year() : null;
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
+
81
106
  const startYear = parseInt(currentYear / 10, 10) * 10;
82
107
  const endYear = startYear + 9;
83
108
  const prefixCls = `${this.rootPrefixCls}-year-panel`;
@@ -91,10 +116,29 @@ export default {
91
116
  testValue.year(yearData.year);
92
117
  disabled = disabledDate(testValue);
93
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
+
94
133
  const classNameMap = {
95
134
  [`${prefixCls}-cell`]: 1,
96
135
  [`${prefixCls}-cell-disabled`]: disabled,
136
+ // 单值模式的选中状态
97
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,
98
142
  [`${prefixCls}-last-decade-cell`]: yearData.year < startYear,
99
143
  [`${prefixCls}-next-decade-cell`]: yearData.year > endYear,
100
144
  };
@@ -0,0 +1,15 @@
1
+ export default {
2
+ // Options.jsx
3
+ items_per_page: '条/页',
4
+ jump_to: '跳至',
5
+ jump_to_confirm: '确定',
6
+ page: '页',
7
+
8
+ // Pagination.jsx
9
+ prev_page: '上一页',
10
+ next_page: '下一页',
11
+ prev_5: '向前 5 页',
12
+ next_5: '向后 5 页',
13
+ prev_3: '向前 3 页',
14
+ next_3: '向后 3 页',
15
+ };