vue3+ant design vue3+ts 日期选择框DatePicker预设常用的日期范围封装自用

文章详细描述了一个Vue组件,展示了如何使用AntDesign的range-picker组件创建一个可定制的时间选择器,包括范围选择、自定义样式和事件处理。组件允许用户快速选择日期范围,并支持自定义按钮和日期格式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、组件代码如下:

<template>
  <div class="time_pink_box" :class="{ 'activebox': isClicks }">
    <div class="lefts" v-if="isClicks" @click="pickerShow = !pickerShow">
      <SvgIcon name="calendar" width="18px" height="18px" />
      <span class="init_dayes" style="margin-right: 12px">{{ isClickname }}</span>
      <span></span>
    </div>
    <div>
      <a-range-picker :open="pickerShow" show-time dropdownClassName="range-picker-custom new_dropdownClassName_pinkes"
        :format="dateFormat" @change="handTime" v-model:value="value2" ref="range" :allowClear="allowClear"
        :bordered="false" @click="pickerShow = !pickerShow" @calendarChange="calendarPicker">

        <template #renderExtraFooter>
          <div class="extra_box">
            <div class="title">快速选择</div>
            <div class="list">
              <div class="list-item" :class="{ 'successItem': index == successValue }"
                @click="changeTime(item.value, item.type, index, item)" v-for="(item, index) in itemList"
                style="color: black">{{
                  item.label
                }}</div>
            </div>
          </div>
        </template>
        <!--       自定义样式-->
        <!--       <template #dateRender="{ current }">-->
        <!--         <div class="ant-picker-cell-inner" :style="getCurrentStyle(current)">-->
        <!--           {{ current.date() }}-->
        <!--         </div>-->
        <!--       </template>-->
        <!--       自定义图标-->
        <template #suffixIcon>
          <span>
            <SvgIcon v-if="isIcones" name="gxtDataPinkes" width="22px" height="22px" />
          </span>
        </template>
      </a-range-picker>
    </div>
  </div>
</template>

<script lang="ts" >
import dayjs, { Dayjs } from 'dayjs';
import { ref, watch } from 'vue';
export default {
  name: "Time",
  props: {
    defaultTime: {
      type: Array,
      require: true
    },
    allowClear: {
      type: Boolean,
      default: false
    }
  },
  setup(props, { emit }) {
    // const dateFormat = ['YYYY/MM/DD HH:mm:ss','YYYY/MM/DD HH:mm:ss'];
    const pickerShow = ref(false);
    const dateFormat = 'YYYY-MM-DD HH:mm:ss';
    const successValue = ref(null)
    const range = ref()
    const value2 = ref(props.defaultTime)
    watch(
      () => props.defaultTime,
      (val) => {
        value2.value = props.defaultTime
        successValue.value = null
      }, {
      deep: true
    }
    )
    const isClicks = ref(true)
    const spacedata = new Date(props.defaultTime[1]) - new Date(props.defaultTime[0])

    const isClickname = ref('今天')
    const isIcones = ref(false)
    const resetTime = (type) => {
      isClickname.value = '今天';
      isClicks.value = true;
      if (type == 'empty') {
        successValue.value = null;
        value2.value = []
      }
    }
    const changeTime = (value, type, index, item) => {
      console.log(value, type);
      successValue.value = index
      isClickname.value = item.label
      if (value) {
        value2.value = [
          dayjs().subtract(value, type), dayjs()
        ]

      } else if (type == 'day') {
        value2.value = [
          dayjs().subtract(1, 'day').startOf(type), dayjs().subtract(1, 'day').endOf(type)
        ]
      } else if (type == 'week') {
        // value2.value = [
        //   dayjs().startOf(type).subtract(6, 'day'), dayjs()
        // ]
        // value2.value = [dayjs().startOf('week').add(1, 'day'), dayjs().endOf('week').add(1, 'day')]
        value2.value = [dayjs().subtract(dayjs().day() ? dayjs().day() - 1 : 6, "day").startOf('date'), dayjs().add(dayjs().day() ? 7 - dayjs().day() : dayjs().day(), "day").endOf('date')]
      } else if (type == 'month') {
        value2.value = [
          dayjs().startOf('month'), dayjs().endOf('month')
        ]
      } else {
        value2.value = [
          dayjs().startOf(type), dayjs().endOf(type)
        ]
      }

      range.value.blur()
      isClicks.value = true
      isIcones.value = false;
      pickerShow.value = !pickerShow.value;
      emit("changcilck", [dayjs(value2.value[0]).format(dateFormat), dayjs(value2.value[1]).format(dateFormat)])
    }
    const calendarPicker = (dates: [dayjs, dayjs] | [string, string], dateStrings: [string, string], info: { range: start | end }) => {

      if (info.range == 'end') {
        pickerShow.value = false;
      }
    }
    const handTime = (dataString: string) => {
      successValue.value = null
      isClicks.value = false
      isIcones.value = true
      emit("changes", dataString)
      // pickerShow.value = !pickerShow.value;
    }
    const disabledDate = (current: Dayjs) => {
      return current && current > dayjs()
    };
    const itemList = [
      {
        label: "今天",
        type: 'date'
      },
      {
        label: "过去10分钟",
        value: "10",
        type: "minute"
      }, {
        label: "昨日",
        type: "day"
      },
      {
        label: "过去30分钟",
        value: "30",
        type: "minute"
      },
      {
        label: "本周",
        type: "week"
      },
      {
        label: "过去1小时",
        value: "1",
        type: "hour"
      },
      {
        label: "本月",
        type: "month"
      },
      {
        label: "过去3小时",
        value: "3",
        type: "hour"
      },
      {
        label: "过去30天",
        value: "30",
        type: "day"
      },
      {
        label: "过去6小时",
        value: "6",
        type: "hour"
      },
      {
        label: "过去60天",
        value: "60",
        type: "day"
      },
      {
        label: "过去12小时",
        value: "12",
        type: "hour"
      },

    ]
    return {
      pickerShow,
      resetTime,
      handTime,
      range,
      changeTime,
      dateFormat,
      isClicks,
      isIcones,
      isClickname,
      itemList,
      calendarPicker,
      disabledDate,
      value2,
      successValue,
    }
  }
}

</script>
<style scoped lang="less">
:deep(.ant-picker-suffix) {
  width: 10px;

  span {
    position: absolute;
    right: 7px;
    top: 50%;
    transform: translateY(-53%);
  }
}

//:deep(.ant-picker){
//  width: 420px!important;
//}
//:deep(.ant-picker-range){
//  width: 420px!important;
//}
.time_pink_box {
  display: flex;
  align-items: center;
  border: 1px solid #d9d9d9;

  //padding-left: 12px;
  //border-right: 1px;
  .lefts {
    display: flex;
    align-items: center;
    font-size: 14px;
    font-family: HelveticaNeue;
    color: rgba(0, 0, 0, 0.85);

    span {
      &:nth-of-type(1) {
        letter-spacing: 1px;
        white-space: nowrap;
      }

      &:nth-of-type(2) {
        width: 1px;
        height: 13px;
        background: rgba(0, 0, 0, 0.85);
        //border: 0.5px solid  rgba(0,0,0,0.85);
      }
    }

    .init_dayes {
      padding-top: 2px;
      margin-left: 12px;
    }
  }
}

.activebox {
  padding-left: 12px;
}

:deep(.ant-picker) {
  position: relative;
  padding-right: 0px;

  //padding-left: 0px;
  .ant-picker-input {
    &:nth-of-type(1) {
      //margin-left: 90px;
    }
  }
}

.timews {
  position: absolute;
  display: flex;
  align-items: center;
  left: 17px;
  top: 50%;
  transform: translateY(-50%);
  font-size: 14px;
  font-family: HelveticaNeue;
  color: rgba(0, 0, 0, 0.85);
}

/*.new_dropdownClassName_pinkes{*/
/*  width: 420px!important;*/
/*}*/
.time_pink_box :deep(.ant-picker-cell-in-view.ant-picker-cell-in-range::before) {
  background: none !important;
}

.time_pink_box :deep(.ant-picker-panel-container) {
  border-bottom-left-radius: 0px;
}

.range-picker-custom .ant-picker-footer-extra .extra_box {
  position: absolute !important;
  top: 7px;
  left: -207px;
  background: #fff;
  width: 207px;
  height: calc(100% - 13px);
  /* height: 314px; */
  padding: 9px 8px 28px 15px;
  box-shadow: -8px 5px 10px -1px rgb(0 0 0 / 12%);
  border-bottom-right-radius: 0px;
  border-bottom-left-radius: 2px;
  border-top-left-radius: 2px;
}

.range-picker-custom .ant-picker-footer .ant-picker-ranges {
  line-height: unset !important;
  padding: 3px 12px;
}

.title {
  font-size: 14px;
  font-weight: 600;
  color: rgba(0, 0, 0, 0.85);
}

.list {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
}

.list-item {
  width: 88px;
  height: 28px;
  background: #FAFAFA;
  line-height: 28px;
  text-align: center;
  border-radius: 2px;
  margin-bottom: 12px;
  font-size: 12px;
  font-weight: 400;
  color: rgba(0, 0, 0, 0.85);
  cursor: pointer;
}

.successItem {
  background: #03985A;
  color: #FFFFFF !important;
}
</style>

2、父组件中使用

<template>
<date-picker @changcilck="changeOriginTime" @changes="changeOriginTime" :defaultTime="timeValue"
            ref="originTimePickerRef" :allowClear="true"></date-picker>
</template>
<script lang="ts" setup>
import dayjs, { Dayjs } from 'dayjs'
import { ref, watch } from 'vue'
const originTimePickerRef=ref();
const timeValue = ref<[Dayjs, Dayjs]>([dayjs().startOf('date'), dayjs().endOf('date')]);//日期组件 默认显示今天
const startTransDate=ref(null);//页面所需开始日期时间
const endTransDate=ref(null);//页面所需结束日期时间
const changeOriginTime = (timeString) => {
  if (timeString && timeString.length > 0) {
    startTransDate.value = dayjs(timeString[0]).format('YYYY-MM-DD HH:mm:ss')
    endTransDate.value = dayjs(timeString[1]).format('YYYY-MM-DD HH:mm:ss')
  } else {
    startTransDate.value = ''
    endTransDate.value = ''
  }
}

//originTimePickerRef.value.resetTime()//组件选择的日期时间设置成今天
//originTimePickerRef.value.resetTime('empty')//组件选择的日期时间设置为空
</script>

3、效果如图
时间组件效果图

### 自定义 Ant Design RangePicker 的日期渲染方法 在 Ant Design Vue 中,`RangePicker` 是基于 `DatePicker` 实现的一个范围选择组件。通过其内置的 `dateRender` 属性,可以自定义日期单元格的内容和样式[^1]。 以下是实现自定义 `dateRender` 方法的具体方式: #### 示例代码 ```vue <template> <a-range-picker :date-render="customDateRender" /> </template> <script> export default { methods: { customDateRender(current) { const style = {}; if (current && current.date() === 1) { // 如果当前日期是每月的第一天 style.border = &#39;1px solid #ff0000&#39;; // 设置边颜色为红色 style.borderRadius = &#39;50%&#39;; // 圆形显示 } return ( <div style={style} class="custom-date"> {current.date()} {/* 显示日期 */} </div> ); }, }, }; </script> <style scoped> .custom-date { width: 20px; height: 20px; line-height: 20px; text-align: center; } </style> ``` 上述代码实现了以下功能: - 当前月份中的每一天都可以被单独定制。 - 特定条件下的日期(如每个月第一天)会应用特殊的样式[^2]。 --- #### 关键点解析 1. **`dateRender` 函数的作用** - 它接收一个参数 `current`,表示当前遍历到的日期对象。 - 返回值是一个 React 节点或者 Vue 渲染函数的结果,用于替换默认的日期单元格内容[^3]。 2. **动态样式的控制** - 可以根据业务逻辑动态调整每个日期单元格的样式,例如高亮特定日期、标记节假日等[^4]。 3. **注意事项** - 确保返回的是合法的 DOM 结构或虚拟节点。 - 如果需要更复杂的交互行为,可以在 `dateRender` 中嵌套事件监听或其他子组件。 --- ###
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值