没想到啊,几年前写的组件现在居然还有人用,然后很多人给我说有问题,毕竟这么多年了,我这次又重新修改下,不要再骂我了
这是效果
因为项目需求,需要有半年的选项,所以弄了这么个跟el日期选择器差不多的半年选项,默认禁止未来时间,你们也可以自己改改
不支持多选
返回为时间段
如图返回为['2024-07-01','2024-12-31']
以下是组件代码
<template>
<div class="el-quarter-picker">
<el-popover v-model="visible" placement="bottom-start" transition="el-zoom-in-top" trigger="click">
<div class="content">
<p>
<button
type="button"
aria-label="前一年"
class="el-picker-panel__icon-btn el-date-picker__prev-btn el-icon-d-arrow-left"
@click="prev"
/>
<span role="button" class="span-year">{{ year }}年</span>
<button
type="button"
aria-label="后一年"
class="el-picker-panel__icon-btn el-date-picker__next-btn el-icon-d-arrow-right"
@click="next"
/>
</p>
<div class="choose-item">
<button :class="classStyle1" :disabled="disabled1" @click="selectHalfYear('上半年',disabled1)">上半年</button>
<button :class="classStyle2" :disabled="disabled2" @click="selectHalfYear('下半年',disabled2)">下半年</button>
</div>
</div>
<el-input slot="reference" v-model="text" :placeholder="'选择半年'" size="small" @change="iptchange">
<i slot="prefix" class="el-input__icon el-icon-date" />
</el-input>
</el-popover>
</div>
</template>
<script>
export default {
name: 'HalfYearPicker',
model: {
prop: 'value',
event: 'change'
},
props: {
// 返回值,数组,格式为['2020-01-01','2020-06-30']
// 如果有defaultValue,则默认[defaultValue,defaultValue]
value: {
type: Array,
default: () => []
},
// 传入默认值
// 格式为'2020-01-01'
defaultValue: {
type: String,
default: ''
},
// 禁止时间,数组
// 格式为['','2020-06-30'],1为开始时间,2为结束时间;
// 1为空,2有值,为禁止2时间之后
// 2为空,1有值,为禁止1时间之前
// 1有值,2有值,为禁止1、2时间之间
disabledDate: {
type: Array,
default: null
}
},
data() {
return {
visible: false,
text: '',
year: new Date().getFullYear(),
nowmonth: new Date().getMonth(),
nowyear: new Date().getFullYear(),
emitValue: [],
clickyear: '',
clickmonth: '',
disabled1: false, // 禁止,开始时间之前
disabled2: false // 禁止,开始时间之前
}
},
computed: {
classStyle1: function() {
return {
today: (this.nowyear === this.year) && (this.nowmonth < 6 || this.nowmonth) === 6,
clickcell: (this.year === this.clickyear) && (this.clickmonth === '上半年'),
selectMonth: true,
'is-disabled': this.disabled1
}
},
classStyle2: function() {
return {
today: (this.nowyear === this.year) && (this.nowmonth > 6),
clickcell: (this.year === this.clickyear) && (this.clickmonth === '下半年'),
selectMonth: true,
'is-disabled': this.disabled2
}
}
},
mounted() {
if (this.defaultValue) {
const time = this.defaultValue.split('-')
this.year = time[0]
this.clickyear = time[0]
this.clickmonth = time[1] < 7 ? '上半年' : '下半年'
this.text = this.clickyear + this.clickmonth
this.$emit('change', [this.defaultValue, this.defaultValue])
}
this.disabledDate && this.aviod(this.disabledDate)
},
methods: {
// 上一年
prev() {
this.year = this.year * 1 - 1
this.aviod(this.disabledDate)
},
// 下一年
next() {
this.year = this.year * 1 + 1
this.aviod(this.disabledDate)
},
// 点击选项事件
selectHalfYear(item, disabled) {
if (disabled) return
this.text = this.year + item
this.clickyear = this.year
this.clickmonth = item
if (item === '上半年') {
const data1 = this.year + '-01-01'
const data2 = this.year + '-06-30'
this.emitValue = [data1, data2]
} else {
const data1 = this.year + '-07-01'
const data2 = this.year + '-12-31'
this.emitValue = [data1, data2]
}
this.visible = false
this.$emit('change', this.emitValue)
},
// 自主输入判断
iptchange(val) {
if (val !== '') {
const year = val.slice(0, 4)
const text = val.slice(4, 8)
const reg = /^[0-9]{4}$/
if (reg.test(year)) {
if (text === '上半年' || text === '下半年') {
this.text = val
this.clickyear = year
this.clickmonth = text
this.year = year
const data1 = this.year + '-01-01'
const data2 = this.year + '-06-30'
this.emitValue = [data1, data2]
this.$emit('change', this.emitValue)
} else {
this.text = ''
}
} else {
this.text = ''
}
} else {
this.$emit('change', ['', ''])
}
},
// 禁止事件
aviod(disabledDate) {
if (!disabledDate) return
// 开始时间
let timeA = disabledDate[0].split('-').map(Number)
// 结束时间
let timeB = disabledDate[1].split('-').map(Number)
// 开始有值,结束有值,为禁止开始、结束时间之间(包括开始、结束)
if (disabledDate[0].length > 0 && disabledDate[1].length > 0) {
// 如果开始年大于结束年,交换位置
if (timeA[0] > timeB[0]) {
const c = timeA
timeA = timeB
timeB = c
}
// 一系列条件判断
// 1.年份不在区间内,都不禁止
if ((timeA[0] > this.year) || (timeB[0] < this.year)) {
this.disabled1 = false
this.disabled2 = false
}
// 2.开始小于当前
if (timeA[0] < this.year) {
// 2.1正常区间内
if (timeB[0] > this.year) {
this.disabled1 = true
this.disabled2 = true
}
// 2.2结束年等于当前年
if (timeB[0] === this.year) {
this.disabled1 = true
this.disabled2 = timeB[1] >= 6
}
}
// 3.开始年等于当前年
if (timeA[0] === this.year) {
// 3.1结束大于当前
if (timeB[0] > this.year) {
this.disabled1 = timeA[1] < 7
this.disabled2 = true
}
// 3.2两个年份相同
if (timeB[0] === this.year) {
// 开始月份大于结束月份,交换位置
if (timeA[1] > timeB[2]) {
const c = timeA
timeA = timeB
timeB = c
}
this.disabled1 = timeA[1] < 7
this.disabled2 = timeB[1] >= 6
}
}
}
// 开始无值,结束有值,为禁止结束时间之后(包括结束)
if (disabledDate[0].length === 0 && disabledDate[1].length > 0) {
if (timeB[0] < this.year) {
this.disabled1 = true
this.disabled2 = true
} else if (timeB[0] === this.year) {
this.disabled1 = timeB[1] <= 6
this.disabled2 = true
} else {
this.disabled1 = false
this.disabled2 = false
}
}
// 开始有值,结束无值,为禁止开始时间之前(包括开始)
if (disabledDate[1].length === 0 && disabledDate[0].length > 0) {
if (timeA[0] < this.year) {
this.disabled1 = false
this.disabled2 = false
} else if (timeA[0] === this.year) {
this.disabled1 = timeB[1] <= 6
this.disabled2 = false
} else {
this.disabled1 = true
this.disabled2 = true
}
}
}
}
}
</script>
<style lang="scss" scoped>
.content {
width: 220px;
min-width: 220px;
p {
display: flex;
align-items: center;
justify-content: space-between;
border-bottom: solid 1px #ebeef5;
padding-bottom: 12px;
font-size: 16px;
button {
margin-top: 0;
}
}
.choose-item {
display: flex;
justify-content: space-around;
.selectMonth {
margin: 14px 10px;
font-size: 12px;
background: transparent;
border: none;
}
.selectMonth:hover {
color: #409eff;
cursor: pointer;
}
.today {
color: #409eff;
font-weight: 700;
}
.clickcell {
color: #409eff;
}
.is-disabled {
color: #c0c4cc !important;
cursor: not-allowed !important;
background-color: #fff;
border-color: #ebeef5;
}
}
}
</style>
页面引用
首先import一下组件,然后直接引用就是
<halfYear v-model="date" default-value="2029-01-01" :disabled-date="['2028-01-01', '2028-01-01']" />
参数
代码里面会有详细备注,这里就写个大概
参数名 | 默认 | 格式 | 例子 | 说明 |
---|---|---|---|---|
value | [] | Array | [‘2020-01-01’,‘2020-06-30’] | v-model双向绑定值,父组件默认写[] |
defaultValue | “” | String | “2029-01-01” | 组件默认选中值 |
disabled-date | null | Array | [‘2028-01-01’, ‘2028-01-01’] | 禁止点击时间 |
注:输入框输入的时候不写日期,直接写年
+上半年/下半年
,比如2024上半年
,就会选中2024上半年