7 changed files with 6844 additions and 3052 deletions
File diff suppressed because it is too large
@ -0,0 +1,293 @@ |
|||||
|
<template> |
||||
|
<div class="date-picker"> |
||||
|
<div class="header"> |
||||
|
<div class="current-date year-selector" v-if="view === 'month'" > |
||||
|
<button><</button> |
||||
|
<span @click="getMonYear">{{ currentYear !== selectedYear ? selectedYear : currentYear }}</span> |
||||
|
<button>></button> |
||||
|
</div> |
||||
|
<div class="selectYear" v-if="view !== 'month'" > |
||||
|
<span class="year">{{view == 'monthTwo' ? '选择年份':'' }}</span> |
||||
|
</div> |
||||
|
<div class="controls"> |
||||
|
<button @click="toggleView('month')" :class="{ active: view !== 'year' }">月度</button> |
||||
|
<button @click="toggleView('year')" :class="{ active: view === 'year' }">年度</button> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div class="selector" v-if="view === 'month'"> |
||||
|
|
||||
|
<div class="month-grid"> |
||||
|
<button |
||||
|
v-for="month in months" |
||||
|
:key="month.value" |
||||
|
@click="selectMonth(month.value)" |
||||
|
:class="{ active: month.value === currentMonth && currentYear === selectedYear }" |
||||
|
> |
||||
|
{{ month.label }} |
||||
|
</button> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div class="selector" v-if="view !== 'month'"> |
||||
|
<div :class="[view == 'monthTwo' ? 'monthTwo-grid' :'','year-grid']"> |
||||
|
<button |
||||
|
v-for="year in visibleYears" |
||||
|
:key="year" |
||||
|
@click="selectYear(year)" |
||||
|
:class="{ |
||||
|
yearActive: year === currentYear, |
||||
|
current: year === new Date().getFullYear(), |
||||
|
}" |
||||
|
> |
||||
|
{{ year }} |
||||
|
</button> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
export default { |
||||
|
name: 'DatePicker', |
||||
|
props: { |
||||
|
modelValue: { |
||||
|
type: Date, |
||||
|
default: () => new Date() |
||||
|
}, |
||||
|
view:{ |
||||
|
type:String, |
||||
|
default:'month' |
||||
|
} |
||||
|
}, |
||||
|
data() { |
||||
|
return { |
||||
|
// view: 'month', // 'month' or 'year monthTwo' |
||||
|
selectedYear: this.modelValue.getFullYear(), |
||||
|
currentMonth: this.modelValue.getMonth() + 1, |
||||
|
currentYear: this.modelValue.getFullYear(), |
||||
|
decadeStart: Math.floor(this.modelValue.getFullYear() / 10) * 10, |
||||
|
months: [ |
||||
|
{ value: 1, label: '1月' }, |
||||
|
{ value: 2, label: '2月' }, |
||||
|
{ value: 3, label: '3月' }, |
||||
|
{ value: 4, label: '4月' }, |
||||
|
{ value: 5, label: '5月' }, |
||||
|
{ value: 6, label: '6月' }, |
||||
|
{ value: 7, label: '7月' }, |
||||
|
{ value: 8, label: '8月' }, |
||||
|
{ value: 9, label: '9月' }, |
||||
|
{ value: 10, label: '10月' }, |
||||
|
{ value: 11, label: '11月' }, |
||||
|
{ value: 12, label: '12月' } |
||||
|
] |
||||
|
}; |
||||
|
}, |
||||
|
computed: { |
||||
|
decadeEnd() { |
||||
|
return this.decadeStart + 9; |
||||
|
}, |
||||
|
visibleYears() { |
||||
|
const years = []; |
||||
|
for (let i = 0; i < 12; i++) { |
||||
|
years.push(this.decadeStart + i); |
||||
|
} |
||||
|
return years; |
||||
|
} |
||||
|
}, |
||||
|
mounted(){ |
||||
|
let selectedDate = new Date() |
||||
|
const oldDate = JSON.parse(localStorage.getItem('date')) |
||||
|
if(oldDate){ |
||||
|
selectedDate = new Date(oldDate) |
||||
|
this.currentMonth = selectedDate.getMonth() + 1; |
||||
|
this.currentYear = selectedDate.getFullYear(); |
||||
|
this.selectedYear = this.currentYear; |
||||
|
this.decadeStart = Math.floor(this.currentYear / 10) * 10; |
||||
|
}else{ |
||||
|
selectedDate = new Date() |
||||
|
} |
||||
|
}, |
||||
|
beforeUnmount() { |
||||
|
// 移除监听 |
||||
|
// this.$emit('update-count', 'month') |
||||
|
}, |
||||
|
destroyed(){ |
||||
|
this.$emit('update-count', 'month') |
||||
|
console.log('destroyed===='); |
||||
|
}, |
||||
|
methods: { |
||||
|
getMonYear(){ |
||||
|
this.$emit('update-count', 'monthTwo') |
||||
|
}, |
||||
|
toggleView(viewType) { |
||||
|
this.$emit('update-count', viewType) |
||||
|
|
||||
|
}, |
||||
|
selectMonth(month) { |
||||
|
this.currentMonth = month; |
||||
|
this.currentYear = this.selectedYear; |
||||
|
this.$emit('update-count', 'month') |
||||
|
this.emitDate(); |
||||
|
}, |
||||
|
selectYear(year) { |
||||
|
this.selectedYear = year; |
||||
|
this.currentYear = this.selectedYear; |
||||
|
if(this.view == 'monthTwo'){ |
||||
|
this.$emit('update-count', 'month') |
||||
|
} |
||||
|
this.emitDate(); |
||||
|
}, |
||||
|
prevYear() { |
||||
|
this.selectedYear--; |
||||
|
this.updateDecade(); |
||||
|
}, |
||||
|
nextYear() { |
||||
|
this.selectedYear++; |
||||
|
this.updateDecade(); |
||||
|
}, |
||||
|
prevDecade() { |
||||
|
this.decadeStart -= 10; |
||||
|
}, |
||||
|
nextDecade() { |
||||
|
this.decadeStart += 10; |
||||
|
}, |
||||
|
updateDecade() { |
||||
|
this.decadeStart = Math.floor(this.selectedYear / 10) * 10; |
||||
|
}, |
||||
|
emitDate() { |
||||
|
const selectedDate = new Date(this.currentYear, this.currentMonth - 1, 1); |
||||
|
this.$emit('update:modelValue', selectedDate); |
||||
|
this.$emit('change', selectedDate); |
||||
|
} |
||||
|
}, |
||||
|
watch: { |
||||
|
modelValue(newVal) { |
||||
|
let selectedDate = newVal |
||||
|
this.currentMonth = selectedDate.getMonth() + 1; |
||||
|
this.currentYear = selectedDate.getFullYear(); |
||||
|
this.selectedYear = this.currentYear; |
||||
|
this.decadeStart = Math.floor(this.currentYear / 10) * 10; |
||||
|
} |
||||
|
} |
||||
|
}; |
||||
|
</script> |
||||
|
|
||||
|
<style scoped> |
||||
|
.date-picker { |
||||
|
font-family: Microsoft YaHei UI; |
||||
|
width: 300px; |
||||
|
/* border: 1px solid #ddd; */ |
||||
|
border-radius: 4px; |
||||
|
padding: 10px 0 0 0; |
||||
|
/* box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1); */ |
||||
|
} |
||||
|
|
||||
|
.header { |
||||
|
display: flex; |
||||
|
justify-content: space-between; |
||||
|
align-items: center; |
||||
|
margin-bottom: 8px; |
||||
|
padding-bottom: 8px; |
||||
|
border-bottom: 1px solid #F1F2F5; |
||||
|
letter-spacing: 0.08em; |
||||
|
color: #626573; |
||||
|
|
||||
|
} |
||||
|
|
||||
|
.current-date { |
||||
|
font-weight: bold; |
||||
|
} |
||||
|
.selectYear{ |
||||
|
font-size: 14px; |
||||
|
font-weight: normal; |
||||
|
line-height: normal; |
||||
|
text-align: center; |
||||
|
letter-spacing: 0.08em; |
||||
|
color: #006AFF; |
||||
|
} |
||||
|
.controls{ |
||||
|
border-radius: 4px; |
||||
|
background: #EAECF0; |
||||
|
box-sizing: border-box; |
||||
|
border: 1px solid #EAECF0; |
||||
|
padding: 3px 6px; |
||||
|
} |
||||
|
|
||||
|
.selector{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
.controls button { |
||||
|
background: none; |
||||
|
border: none; |
||||
|
padding: 1px 12px; |
||||
|
cursor: pointer; |
||||
|
} |
||||
|
|
||||
|
.controls button.active { |
||||
|
background-color: #FFFFFF; |
||||
|
color: #006AFF; |
||||
|
/* border-color: #1890ff; */ |
||||
|
} |
||||
|
|
||||
|
.year-selector, .decade-selector { |
||||
|
display: flex; |
||||
|
justify-content: space-between; |
||||
|
align-items: center; |
||||
|
margin-bottom: 10px; |
||||
|
} |
||||
|
|
||||
|
.year-selector button, .decade-selector button { |
||||
|
background: none; |
||||
|
border: none; |
||||
|
cursor: pointer; |
||||
|
font-size: 16px; |
||||
|
} |
||||
|
.year-selector{ |
||||
|
margin-bottom: 0; |
||||
|
} |
||||
|
|
||||
|
.month-grid, .year-grid { |
||||
|
display: grid; |
||||
|
grid-template-columns: repeat(4, 1fr); |
||||
|
gap: 5px; |
||||
|
} |
||||
|
|
||||
|
.month-grid button, .year-grid button { |
||||
|
font-family: Microsoft YaHei UI; |
||||
|
padding: 8px; |
||||
|
border: none; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
width: 48px; |
||||
|
background: none; |
||||
|
cursor: pointer; |
||||
|
border-radius: 20px; |
||||
|
color: #1E2226; |
||||
|
box-sizing: border-box; |
||||
|
} |
||||
|
|
||||
|
.month-grid button:hover, .year-grid button:hover { |
||||
|
background-color: #F2F7FF; |
||||
|
} |
||||
|
|
||||
|
.month-grid button.active, .year-grid button.active,.year-grid button.yearActive{ |
||||
|
background-color: #006AFF; |
||||
|
color: white !important; |
||||
|
} |
||||
|
.monthTwo-grid button.current { |
||||
|
/* background-color: #006AFF !important; |
||||
|
color: white !important; |
||||
|
border-color: #1890ff !important; */ |
||||
|
color: #fff; |
||||
|
|
||||
|
} |
||||
|
.year-grid button.current{ |
||||
|
/* font-weight: bold; */ |
||||
|
color: #006AFF; |
||||
|
/* background-color: #F2F7FF; */ |
||||
|
/* border-color: #1890ff; */ |
||||
|
} |
||||
|
</style> |
Loading…
Reference in new issue