diff --git a/src/components/date-picker/base/date-table.vue b/src/components/date-picker/base/date-table.vue
index 07beb3e..ee83b6b 100644
--- a/src/components/date-picker/base/date-table.vue
+++ b/src/components/date-picker/base/date-table.vue
@@ -6,7 +6,7 @@
日一二三四五六
- {{ cell.text }}
+ {{ cell.text }}
\ No newline at end of file
diff --git a/src/components/date-picker/base/year-table.vue b/src/components/date-picker/base/year-table.vue
index 3e04a67..47b551e 100644
--- a/src/components/date-picker/base/year-table.vue
+++ b/src/components/date-picker/base/year-table.vue
@@ -1,13 +1,75 @@
- year
+
+ {{ cell.text }}
+
\ No newline at end of file
diff --git a/src/components/date-picker/panel/date.vue b/src/components/date-picker/panel/date.vue
index fd971d2..e1c5bd2 100644
--- a/src/components/date-picker/panel/date.vue
+++ b/src/components/date-picker/panel/date.vue
@@ -10,25 +10,25 @@
+ @click="prevYear">
+ v-show="currentView === 'date'">
{{ }}
+ @click="showYearPicker">{{ yearLabel }}
{{ }}
+ v-show="currentView === 'date'">{{ month + 1 + '月' }}
+
-
+ v-show="currentView === 'date'">
+ :disabled-date="disabledDate"
+ @on-pick="handleDatePick">
+ v-ref:year-table
+ v-show="currentView === 'year'"
+ :year="year"
+ :date="date"
+ :disabled-date="disabledDate"
+ @on-pick="handleYearPick">
+ v-ref:month-table
+ v-show="currentView === 'month'"
+ :month="month"
+ :date="date"
+ :disabled-date="disabledDate"
+ @on-pick="handleMonthPick">
\ No newline at end of file
diff --git a/src/components/date-picker/picker.vue b/src/components/date-picker/picker.vue
index 34f39e7..dc3dfb9 100644
--- a/src/components/date-picker/picker.vue
+++ b/src/components/date-picker/picker.vue
@@ -1,9 +1,7 @@
+ v-clickoutside="handleClose">
@@ -27,13 +28,14 @@
import Drop from '../../components/select/dropdown.vue';
import clickoutside from '../../directives/clickoutside';
import { oneOf } from '../../utils/assist';
- import { formatDate } from './util';
+ import { formatDate, parseDate } from './util';
const prefixCls = 'ivu-date-picker';
const DEFAULT_FORMATS = {
date: 'yyyy-MM-dd',
month: 'yyyy-MM',
+ year: 'yyyy',
datetime: 'yyyy-MM-dd HH:mm:ss',
time: 'HH:mm:ss',
timerange: 'HH:mm:ss',
@@ -41,6 +43,96 @@
datetimerange: 'yyyy-MM-dd HH:mm:ss'
};
+ const RANGE_SEPARATOR = ' - ';
+
+ const DATE_FORMATTER = function(value, format) {
+ return formatDate(value, format);
+ };
+ const DATE_PARSER = function(text, format) {
+ return parseDate(text, format);
+ };
+ const RANGE_FORMATTER = function(value, format) {
+ if (Array.isArray(value) && value.length === 2) {
+ const start = value[0];
+ const end = value[1];
+
+ if (start && end) {
+ return formatDate(start, format) + RANGE_SEPARATOR + formatDate(end, format);
+ }
+ }
+ return '';
+ };
+ const RANGE_PARSER = function(text, format) {
+ const array = text.split(RANGE_SEPARATOR);
+ if (array.length === 2) {
+ const range1 = array[0];
+ const range2 = array[1];
+
+ return [parseDate(range1, format), parseDate(range2, format)];
+ }
+ return [];
+ };
+
+ const TYPE_VALUE_RESOLVER_MAP = {
+ default: {
+ formatter(value) {
+ if (!value) return '';
+ return '' + value;
+ },
+ parser(text) {
+ if (text === undefined || text === '') return null;
+ return text;
+ }
+ },
+ date: {
+ formatter: DATE_FORMATTER,
+ parser: DATE_PARSER
+ },
+ datetime: {
+ formatter: DATE_FORMATTER,
+ parser: DATE_PARSER
+ },
+ daterange: {
+ formatter: RANGE_FORMATTER,
+ parser: RANGE_PARSER
+ },
+ datetimerange: {
+ formatter: RANGE_FORMATTER,
+ parser: RANGE_PARSER
+ },
+ timerange: {
+ formatter: RANGE_FORMATTER,
+ parser: RANGE_PARSER
+ },
+ time: {
+ formatter: DATE_FORMATTER,
+ parser: DATE_PARSER
+ },
+ month: {
+ formatter: DATE_FORMATTER,
+ parser: DATE_PARSER
+ },
+ year: {
+ formatter: DATE_FORMATTER,
+ parser: DATE_PARSER
+ },
+ number: {
+ formatter(value) {
+ if (!value) return '';
+ return '' + value;
+ },
+ parser(text) {
+ let result = Number(text);
+
+ if (!isNaN(text)) {
+ return result;
+ } else {
+ return null;
+ }
+ }
+ }
+ };
+
const PLACEMENT_MAP = {
left: 'bottom-start',
center: 'bottom-center',
@@ -101,6 +193,47 @@
},
placement () {
return PLACEMENT_MAP[this.align];
+ },
+ selectionMode() {
+ if (this.type === 'week') {
+ return 'week';
+ } else if (this.type === 'month') {
+ return 'month';
+ } else if (this.type === 'year') {
+ return 'year';
+ }
+
+ return 'day';
+ },
+ visualValue: {
+ get () {
+ const value = this.internalValue;
+ if (!value) return;
+ const formatter = (
+ TYPE_VALUE_RESOLVER_MAP[this.type] ||
+ TYPE_VALUE_RESOLVER_MAP['default']
+ ).formatter;
+ const format = DEFAULT_FORMATS[this.type];
+
+ return formatter(value, this.format || format);
+ },
+
+ set (value) {
+ if (value) {
+ const type = this.type;
+ const parser = (
+ TYPE_VALUE_RESOLVER_MAP[type] ||
+ TYPE_VALUE_RESOLVER_MAP['default']
+ ).parser;
+ const parsedValue = parser(value, this.format || DEFAULT_FORMATS[type]);
+
+ if (parsedValue) {
+ if (this.picker) this.picker.value = parsedValue;
+ }
+ return;
+ }
+ if (this.picker) this.picker.value = value;
+ }
}
},
methods: {
@@ -113,29 +246,51 @@
handleBlur () {
},
- handleMouseenter () {
+ handleInputChange (val) {
+ this.visualValue = val;
+ },
+ handleInputMouseenter () {
if (this.readonly || this.disabled) return;
if (this.visualValue) {
this.showClose = true;
}
},
- handleMouseleave () {
+ handleInputMouseleave () {
this.showClose = false;
},
handleIconClick () {
-
+ if (!this.showClose) return;
+ this.visible = false;
+ this.internalValue = '';
+ this.value = '';
},
showPicker () {
if (!this.picker) {
this.picker = new Vue(this.panel).$mount(this.$els.picker);
this.picker.value = this.internalValue;
+ this.picker.selectionMode = this.selectionMode;
if (this.format) this.picker.format = this.format;
const options = this.options;
for (const option in options) {
this.picker[option] = options[option];
}
+
+ this.picker.$on('on-pick', (date, visible = false) => {
+ this.$emit('on-change', date);
+ this.value = date;
+ this.visible = visible;
+ this.picker.resetView && this.picker.resetView();
+ });
+
+ // todo $on('on-range')
}
+ if (this.internalValue instanceof Date) {
+ this.picker.date = new Date(this.internalValue.getTime());
+ } else {
+ this.picker.value = this.internalValue;
+ }
+ this.picker.resetView && this.picker.resetView();
}
},
watch: {
@@ -143,14 +298,24 @@
if (val) {
this.showPicker();
this.$refs.drop.update();
+ this.$emit('on-open-change', true);
} else {
+ if (this.picker) {
+ this.picker.resetView && this.picker.resetView();
+ }
this.$refs.drop.destroy();
+ this.$emit('on-open-change', false);
+ }
+ },
+ internalValue(val) {
+ if (!val && this.picker && typeof this.picker.handleClear === 'function') {
+ this.picker.handleClear();
}
},
value: {
immediate: true,
handler (val) {
- this.internalValue = formatDate(val);
+ this.internalValue = val;
}
}
},
diff --git a/src/components/date-picker/picker/date-picker.js b/src/components/date-picker/picker/date-picker.js
index 79e77e3..7b5b8c7 100644
--- a/src/components/date-picker/picker/date-picker.js
+++ b/src/components/date-picker/picker/date-picker.js
@@ -20,9 +20,7 @@ export default {
},
default: 'date'
},
- value: {
- type: [String, Array]
- }
+ value: {}
},
created () {
if (!this.value) {
diff --git a/src/components/input/input.vue b/src/components/input/input.vue
index 39fe201..f4194ab 100644
--- a/src/components/input/input.vue
+++ b/src/components/input/input.vue
@@ -14,7 +14,8 @@
v-model="value"
@keyup.enter="handleEnter"
@focus="handleFocus"
- @blur="handleBlur">
+ @blur="handleBlur"
+ @change="handleChange">
@@ -52,7 +54,7 @@
value: {
type: [String, Number],
default: '',
- twoWay: true
+// twoWay: true
},
size: {
validator (value) {
@@ -139,6 +141,9 @@
handleBlur () {
this.$emit('on-blur');
},
+ handleChange () {
+ this.$emit('on-change', this.value);
+ },
resizeTextarea () {
const autosize = this.autosize;
if (!autosize || this.type !== 'textarea') {
@@ -152,11 +157,10 @@
}
},
watch: {
- value (val) {
+ value () {
this.$nextTick(() => {
this.resizeTextarea();
});
- this.$emit('on-change', val);
}
},
ready () {
diff --git a/src/styles/components/date-picker.less b/src/styles/components/date-picker.less
index ff8adb0..2015a10 100644
--- a/src/styles/components/date-picker.less
+++ b/src/styles/components/date-picker.less
@@ -1,9 +1,11 @@
@date-picker-prefix-cls: ~"@{css-prefix}date-picker";
+@picker-prefix-cls: ~"@{css-prefix}picker";
.@{date-picker-prefix-cls} {
position: relative;
.@{select-dropdown-prefix-cls} {
width: auto;
+ padding: 0;
overflow: visible;
max-height: none;
}
@@ -100,4 +102,75 @@
}
}
}
+
+ &-cells-year,&-cells-month{
+ margin-top: 14px;
+ span{
+ width: 40px;
+ height: 28px;
+ line-height: 28px;
+ margin: 10px 12px;
+ border-radius: @btn-border-radius-small;
+ em{
+ width: 40px;
+ height: 28px;
+ line-height: 28px;
+ margin: 0;
+ }
+ }
+ }
+
+ &-header{
+ height: 32px;
+ line-height: 32px;
+ text-align: center;
+ border-bottom: 1px solid @border-color-split;
+ &-label{
+ cursor: pointer;
+ transition: color @transition-time @ease-in-out;
+ &:hover{
+ color: @primary-color;
+ }
+ }
+ }
+ &-prev-btn{
+ float: left;
+ &-arrow-double{
+ margin-left: 10px;
+ i:after{
+ content: "\F3D2";
+ }
+ }
+ }
+ &-next-btn{
+ float: right;
+ &-arrow-double{
+ margin-right: 10px;
+ i:after{
+ content: "\F3D3";
+ }
+ }
+ }
+}
+
+.@{picker-prefix-cls} {
+ &-panel{
+ &-icon-btn{
+ display: inline-block;
+ width: 20px;
+ height: 24px;
+ line-height: 26px;
+ margin-top: 4px;
+ text-align: center;
+ cursor: pointer;
+ color: @btn-disable-color;
+ transition: color @transition-time @ease-in-out;
+ &:hover{
+ color: @primary-color;
+ }
+ i{
+ font-size: 14px;
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/test/routers/date.vue b/test/routers/date.vue
index cb599a1..73618ab 100644
--- a/test/routers/date.vue
+++ b/test/routers/date.vue
@@ -1,23 +1,42 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
--
libgit2 0.21.4