vue3+ant之实现月份多选组件

文章描述了一个Vue组件multiMonth.vue,它使用AntDesign的Calendar插件实现了一个可自定义月份选择器,同时包含动态添加和移除标签的功能,以及月份下方显示小圆点的需求。
该文章已生成可运行项目,

效果图:
在这里插入图片描述

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’] 赋值即可

在这里插入图片描述

本文章已经生成可运行项目
前端使用VueAnt Design实现且带颜色标签的功能,可按以下步骤操作。 ### 安装依赖 需确保项目中已安装VueAnt Design Vue。若未安装,可使用以下命令进行安装: ```bash npm install vue npm install ant-design-vue ``` ### 引入Ant Design Vue 在`main.js`(或入口文件)中引入并使用Ant Design Vue: ```javascript import { createApp } from &#39;vue&#39;; import App from &#39;./App.vue&#39;; import Antd from &#39;ant-design-vue&#39;; import &#39;ant-design-vue/dist/antd.css&#39;; const app = createApp(App); app.use(Antd); app.mount(&#39;#app&#39;); ``` ### 实现且带颜色标签的组件 以下是一个示例代码,展示如何在Vue组件实现且带颜色标签的功能: ```vue <template> <div> <a-checkbox-group v-model="selectedTags" @change="handleTagChange"> <a-tag v-for="tag in tags" :key="tag.id" :color="tag.color" :checked="selectedTags.includes(tag.id)" > {{ tag.name }} </a-tag> </a-checkbox-group> <p>中的标签: {{ selectedTags }}</p> </div> </template> <script> export default { data() { return { tags: [ { id: 1, name: &#39;标签1&#39;, color: &#39;blue&#39; }, { id: 2, name: &#39;标签2&#39;, color: &#39;green&#39; }, { id: 3, name: &#39;标签3&#39;, color: &#39;orange&#39; }, { id: 4, name: &#39;标签4&#39;, color: &#39;red&#39; }, ], selectedTags: [], }; }, methods: { handleTagChange(checkedValues) { this.selectedTags = checkedValues; }, }, }; </script> ``` 在上述代码中: 1. 使用`a-checkbox-group`和`a-tag`组件实现功能。 2. 通过`v-model`绑定`selectedTags`数组,用于存储中标签的`id`。 3. 为每个`a-tag`设置`color`属性,以显示不同颜色的标签。 4. 监听`a-checkbox-group`的`change`事件,在`handleTagChange`方法中更新`selectedTags`数组。 ### 运行项目 完成以上步骤后,运行项目即可看到可且带颜色标签的效果: ```bash npm run serve ```
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值