Commit 0f6778937cce9dbbc6d1c99b4d0da3f8dfd7283b

Authored by 梁灏
1 parent 17e1fcf1

update DatePicker

update DatePicker
src/components/date-picker/base/date-table.vue
1 1 <template>
2   -
  2 + <table
  3 + cellspacing="0"
  4 + cellpadding="0"
  5 + :class="classes"
  6 + @click="handleClick"
  7 + @mousemove="handleMouseMove">
  8 + <tbody>
  9 + <tr>
  10 + <th v-if="showWeekNumber"></th>
  11 + <th>日</th>
  12 + <th>一</th>
  13 + <th>二</th>
  14 + <th>三</th>
  15 + <th>四</th>
  16 + <th>五</th>
  17 + <th>六</th>
  18 + </tr>
  19 + <tr :class="rowCls(row[1])" v-for="row in rows">
  20 + <td :class="getCellClasses(cell)" v-for="cell in row">{{ cell.text }}</td>
  21 + </tr>
  22 + </tbody>
  23 + </table>
3 24 </template>
4 25 <script>
  26 + const prefixCls = 'ivu-date-picker-table';
  27 +
5 28 export default {
6   - props: {},
  29 + props: {
  30 + date: {},
  31 + year: {},
  32 + month: {},
  33 + week: {},
  34 + selectionMode: {
  35 + default: 'day'
  36 + },
  37 + showWeekNumber: {
  38 + type: Boolean,
  39 + default: false
  40 + },
  41 + disabledDate: {},
  42 + minDate: {},
  43 + maxDate: {},
  44 + rangeState: {
  45 + default () {
  46 + return {
  47 + endDate: null,
  48 + selecting: false,
  49 + row: null,
  50 + column: null
  51 + };
  52 + }
  53 + },
  54 + value: {}
  55 + },
7 56 data () {
8   - return {}
  57 + return {
  58 + prefixCls: prefixCls
  59 + }
  60 + },
  61 + computed: {
  62 + classes () {
  63 + return [
  64 + `${prefixCls}`,
  65 + {
  66 + [`${prefixCls}-week-mode`]: this.selectionMode === 'week'
  67 + }
  68 + ]
  69 + }
9 70 },
10   - computed: {},
11   - methods: {}
  71 + methods: {
  72 + handleClick () {
  73 +
  74 + },
  75 + handleMouseMove () {
  76 +
  77 + },
  78 + rowCls (cell) {
  79 + return [
  80 + `${prefixCls}-row`,
  81 + {
  82 + [`${prefixCls}-row-current`]: this.value && this.isWeekActive(cell)
  83 + }
  84 + ]
  85 + },
  86 + isWeekActive (cell) {
  87 +
  88 + },
  89 + getCellCls (cell) {
  90 + return [
  91 + `${prefixCls}-cell`,
  92 + {
  93 + [`${prefixCls}-cell-today`]: cell.type === 'today'
  94 + }
  95 + ]
  96 + }
  97 + }
12 98 }
13 99 </script>
14 100 \ No newline at end of file
... ...
src/components/date-picker/base/month-table.vue
1 1 <template>
2   -
  2 + <div>month</div>
3 3 </template>
4 4 <script>
5 5 export default {
6   - props: {},
  6 +// props: {},
7 7 data () {
8 8 return {}
9 9 },
... ...
src/components/date-picker/base/year-table.vue
1 1 <template>
2   -
  2 + <div>year</div>
3 3 </template>
4 4 <script>
5 5 export default {
6   - props: {},
  6 +// props: {},
7 7 data () {
8 8 return {}
9 9 },
... ...
src/components/date-picker/panel/date.vue
1 1 <template>
2   -
  2 + <div :class="[prefixCls + '-body-wrapper']">
  3 + <div :class="[prefixCls + '-sidebar']" v-if="shortcuts">
  4 + <div
  5 + :class="[prefixCls + '-shortcut']"
  6 + v-for="shortcut in shortcuts"
  7 + @click="handleShortcutClick(shortcut)">{{ shortcut.text }}</div>
  8 + </div>
  9 + <div :class="[prefixCls + '-body']">
  10 + <div :class="[datePrefixCls + '-header']" v-show="currentView !== 'time'">
  11 + <span
  12 + :class="iconBtnCls('prev', '-double')"
  13 + @click="prevYear"></span>
  14 + <span
  15 + :class="iconBtnCls('prev')"
  16 + @click="prevMonth"
  17 + v-show="currentView === 'date'"></span>
  18 + <span
  19 + :class="[datePrefixCls + '-header-label']"
  20 + @click="showYearPicker">{{ }}</span>
  21 + <span
  22 + :class="[datePrefixCls + '-header-label']"
  23 + @click="showMonthPicker"
  24 + v-show="currentView === 'date'">{{ }}</span>
  25 + <span
  26 + :class="iconBtnCls('next')"
  27 + @click="nextMonth"
  28 + v-show="currentView === 'date'"></span>
  29 + <span
  30 + :class="iconBtnCls('next', '-double')"
  31 + @click="nextYear"></span>
  32 + </div>
  33 + <div :class="[prefixCls + '-content']">
  34 + <date-table
  35 + v-show="currentView === 'date'"></date-table>
  36 + <year-table
  37 + v-show="currentView === 'year'"></year-table>
  38 + <month-table
  39 + v-show="currentView === 'month'"></month-table>
  40 + </div>
  41 + </div>
  42 + </div>
3 43 </template>
4 44 <script>
  45 + import DateTable from '../base/date-table.vue';
  46 + import YearTable from '../base/year-table.vue';
  47 + import MonthTable from '../base/month-table.vue';
  48 +
  49 + const prefixCls = 'ivu-picker-panel';
  50 + const datePrefixCls = 'ivu-date-picker';
  51 +
5 52 export default {
6   - props: {},
  53 + components: { DateTable, YearTable, MonthTable },
7 54 data () {
8   - return {}
  55 + return {
  56 + prefixCls: prefixCls,
  57 + datePrefixCls: datePrefixCls,
  58 + shortcuts: [],
  59 + currentView: 'date'
  60 + }
9 61 },
10 62 computed: {},
11   - methods: {}
  63 + methods: {
  64 + handleShortcutClick (shortcut) {
  65 +
  66 + },
  67 + iconBtnCls (direction, type = '') {
  68 + return [
  69 + `${prefixCls}-icon-btn`,
  70 + `${datePrefixCls}-${direction}-btn`,
  71 + `${datePrefixCls}-${direction}-btn-arrow${type}`,
  72 + ]
  73 + },
  74 + prevYear () {
  75 +
  76 + },
  77 + nextYear () {
  78 +
  79 + },
  80 + prevMonth () {
  81 +
  82 + },
  83 + nextMonth () {
  84 +
  85 + },
  86 + showYearPicker () {
  87 +
  88 + },
  89 + showMonthPicker () {
  90 +
  91 + }
  92 + },
  93 + ready () {
  94 + console.log(123)
  95 + },
  96 + beforeDestroy () {
  97 + console.log(456)
  98 + }
12 99 }
13 100 </script>
14 101 \ No newline at end of file
... ...
src/components/date-picker/picker.vue
1 1 <template>
2   -
  2 + <div
  3 + :class="[prefixCls]"
  4 + v-clickoutside="handleClose"
  5 + @mouseenter="handleMouseenter"
  6 + @mouseleave="handleMouseleave">
  7 + <i-input
  8 + v-el:reference
  9 + :class="[prefixCls + '-editor']"
  10 + :readonly="!editable || readonly"
  11 + :disabled="disabled"
  12 + :size="size"
  13 + :placeholder="placeholder"
  14 + :value.sync="visualValue"
  15 + @on-focus="handleFocus"
  16 + @on-blur="handleBlur"
  17 + @on-click="handleIconClick"
  18 + :icon="iconType"></i-input>
  19 + <Drop v-show="visible" :placement="placement" transition="slide-up" v-ref:drop>
  20 + <div v-el:picker></div>
  21 + </Drop>
  22 + </div>
3 23 </template>
4 24 <script>
  25 + import Vue from 'vue';
  26 + import iInput from '../../components/input/input.vue';
  27 + import Drop from '../../components/select/dropdown.vue';
  28 + import clickoutside from '../../directives/clickoutside';
  29 + import { oneOf } from '../../utils/assist';
  30 +
  31 + const prefixCls = 'ivu-date-picker';
  32 +
  33 + const DEFAULT_FORMATS = {
  34 + date: 'yyyy-MM-dd',
  35 + month: 'yyyy-MM',
  36 + datetime: 'yyyy-MM-dd HH:mm:ss',
  37 + time: 'HH:mm:ss',
  38 + timerange: 'HH:mm:ss',
  39 + daterange: 'yyyy-MM-dd',
  40 + datetimerange: 'yyyy-MM-dd HH:mm:ss'
  41 + };
  42 +
  43 + const PLACEMENT_MAP = {
  44 + left: 'bottom-start',
  45 + center: 'bottom-center',
  46 + right: 'bottom-end'
  47 + };
  48 +
5 49 export default {
6   - props: {},
  50 + components: { iInput, Drop },
  51 + directives: { clickoutside },
  52 + props: {
  53 + format: {
  54 + type: String
  55 + },
  56 + readonly: {
  57 + type: Boolean,
  58 + default: false
  59 + },
  60 + disabled: {
  61 + type: Boolean,
  62 + default: false
  63 + },
  64 + editable: {
  65 + type: Boolean,
  66 + default: true
  67 + },
  68 + size: {
  69 + validator (value) {
  70 + return oneOf(value, ['small', 'large']);
  71 + }
  72 + },
  73 + placeholder: {
  74 + type: String,
  75 + default: ''
  76 + },
  77 + align: {
  78 + validator (value) {
  79 + return oneOf(value, ['left', 'center', 'right']);
  80 + },
  81 + default: 'left'
  82 + },
  83 + options: {
  84 + type: Object
  85 + }
  86 + },
7 87 data () {
8   - return {}
  88 + return {
  89 + prefixCls: prefixCls,
  90 + showClose: false,
  91 + visualValue: '',
  92 + visible: false,
  93 + picker: null
  94 + }
  95 + },
  96 + computed: {
  97 + iconType () {
  98 + return this.showClose ? 'ios-close' : 'ios-calendar-outline';
  99 + },
  100 + placement () {
  101 + return PLACEMENT_MAP[this.align];
  102 + }
  103 + },
  104 + methods: {
  105 + handleClose () {
  106 + this.visible = false;
  107 + },
  108 + handleFocus () {
  109 + this.visible = true;
  110 + },
  111 + handleBlur () {
  112 +
  113 + },
  114 + handleMouseenter () {
  115 + if (this.readonly || this.disabled) return;
  116 + if (this.visualValue) {
  117 + this.showClose = true;
  118 + }
  119 + },
  120 + handleMouseleave () {
  121 + this.showClose = false;
  122 + },
  123 + handleIconClick () {
  124 +
  125 + },
  126 + showPicker () {
  127 + if (!this.picker) {
  128 + this.picker = new Vue(this.panel).$mount(this.$els.picker);
  129 + }
  130 + }
  131 + },
  132 + watch: {
  133 + visible (val) {
  134 + if (val) {
  135 + this.showPicker();
  136 + this.$refs.drop.update();
  137 + } else {
  138 + this.$refs.drop.destroy();
  139 + }
  140 + }
9 141 },
10   - computed: {},
11   - methods: {}
  142 + beforeDestroy () {
  143 + if (this.picker) {
  144 + this.picker.$destroy();
  145 + }
  146 + }
12 147 }
13 148 </script>
14 149 \ No newline at end of file
... ...
src/components/date-picker/picker/date-picker.js
... ... @@ -9,11 +9,15 @@ const getPanel = function (type) {
9 9 return DatePanel;
10 10 };
11 11  
  12 +import { oneOf } from '../../../utils/assist';
  13 +
12 14 export default {
13 15 mixins: [Picker],
14 16 props: {
15 17 type: {
16   - type: String,
  18 + validator (value) {
  19 + return oneOf(value, ['year', 'month', 'week', 'date', 'daterange', 'datetime', 'datetimerange']);
  20 + },
17 21 default: 'date'
18 22 }
19 23 },
... ...
src/components/date-picker/util.js 0 → 100644
  1 +import dateUtil from '../../utils/date';
  2 +
  3 +const newArray = function(start, end) {
  4 + let result = [];
  5 + for (let i = start; i <= end; i++) {
  6 + result.push(i);
  7 + }
  8 + return result;
  9 +};
  10 +
  11 +export const toDate = function(date) {
  12 + date = new Date(date);
  13 + if (isNaN(date.getTime())) return null;
  14 + return date;
  15 +};
  16 +
  17 +export const formatDate = function(date, format) {
  18 + date = toDate(date);
  19 + if (!date) return '';
  20 + return dateUtil.format(date, format || 'yyyy-MM-dd');
  21 +};
  22 +
  23 +export const parseDate = function(string, format) {
  24 + return dateUtil.parse(string, format || 'yyyy-MM-dd');
  25 +};
  26 +
  27 +export const getDayCountOfMonth = function(year, month) {
  28 + if (month === 3 || month === 5 || month === 8 || month === 10) {
  29 + return 30;
  30 + }
  31 +
  32 + if (month === 1) {
  33 + if (year % 4 === 0 && year % 100 !== 0 || year % 400 === 0) {
  34 + return 29;
  35 + } else {
  36 + return 28;
  37 + }
  38 + }
  39 +
  40 + return 31;
  41 +};
  42 +
  43 +export const getFirstDayOfMonth = function(date) {
  44 + const temp = new Date(date.getTime());
  45 + temp.setDate(1);
  46 + return temp.getDay();
  47 +};
  48 +
  49 +export const DAY_DURATION = 86400000;
  50 +
  51 +export const getStartDateOfMonth = function(year, month) {
  52 + const result = new Date(year, month, 1);
  53 + const day = result.getDay();
  54 +
  55 + if (day === 0) {
  56 + result.setTime(result.getTime() - DAY_DURATION * 7);
  57 + } else {
  58 + result.setTime(result.getTime() - DAY_DURATION * day);
  59 + }
  60 +
  61 + return result;
  62 +};
  63 +
  64 +export const getWeekNumber = function(src) {
  65 + const date = new Date(src.getTime());
  66 + date.setHours(0, 0, 0, 0);
  67 + // Thursday in current week decides the year.
  68 + date.setDate(date.getDate() + 3 - (date.getDay() + 6) % 7);
  69 + // January 4 is always in week 1.
  70 + const week1 = new Date(date.getFullYear(), 0, 4);
  71 + // Adjust to Thursday in week 1 and count number of weeks from date to week 1.
  72 + return 1 + Math.round(((date.getTime() - week1.getTime()) / 86400000 - 3 + (week1.getDay() + 6) % 7) / 7);
  73 +};
  74 +
  75 +export const prevMonth = function(src) {
  76 + const year = src.getFullYear();
  77 + const month = src.getMonth();
  78 + const date = src.getDate();
  79 +
  80 + const newYear = month === 0 ? year - 1 : year;
  81 + const newMonth = month === 0 ? 11 : month - 1;
  82 +
  83 + const newMonthDayCount = getDayCountOfMonth(newYear, newMonth);
  84 + if (newMonthDayCount < date) {
  85 + src.setDate(newMonthDayCount);
  86 + }
  87 +
  88 + src.setMonth(newMonth);
  89 + src.setFullYear(newYear);
  90 +
  91 + return new Date(src.getTime());
  92 +};
  93 +
  94 +export const nextMonth = function(src) {
  95 + const year = src.getFullYear();
  96 + const month = src.getMonth();
  97 + const date = src.getDate();
  98 +
  99 + const newYear = month === 11 ? year + 1 : year;
  100 + const newMonth = month === 11 ? 0 : month + 1;
  101 +
  102 + const newMonthDayCount = getDayCountOfMonth(newYear, newMonth);
  103 + if (newMonthDayCount < date) {
  104 + src.setDate(newMonthDayCount);
  105 + }
  106 +
  107 + src.setMonth(newMonth);
  108 + src.setFullYear(newYear);
  109 +
  110 + return new Date(src.getTime());
  111 +};
  112 +
  113 +export const getRangeHours = function(ranges) {
  114 + const hours = [];
  115 + let disabledHours = [];
  116 +
  117 + (ranges || []).forEach(range => {
  118 + const value = range.map(date => date.getHours());
  119 +
  120 + disabledHours = disabledHours.concat(newArray(value[0], value[1]));
  121 + });
  122 +
  123 + if (disabledHours.length) {
  124 + for (let i = 0; i < 24; i++) {
  125 + hours[i] = disabledHours.indexOf(i) === -1;
  126 + }
  127 + } else {
  128 + for (let i = 0; i < 24; i++) {
  129 + hours[i] = false;
  130 + }
  131 + }
  132 +
  133 + return hours;
  134 +};
  135 +
  136 +export const limitRange = function(date, ranges) {
  137 + if (!ranges || !ranges.length) return date;
  138 +
  139 + const len = ranges.length;
  140 + const format = 'HH:mm:ss';
  141 +
  142 + date = dateUtil.parse(dateUtil.format(date, format), format);
  143 + for (let i = 0; i < len; i++) {
  144 + const range = ranges[i];
  145 + if (date >= range[0] && date <= range[1]) {
  146 + return date;
  147 + }
  148 + }
  149 +
  150 + let maxDate = ranges[0][0];
  151 + let minDate = ranges[0][0];
  152 +
  153 + ranges.forEach(range => {
  154 + minDate = new Date(Math.min(range[0], minDate));
  155 + maxDate = new Date(Math.max(range[1], maxDate));
  156 + });
  157 +
  158 + return date < minDate ? minDate : maxDate;
  159 +};
... ...
src/utils/date.js 0 → 100755
  1 +/*eslint-disable*/
  2 +// 把 YYYY-MM-DD 改成了 yyyy-MM-dd
  3 +(function (main) {
  4 + 'use strict';
  5 +
  6 + /**
  7 + * Parse or format dates
  8 + * @class fecha
  9 + */
  10 + var fecha = {};
  11 + var token = /d{1,4}|M{1,4}|yy(?:yy)?|S{1,3}|Do|ZZ|([HhMsDm])\1?|[aA]|"[^"]*"|'[^']*'/g;
  12 + var twoDigits = /\d\d?/;
  13 + var threeDigits = /\d{3}/;
  14 + var fourDigits = /\d{4}/;
  15 + var word = /[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i;
  16 + var noop = function () {
  17 + };
  18 +
  19 + function shorten(arr, sLen) {
  20 + var newArr = [];
  21 + for (var i = 0, len = arr.length; i < len; i++) {
  22 + newArr.push(arr[i].substr(0, sLen));
  23 + }
  24 + return newArr;
  25 + }
  26 +
  27 + function monthUpdate(arrName) {
  28 + return function (d, v, i18n) {
  29 + var index = i18n[arrName].indexOf(v.charAt(0).toUpperCase() + v.substr(1).toLowerCase());
  30 + if (~index) {
  31 + d.month = index;
  32 + }
  33 + };
  34 + }
  35 +
  36 + function pad(val, len) {
  37 + val = String(val);
  38 + len = len || 2;
  39 + while (val.length < len) {
  40 + val = '0' + val;
  41 + }
  42 + return val;
  43 + }
  44 +
  45 + var dayNames = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
  46 + var monthNames = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
  47 + var monthNamesShort = shorten(monthNames, 3);
  48 + var dayNamesShort = shorten(dayNames, 3);
  49 + fecha.i18n = {
  50 + dayNamesShort: dayNamesShort,
  51 + dayNames: dayNames,
  52 + monthNamesShort: monthNamesShort,
  53 + monthNames: monthNames,
  54 + amPm: ['am', 'pm'],
  55 + DoFn: function DoFn(D) {
  56 + return D + ['th', 'st', 'nd', 'rd'][D % 10 > 3 ? 0 : (D - D % 10 !== 10) * D % 10];
  57 + }
  58 + };
  59 +
  60 + var formatFlags = {
  61 + D: function (dateObj) {
  62 + return dateObj.getDay();
  63 + },
  64 + DD: function (dateObj) {
  65 + return pad(dateObj.getDay());
  66 + },
  67 + Do: function (dateObj, i18n) {
  68 + return i18n.DoFn(dateObj.getDate());
  69 + },
  70 + d: function (dateObj) {
  71 + return dateObj.getDate();
  72 + },
  73 + dd: function (dateObj) {
  74 + return pad(dateObj.getDate());
  75 + },
  76 + ddd: function (dateObj, i18n) {
  77 + return i18n.dayNamesShort[dateObj.getDay()];
  78 + },
  79 + dddd: function (dateObj, i18n) {
  80 + return i18n.dayNames[dateObj.getDay()];
  81 + },
  82 + M: function (dateObj) {
  83 + return dateObj.getMonth() + 1;
  84 + },
  85 + MM: function (dateObj) {
  86 + return pad(dateObj.getMonth() + 1);
  87 + },
  88 + MMM: function (dateObj, i18n) {
  89 + return i18n.monthNamesShort[dateObj.getMonth()];
  90 + },
  91 + MMMM: function (dateObj, i18n) {
  92 + return i18n.monthNames[dateObj.getMonth()];
  93 + },
  94 + yy: function (dateObj) {
  95 + return String(dateObj.getFullYear()).substr(2);
  96 + },
  97 + yyyy: function (dateObj) {
  98 + return dateObj.getFullYear();
  99 + },
  100 + h: function (dateObj) {
  101 + return dateObj.getHours() % 12 || 12;
  102 + },
  103 + hh: function (dateObj) {
  104 + return pad(dateObj.getHours() % 12 || 12);
  105 + },
  106 + H: function (dateObj) {
  107 + return dateObj.getHours();
  108 + },
  109 + HH: function (dateObj) {
  110 + return pad(dateObj.getHours());
  111 + },
  112 + m: function (dateObj) {
  113 + return dateObj.getMinutes();
  114 + },
  115 + mm: function (dateObj) {
  116 + return pad(dateObj.getMinutes());
  117 + },
  118 + s: function (dateObj) {
  119 + return dateObj.getSeconds();
  120 + },
  121 + ss: function (dateObj) {
  122 + return pad(dateObj.getSeconds());
  123 + },
  124 + S: function (dateObj) {
  125 + return Math.round(dateObj.getMilliseconds() / 100);
  126 + },
  127 + SS: function (dateObj) {
  128 + return pad(Math.round(dateObj.getMilliseconds() / 10), 2);
  129 + },
  130 + SSS: function (dateObj) {
  131 + return pad(dateObj.getMilliseconds(), 3);
  132 + },
  133 + a: function (dateObj, i18n) {
  134 + return dateObj.getHours() < 12 ? i18n.amPm[0] : i18n.amPm[1];
  135 + },
  136 + A: function (dateObj, i18n) {
  137 + return dateObj.getHours() < 12 ? i18n.amPm[0].toUpperCase() : i18n.amPm[1].toUpperCase();
  138 + },
  139 + ZZ: function (dateObj) {
  140 + var o = dateObj.getTimezoneOffset();
  141 + return (o > 0 ? '-' : '+') + pad(Math.floor(Math.abs(o) / 60) * 100 + Math.abs(o) % 60, 4);
  142 + }
  143 + };
  144 +
  145 + var parseFlags = {
  146 + d: [twoDigits, function (d, v) {
  147 + d.day = v;
  148 + }],
  149 + M: [twoDigits, function (d, v) {
  150 + d.month = v - 1;
  151 + }],
  152 + yy: [twoDigits, function (d, v) {
  153 + var da = new Date(), cent = +('' + da.getFullYear()).substr(0, 2);
  154 + d.year = '' + (v > 68 ? cent - 1 : cent) + v;
  155 + }],
  156 + h: [twoDigits, function (d, v) {
  157 + d.hour = v;
  158 + }],
  159 + m: [twoDigits, function (d, v) {
  160 + d.minute = v;
  161 + }],
  162 + s: [twoDigits, function (d, v) {
  163 + d.second = v;
  164 + }],
  165 + yyyy: [fourDigits, function (d, v) {
  166 + d.year = v;
  167 + }],
  168 + S: [/\d/, function (d, v) {
  169 + d.millisecond = v * 100;
  170 + }],
  171 + SS: [/\d{2}/, function (d, v) {
  172 + d.millisecond = v * 10;
  173 + }],
  174 + SSS: [threeDigits, function (d, v) {
  175 + d.millisecond = v;
  176 + }],
  177 + D: [twoDigits, noop],
  178 + ddd: [word, noop],
  179 + MMM: [word, monthUpdate('monthNamesShort')],
  180 + MMMM: [word, monthUpdate('monthNames')],
  181 + a: [word, function (d, v, i18n) {
  182 + var val = v.toLowerCase();
  183 + if (val === i18n.amPm[0]) {
  184 + d.isPm = false;
  185 + } else if (val === i18n.amPm[1]) {
  186 + d.isPm = true;
  187 + }
  188 + }],
  189 + ZZ: [/[\+\-]\d\d:?\d\d/, function (d, v) {
  190 + var parts = (v + '').match(/([\+\-]|\d\d)/gi), minutes;
  191 +
  192 + if (parts) {
  193 + minutes = +(parts[1] * 60) + parseInt(parts[2], 10);
  194 + d.timezoneOffset = parts[0] === '+' ? minutes : -minutes;
  195 + }
  196 + }]
  197 + };
  198 + parseFlags.DD = parseFlags.DD;
  199 + parseFlags.dddd = parseFlags.ddd;
  200 + parseFlags.Do = parseFlags.dd = parseFlags.d;
  201 + parseFlags.mm = parseFlags.m;
  202 + parseFlags.hh = parseFlags.H = parseFlags.HH = parseFlags.h;
  203 + parseFlags.MM = parseFlags.M;
  204 + parseFlags.ss = parseFlags.s;
  205 + parseFlags.A = parseFlags.a;
  206 +
  207 +
  208 + // Some common format strings
  209 + fecha.masks = {
  210 + 'default': 'ddd MMM dd yyyy HH:mm:ss',
  211 + shortDate: 'M/D/yy',
  212 + mediumDate: 'MMM d, yyyy',
  213 + longDate: 'MMMM d, yyyy',
  214 + fullDate: 'dddd, MMMM d, yyyy',
  215 + shortTime: 'HH:mm',
  216 + mediumTime: 'HH:mm:ss',
  217 + longTime: 'HH:mm:ss.SSS'
  218 + };
  219 +
  220 + /***
  221 + * Format a date
  222 + * @method format
  223 + * @param {Date|number} dateObj
  224 + * @param {string} mask Format of the date, i.e. 'mm-dd-yy' or 'shortDate'
  225 + */
  226 + fecha.format = function (dateObj, mask, i18nSettings) {
  227 + var i18n = i18nSettings || fecha.i18n;
  228 +
  229 + if (typeof dateObj === 'number') {
  230 + dateObj = new Date(dateObj);
  231 + }
  232 +
  233 + if (Object.prototype.toString.call(dateObj) !== '[object Date]' || isNaN(dateObj.getTime())) {
  234 + throw new Error('Invalid Date in fecha.format');
  235 + }
  236 +
  237 + mask = fecha.masks[mask] || mask || fecha.masks['default'];
  238 +
  239 + return mask.replace(token, function ($0) {
  240 + return $0 in formatFlags ? formatFlags[$0](dateObj, i18n) : $0.slice(1, $0.length - 1);
  241 + });
  242 + };
  243 +
  244 + /**
  245 + * Parse a date string into an object, changes - into /
  246 + * @method parse
  247 + * @param {string} dateStr Date string
  248 + * @param {string} format Date parse format
  249 + * @returns {Date|boolean}
  250 + */
  251 + fecha.parse = function (dateStr, format, i18nSettings) {
  252 + var i18n = i18nSettings || fecha.i18n;
  253 +
  254 + if (typeof format !== 'string') {
  255 + throw new Error('Invalid format in fecha.parse');
  256 + }
  257 +
  258 + format = fecha.masks[format] || format;
  259 +
  260 + // Avoid regular expression denial of service, fail early for really long strings
  261 + // https://www.owasp.org/index.php/Regular_expression_Denial_of_Service_-_ReDoS
  262 + if (dateStr.length > 1000) {
  263 + return false;
  264 + }
  265 +
  266 + var isValid = true;
  267 + var dateInfo = {};
  268 + format.replace(token, function ($0) {
  269 + if (parseFlags[$0]) {
  270 + var info = parseFlags[$0];
  271 + var index = dateStr.search(info[0]);
  272 + if (!~index) {
  273 + isValid = false;
  274 + } else {
  275 + dateStr.replace(info[0], function (result) {
  276 + info[1](dateInfo, result, i18n);
  277 + dateStr = dateStr.substr(index + result.length);
  278 + return result;
  279 + });
  280 + }
  281 + }
  282 +
  283 + return parseFlags[$0] ? '' : $0.slice(1, $0.length - 1);
  284 + });
  285 +
  286 + if (!isValid) {
  287 + return false;
  288 + }
  289 +
  290 + var today = new Date();
  291 + if (dateInfo.isPm === true && dateInfo.hour != null && +dateInfo.hour !== 12) {
  292 + dateInfo.hour = +dateInfo.hour + 12;
  293 + } else if (dateInfo.isPm === false && +dateInfo.hour === 12) {
  294 + dateInfo.hour = 0;
  295 + }
  296 +
  297 + var date;
  298 + if (dateInfo.timezoneOffset != null) {
  299 + dateInfo.minute = +(dateInfo.minute || 0) - +dateInfo.timezoneOffset;
  300 + date = new Date(Date.UTC(dateInfo.year || today.getFullYear(), dateInfo.month || 0, dateInfo.day || 1,
  301 + dateInfo.hour || 0, dateInfo.minute || 0, dateInfo.second || 0, dateInfo.millisecond || 0));
  302 + } else {
  303 + date = new Date(dateInfo.year || today.getFullYear(), dateInfo.month || 0, dateInfo.day || 1,
  304 + dateInfo.hour || 0, dateInfo.minute || 0, dateInfo.second || 0, dateInfo.millisecond || 0);
  305 + }
  306 + return date;
  307 + };
  308 +
  309 + /* istanbul ignore next */
  310 + if (typeof module !== 'undefined' && module.exports) {
  311 + module.exports = fecha;
  312 + } else if (typeof define === 'function' && define.amd) {
  313 + define(function () {
  314 + return fecha;
  315 + });
  316 + } else {
  317 + main.fecha = fecha;
  318 + }
  319 +})(this);
... ...
test/app.vue
... ... @@ -45,6 +45,7 @@ li + li {
45 45 <li><a v-link="'/dropdown'">Dropdown</a></li>
46 46 <li><a v-link="'/tabs'">Tabs</a></li>
47 47 <li><a v-link="'/menu'">Menu</a></li>
  48 + <li><a v-link="'/date'">Date</a></li>
48 49 </ul>
49 50 </nav>
50 51 <router-view></router-view>
... ...
test/main.js
... ... @@ -122,6 +122,11 @@ router.map({
122 122 component: function (resolve) {
123 123 require(['./routers/menu.vue'], resolve);
124 124 }
  125 + },
  126 + '/date': {
  127 + component: function (resolve) {
  128 + require(['./routers/date.vue'], resolve);
  129 + }
125 130 }
126 131 });
127 132  
... ...
test/routers/date.vue 0 → 100644
  1 +<template>
  2 + <div style="margin: 50px">
  3 + <date-picker style="width:200px" placeholder="请选择日期"></date-picker>
  4 + </div>
  5 +</template>
  6 +<script>
  7 + export default {
  8 + props: {},
  9 + data () {
  10 + return {}
  11 + },
  12 + computed: {},
  13 + methods: {}
  14 + }
  15 +</script>
0 16 \ No newline at end of file
... ...