antdV 时间选择器没有年?没有半年?没有季度?这里有!

58 阅读1分钟

选择器是基于form 表单场景实现

PixPin_2025-07-23_18-04-48.gif
// template 代码片段
<a-date-picker
  v-decorator="['year']"
  format="YYYY"
  mode="year"
  placeholder="请选择年"
  :open="yearPickerOpen"
  @openChange="(status) => (yearPickerOpen = status)"
  @panelChange="yearPickpanelChange"
/>

// methods 代码片段
yearPickpanelChange(val) {
  this.form.setFieldsValue({ year: val.format('YYYY') })
  this.yearPickerOpen = false
},
// template 代码片段
<a-month-picker
  dropdownClassName="selfPicker"
  v-decorator="['halfYear']"
  valueFormat="YYYY-MM"
  placeholder="请选择"
>
  <a-input :value="halfYearRender()" />
  <template slot="monthCellContentRender" slot-scope="date">
    <div
      :class="{
        select: halfYearRangeStyle(date),
      }"
    >
      {{ chineseNumbers[date.month()] }}月
    </div>
  </template>
</a-month-picker>

// methods 代码片段
halfYearRender() {
  try {
    const { year, isFirstHalf } = halfYearTool(this)
    return `${year}${isFirstHalf ? '上' : '下'}`
  } catch (e) {
    console.error('halfYearRender error:', e)
    return ''
  }
},

halfYearRangeStyle(curDate) {
  try {
    const { year, isFirstHalf } = halfYearTool(this)
    const month = curDate.month() + 1
    const inSelectRange = isFirstHalf ? month <= 6 : month > 6
    return year == curDate.year() && inSelectRange
  } catch (e) {
    console.error('halfYearRangeStyle error:', e)
    return ''
  }
}


/*半年工具函数*/
export const halfYearTool = (target) => {
  const val = target.form.getFieldValue('halfYear')
  if (!val) {
    throw new Error('无需处理')
  }
  // eslint-disable-next-line no-unused-vars
  const [year, month] = val.split('-')
  const isFirstHalf = month <= 6
  return { year, month, isFirstHalf }
}

//style 
<style lang="less">
.selfPicker {
  .ant-calendar-month-panel-selected-cell .ant-calendar-month-panel-month {
    background: #e6f3ff;
    color: rgba(0, 0, 0, 0.65);
  }
  .ant-calendar-month-panel-cell:has(> a > div.select) {
    background: #e6f3ff;
  }

  .ant-calendar-year-panel-body {
    flex: none;
  }
}
</style>
<a-month-picker
  dropdownClassName="selfPicker"
  v-decorator="['quarter']"
  valueFormat="YYYY-MM"
  placeholder="请选择"
>
  <a-input :value="quarterRender()" />
  <template slot="monthCellContentRender" slot-scope="date">
    <div
      :class="{
        select: quarterRangeStyle(date),
      }"
    >
      {{ chineseNumbers[date.month()] }}月
    </div>
  </template>
</a-month-picker>

// methods
quarterRender() {
  const val = this.form.getFieldValue('quarter')
  if (!val) return
  const parsed = parseQuarter(val)
  if (!parsed) return
  return `${parsed.year}${getQuarterText(parsed.quarter)}`
},

quarterRangeStyle(curDate) {
  const val = this.form.getFieldValue('quarter')
  const parsed = parseQuarter(val)
  if (!parsed) return
  const { year, quarter } = parsed
  const monthsInQuarter = [quarter * 3 - 2, quarter * 3 - 1, quarter * 3]
  const inSelectRange = monthsInQuarter.includes(curDate.month() + 1)
  return year == curDate.year() && inSelectRange
}


/**
 * 季度工具函数
 * @param {*}
 * @returns  { year, quarter }
 */

export const parseQuarter = (val) => {
  if (!val) return null
  const [year, month] = val.split('-').map(Number)
  if (!year || !month) return null
  const quarter = Math.ceil(month / 3)
  return { year, quarter }
}

// 获取季度中文名
export const getQuarterText = (quarter) => {
  const quarterNames = ['Q1', 'Q2', 'Q3', 'Q4']
  return quarterNames[quarter - 1] || ''
}

//style 
<style lang="less">
.selfPicker {
  .ant-calendar-month-panel-selected-cell .ant-calendar-month-panel-month {
    background: #e6f3ff;
    color: rgba(0, 0, 0, 0.65);
  }
  .ant-calendar-month-panel-cell:has(> a > div.select) {
    background: #e6f3ff;
  }

  .ant-calendar-year-panel-body {
    flex: none;
  }
}
</style>