可跨年多选,支持自定义格式(format="YYYY-MM"),需引入moment时间格式化插件(不想引入的话自己改下代码),使用时直接其他页面导入就行了
直接上效果图,
<template>
<!-- 月份多选插件 -->
<div class="monthEl">
<div @mouseenter="changeIcon" @mouseleave="removeIcon">
<el-input
v-model="monthVal"
placeholder="选择一个或多个月份"
readonly
@click.stop.native="isMonthDis = true"
>
</el-input>
<i
v-show="isRemove"
class="el-icon-circle-close"
@click="monthValRemove"
></i>
</div>
<transition name="fade">
<div v-show="isMonthDis" class="month" @click.stop="isMonthDis = true">
<div class="date-menu">
<i class="el-icon-d-arrow-left" @click="addAndReduce('reduce')"></i>
<span>{{ years }}年</span>
<i class="el-icon-d-arrow-right" @click="addAndReduce('add')"></i>
</div>
<ul>
<li
v-for="(item, i) in newMonths"
:key="i"
@click="monthSelected(item)"
>
<span
:class="{ selected: item.show, active: item.currentM }"
>{{ item.num }}月</span>
</li>
</ul>
<el-row type="flex" justify="end">
<el-button class="mini" @click.stop="sure">确定</el-button>
</el-row>
</div>
</transition>
</div>
</template>
<script>
import moment from 'moment'
export default {
props: {
format: {
type: String,
default: 'YYYYMM'
}
},
data() {
return {
monthVal: '',
years: new Date().getFullYear(),
months: [],
isMonthDis: false,
isRemove: false
}
},
computed: {
newMonths: vm => {
return vm.months.filter(e => e.years === vm.years)
}
},
watch: {
isMonthDis(val) {
if (val) {
this.ergodic()
} else {
if (!this.monthVal) {
this.clearSelected()
}
}
}
},
mounted() {
this.months = this.getMonthList()
},
methods: {
// 清除选中项
clearSelected() {
this.months.forEach(e => {
e.show = false
})
},
// 高亮当前月
ergodic() {
const date = new Date()
this.months.forEach(e => {
if (
this.years === date.getFullYear() &&
e.num === date.getMonth() + 1
) {
e.currentM = true
} else {
e.currentM = false
}
})
},
// 选中月份
monthSelected(item) {
item.show = !item.show
},
// 确定选中值
sure() {
const arr = []
this.months.forEach(e => {
if (e.show) {
arr.push(moment(`${e.years}-${e.num}`).format(this.format))
}
})
this.monthVal = arr.join(',')
this.isMonthDis = false
this.$emit('selectDate', this.monthVal)
},
// 返回月份数组
getMonthList() {
const arr = []
for (var i = 1; i <= 12; i++) {
arr.push({
num: i,
show: false,
years: this.years,
currentM: false
})
}
return arr
},
// 加减月份
addAndReduce(type) {
if (type === 'reduce') {
this.years--
} else {
this.years++
}
if (!this.months.some(e => e.years === this.years)) {
// 所有月份中不存在属于所选年的月份
if (type === 'reduce') {
this.months = this.getMonthList().concat(this.months)
} else {
this.months = this.months.concat(this.getMonthList())
}
}
this.ergodic()
},
// 鼠标移入
changeIcon() {
if (this.monthVal) {
this.isRemove = true
}
},
// 鼠标离开
removeIcon() {
this.isRemove = false
},
// 清空月值
monthValRemove() {
this.monthVal = ''
this.years = new Date().getFullYear()
this.clearSelected()
}
}
}
</script>
<style lang="scss" scoped>
.monthEl {
position: relative;
width: 220px;
.el-input {
position: relative;
cursor: pointer;
input {
text-overflow: ellipsis;
}
}
.el-icon-circle-close {
position: absolute;
top: 50%;
transform: translateY(-50%);
right: 10px;
font-size: 14px;
color: #c0c4cc;
cursor: pointer;
}
.fade-enter-active,
.fade-leave-active {
transition: all 0.2s;
}
.fade-enter,
.fade-leave-active {
opacity: 0;
transform: translateY(-10px);
}
.month {
width: 324px;
position: absolute;
top: 45px;
left: 0;
z-index: 4;
background: #fff;
border: 1px solid #dcdfe6;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
padding: 12px;
border-radius: 4px;
.date-menu {
display: flex;
justify-content: space-between;
border-bottom: 1px solid #ebeef5;
padding-bottom: 5px;
i {
font-size: 12px;
margin-top: 7px;
}
}
ul {
list-style: none;
padding-left: 0;
border-bottom: 1px solid #ebeef5;
li {
width: 25%;
height: 40px;
line-height: 40px;
display: inline-block;
cursor: pointer;
font-size: 12px;
text-align: center;
span {
display: inline-block;
width: 30px;
height: 30px;
line-height: 30px;
}
}
li:hover {
color: #409eff;
}
.active {
color: #409eff;
font-weight: 700;
}
.selected {
color: #fff;
background: #409eff;
border-radius: 15px;
}
}
.mini {
font-size: 12px;
}
}
.month:after {
content: '';
display: block;
width: 8px;
height: 8px;
border-right: 1px solid #dcdfe6;
border-top: 1px solid #dcdfe6;
transform: rotate(-45deg);
position: absolute;
top: -5px;
background: #fff;
}
}
</style>
使用时引入:
<template>
<div class="align-items-center">
<span>所属时间:</span>
<monthMultipleChoice @selectDate="selectDateHandle" />
</div>
</template>
<script>
export default {
components: {
monthMultipleChoice: () =>
import('@/views/common/monthMultipleChoice/index')
},
methods: {
selectDateHandle(time) {
console.log(time)
},
}
</script>