效果图:
multiMonth.vue
<template>
<div class="mul-box">
<a-popover v-model:visible="isShow" title="" trigger="click" getPopupContainer placement="bottom" overlayClassName="monthCard">
<template #content>
<a-calendar :fullscreen="false" @select="onPanelChange" mode="year">
<template #monthFullCellRender="{ current }">
<div :class="calculateMonth(current)">{{new Date(current).getMonth() + 1 + '月'}}</div>
<div :class="getAllMonth(current)"></div>
</template>
</a-calendar>
</template>
<!-- :id="monthId"-->
<div :class="useConfig?.disabled ? 'dised-arrbox' : 'arrbox'" @click="toolTipShow" :style="styleConfig">
<div class="suffix">
<CalendarOutlined style="color: rgba(0, 0, 0, 0.45)"/>
</div>
<div class="tags-part">
<a-tag v-for="(item,index) in tagList" :closable="typeParent === 'searchUse' && tagList.length < 2 ? false : true" class="suspend" @close="tagClose(index,item)" :key="index">
{{item + '月'}}
</a-tag>
</div>
<a-input v-model:value="time" ref="inputTag" class="inputTag" :style="inputStyle" :disabled="useConfig.disabled" />
</div>
</a-popover>
</div>
</template>
<script>
import { computed, reactive, toRefs, watch,ref, nextTick} from 'vue'
import {CalendarOutlined} from '@ant-design/icons-vue'
import dayjs from 'dayjs'
export default {
components:{
CalendarOutlined
},
props:{
defaultMonth:{
type: String,
required: false,
default: ''
},
mounthType: {
type: String,
default: ''
},
mounthId: {
type: String,
default: 'id_1'
},
styleConfig: {
type:String,
default:''
},
allDataList:{
type: Array,
default: ()=>{
return []
}
},
useConfig: {
type: Object,
default: function() {
return {}
}
}
},
setup(props,context){
let inputTag = ref(null);
let aside = ref(null)
const state = reactive({
time:null,
isShow:false,
inputLength:0,
tagList:[],
month:[],
typeParent:'',
mounthId:'0',
allDataList:[],//已有的
})
const inputStyle = computed(() =>{
let style = {}
style.width = `${state.inputLength}px`
return style
})
watch(() => props.allDataList, (value) => {
if(value.length>0){
state.allDataList = value
}
}, {immediate: true})
watch(() => props.monthId, (value) => {
if(!value) return
state.mounthId = value
}, {immediate: true})
watch(() => props.defaultMonth, (value) => {
if(!value) {
state.tagList = []
state.month = []
state.time = ''
return
}
const val_list = value !== '' ? value.split(',') : []
setTimeout(() =>{
state.tagList = [].concat(val_list)
state.month = [].concat(val_list)
context.emit('updateMonth',state.month)
state.time = value
},200)
}, {immediate: true})
watch(() => props.mounthType, (value) =>{
if(!value) return
state.typeParent = value
}, {immediate: true})
watch(() => state.time, (value) => {
if(!value) return
state.inputLength = inputTag.value.length * 12 + 50;
}, {immediate: true})
function toolTipShow(){
if(props.useConfig?.disabled) return
state.isShow = !state.isShow
}
function tagClose(index,data){
state.tagList.splice(index,1)
state.month = [].concat(state.tagList)
state.time = state.tagList.join(',')
context.emit('updateMonth',state.month)
}
const calculateMonth = (month) => {
if(state.month.findIndex(mon => mon === dayjs(month).format('YYYY-MM')) !== -1){
return 'checkbox'
}else{
return 'defultbox'
}
}
//实现月份下方添加小圆点需求
const getAllMonth = (month) => {
if(state.allDataList.findIndex(mon => mon === dayjs(month).format('YYYY-MM')) !== -1){
return 'checkbox1'
}else{
return 'defultbox1'
}
}
const onPanelChange = (day,mode) => {
if(mode.source == "month"){
const index = state.month.findIndex(mon => mon === dayjs(day).format('YYYY-MM'))
if(index === -1){
state.month.push(dayjs(day).format('YYYY-MM'))
}else{
state.month.splice(index,1)
}
state.time = state.month.map(mons => (new Date(mons).getMonth() + 1)).join(',')
state.tagList = [].concat(state.month)
context.emit('updateMonth',state.month)
}
};
return{
inputTag,
aside,
...toRefs(state),
toolTipShow,
getAllMonth,
onPanelChange,
calculateMonth,
inputStyle,
tagClose
}
}
}
</script>
<style lang="scss">
.mul-box {
width: 100%;
.arrbox {
box-sizing:border-box;
border: 1px solid #dcdee2;
background-color: white;
border-radius: 4px;
font-size: 14px;
width: 100% ;
text-align: left;
padding-left: 5px;
overflow: hidden;
cursor: pointer;
display: flex;
justify-content: flex-start;
align-items: center;
.suffix{
display: inline-flex;
margin-right: 10px;
}
.tooltip{
color: #ffffff;
visibility: hidden
}
}
/* 禁用盒子 */
.dised-arrbox {
box-sizing:border-box;
border: 1px solid #dcdee2;
background-color: rgba(238, 238, 236, 0.6);
cursor: not-allowed;
border-radius: 4px;
font-size: 14px;
width: 100% ;
text-align: left;
padding-left: 5px;
// word-wrap: break-word;
overflow: hidden;
display: flex;
justify-content: flex-start;
align-items: center;
.suffix{
margin-right: 10px;
display: inline-flex;
}
.tooltip{
color: #ffffff;
visibility: hidden
}
}
/* 标签 */
.tags-part {
display: inline-block;
font-size: 14px;
margin: 4px 4px 3px 0;
.ant-tag-hidden{
display: inline-block;
}
}
.inputTag {
display: inline-block;
font-size: 14px;
border: none;
box-shadow: none;
outline: none;
padding: 5px;
background-color: transparent;
padding: 0;
vertical-align: top;
height: 32px;
color: #495060;
line-height: 32px;
}
}
.monthCard .ant-tooltip-arrow-content{
display: none
}
.checkbox{
background-color: #0067c0;
width: 73px;
height: 30px;
margin-right: 5px;
margin-bottom: 5px;
color: #ffffff;
display: flex;
border-radius: 5px;
justify-content: center;
align-items: center;
}
.defaultbox{
background-color: #ffffff;
width: 73px;
height: 30px;
margin-right: 5px;
margin-bottom: 5px;
}
.checkbox1{
position: absolute;
left: 50%;
height: 5px;
width: 8px;
border-radius: 5px;
background-color: #ff9800;
transform: translate3d(-50%,0,0)
}
.defaultbox1{
background-color: #ff9800;
height: 5px;
width: 8px;
}
.monthCard {
z-index: 9999;
}
.monthCard .ant-fullcalendar-month-panel-cell{
width: 60px;
height: 30px;
text-align: center;
line-height: 30px;
}
.monthCard .ant-popover-inner-content{
width: 250px;
padding: 8px;
.ant-radio-group{
display: none;
}
.ant-fullcalendar{
border-top: none;
}
}
</style>
使用月份组件
<template>
<div>
<multi-month @update-month="monthChange" :default-month="months" />
</div>
<template>
<script>
import { ref, shallowRef, watch, nextTick, onMounted, inject,reactive ,computed,toRefs,getCurrentInstance,watchEffect} from 'vue'
import multiMonth from 'src/components/multiMonth/index'
export default {
name: "monthlyLedgerProduction",
components:{
multiMonth
},
setup(){
const state = reactive({
months:'',//默认值 :default-month
})
const monthChange = (timeListStr) =>{
console.log('月份',timeListStr)
}
return{
monthChange,
...toRefs(state)
}
}
}
</script>
如果想实现日期下方加黄色小圆点需求
添加 :allDataList=“allDataList”
<multi-month @update-month="monthChange" :default-month="months" :allDataList="allDataList"/>
//给 allDataList:[‘2019-01’,‘2019-02’,‘2019-03’,‘2019-04’,‘2019-05’,‘2019-06’,‘2019-07’,‘2019-08’] 赋值即可