monthpicker.vue 5.97 KB
<style scoped>
.datetime-picker {
    position: relative;
    display: inline-block;
    font-family: Helvetica, Arial, "Microsoft YaHei";
    -webkit-font-smoothing: antialiased;
    color: #333;
}
.datetime-picker * {
    box-sizing: border-box;
}
.datetime-picker input {
    width: 100%;
    padding: 5px 10px;
    height: 34px;
    line-height: 32px;
    outline: 0 none;
    border: 1px solid #ccc;
    font-size: 14px;
}
.datetime-picker .picker-wrap {
    position: absolute;
    z-index: 1000;
    width: 286px; 
    height: 140px;
    margin-top: 2px;
    background-color: #fff;
    box-shadow: 0 0 6px #ccc;
}
.datetime-picker table {
    width: 100%;
    border-collapse: collapse;
    border-spacing: 0;
    text-align: center;
    font-size: 13px;
}
.datetime-picker tr {
    height: 34px;
    border: 0 none;
}
.datetime-picker th, .datetime-picker td {
    user-select: none;
    width: 34px;
    height: 34px;
    padding: 0;
    border: 0 none;
    line-height: 34px;
    text-align: center;
}
.datetime-picker td {
    cursor: pointer;
}
.datetime-picker td:hover {
    background-color: #f0f0f0;
}
.datetime-picker td.date-pass, .datetime-picker td.date-future {
    color: #aaa;
}
.datetime-picker td.date-active {
    background-color: #ececec;
    color: #3bb4f2;
}
.datetime-picker .date-head {
    background-color: #3bb4f2;
    text-align: center;
    color: #fff;
    font-size: 14px;
}
.datetime-picker .date-days {
    color: #3bb4f2;
    font-size: 14px;
}
.datetime-picker .show-year {
    display: inline-block;
    min-width: 62px;
    vertical-align: middle;
}
.datetime-picker .show-month {
    display: inline-block;
    min-width: 28px;
    vertical-align: middle;
}
.datetime-picker .btn-prev,
.datetime-picker .btn-next {
    cursor: pointer;
    display: inline-block;
    padding: 0 10px;
    vertical-align: middle;
}
.datetime-picker .btn-prev:hover,
.datetime-picker .btn-next:hover {
    background: rgba(16, 160, 234, 0.5);
}
</style>

<template>
    <div class="datetime-picker" :style="{ width: width }">
        <input
            type="text"
            :style="styleObj"
            :readonly="readonly"
            v-model="target"
            @click="show = !show" :placeholder='placeholder' :class='inpclass' :id='id'>
        <div class="picker-wrap" v-show="show">
            <table class="date-picker">
                <thead>
                    <tr class="date-head">
                        <th colspan="4">
                            <span class="btn-prev" @click="yearClick(-1)">&lt;</span>
                            <span class="show-year">{{now.getFullYear()}}</span>
                            <span class="btn-next" @click="yearClick(1)">&gt;</span>
                        </th>
                    </tr>
                </thead>
                <tbody>
                    <tr v-for="i in 3">
                        <td v-for="j in 4"
                            :class="date[i * 4 + j] && date[i * 4 + j].status"
                            :date="date[i * 4 + j] && date[i * 4 + j].date"
                            @click="pickDate(i * 4 + j)">{{date[i * 4 + j] && date[i * 4 + j]}}</td>
                    </tr>
                </tbody>
            </table>
        </div>
    </div>
</template>

<script>
    export default {
        props: {
            width: { type: String, default: '100%' },
            readonly: { type: Boolean, default: false },
            value: { type: String, default: '' },
            format: { type: String, default: 'YYYY-MM' },
            target: { type: String, twoWay: true },
            placeholder:{ type:String,default: '年月'},
             inpclass:{ type:String},
            id:{type:String}
        },
        data () {
            return {
                show: false,
                months: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
                date: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
                dateName: ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12'],
                now: new Date()
            };
        },
        watch: {
            now () {
                this.update();
            },
            show () {
                this.update();
            }
        },
        methods: {
            close () {
                this.show = false;
            },
            update () {
                var arr = ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'];
                var j = 1;
                while (arr.length < 12) {
                    arr.push({
                        text: j,
                        time: new Date(time.getFullYear(), time.getMonth() + 1, j),
                        status: 'date-future'
                    });
                    j++;
                }
                this.date = arr;
            },
            yearClick (flag) {
                this.now.setFullYear(this.now.getFullYear() + flag);
                this.now = new Date(this.now);
            },
            monthClick (flag) {
                this.now.setMonth(this.now.getMonth() + flag);
                this.now = new Date(this.now);
            },
            pickDate (index) {
                this.show = false;
                var year = this.now.getFullYear();
                this.target = year + "年" + this.dateName[index] + "月";
            },
            parse (str) {
                var time = new Date(str);
                return isNaN(time.getTime()) ? null : time;
            },
            leave (e) {
                if (!this.$el.contains(e.target)) {
                    this.close();
                }
            }
        },
        ready () {
            this.now = this.parse(this.value) || new Date();
            document.addEventListener('click', this.leave, false);
        },
        beforeDestroy () {
            document.removeEventListener('click', this.leave, false);
        }
    };
</script>