因UI需求鸿蒙DatePicker不能取消循环问题,用TextPicker封装了一个显示年月日的时间控件。
import dayjs from "dayjs"
@Component
export struct CustomDatePicker {
@Prop startDate:Date
@Prop endDate:Date
@Link selectedDate:Date
@State generateYearMonth:TextCascadePickerRangeContent[] = []
@State nums:number[] = []
@State current:number[] = []
disappearTextStyle:PickerTextStyle = {font:{size:16},color:$r('app.color.color_666666')}
textStyle:PickerTextStyle = {font:{size:18},color:$r('app.color.color_333333')}
selectedTextStyle:PickerTextStyle = {font:{size:20},color:$r('app.color.color_000000')}
///正常一个月有基本固定的天
@State normal31Days:TextCascadePickerRangeContent[] = []
@State normal30Days:TextCascadePickerRangeContent[] = []
@State normal28Days:TextCascadePickerRangeContent[] = []
@State normal29Days:TextCascadePickerRangeContent[] = []
//平年、闰年
@State normalOneMoths:TextCascadePickerRangeContent[] = []
@State normalTwoMoths:TextCascadePickerRangeContent[] = []
//得到固定的月信息
getMonthsWithYear(year:number){
let daysInMonth = new Date(year,2,0).getDate()
let months : TextCascadePickerRangeContent[] = []
if (daysInMonth === 28) { //平年
if (this.normalOneMoths.length === 12) {
return this.normalOneMoths
}
}else { //闰年
if (this.normalTwoMoths.length === 12) {
return this.normalTwoMoths
}
}
for (let month = 1; month <= 12 ; month++) {
let days = this.getDaysWithMonth(year,month)
if (days.length>0) {
months.push({text:`${month.toString().padStart(2,'0')}月`,children:days})
}
}
if (daysInMonth === 28) { //平年
this.normalOneMoths = months
}else {
this.normalTwoMoths = months
}
return months
}
//得到固定的天
getDaysWithMonth(year:number,month:number){
let days : TextCascadePickerRangeContent[] = []
/// 计算每个月的天数
let daysInMonth = new Date(year,month,0).getDate()
if (daysInMonth === 31) {
if (this.normal31Days.length !== 31) {
for (let day = 1; day <= daysInMonth; day++) {
days.push({text:`${day.toString().padStart(2,'0')}日`})
}
this.normal31Days = days
}else {
days = this.normal31Days
}
}else if (daysInMonth === 30){
if (this.normal30Days.length !== 30) {
for (let day = 1; day <= daysInMonth; day++) {
days.push({text:`${day.toString().padStart(2,'0')}日`})
}
this.normal30Days = days
}else {
days = this.normal30Days
}
}else if (daysInMonth === 29){
if (this.normal29Days.length !== 30) {
for (let day = 1; day <= daysInMonth; day++) {
days.push({text:`${day.toString().padStart(2,'0')}日`})
}
this.normal29Days = days
}else {
days = this.normal29Days
}
}else if (daysInMonth === 28){
if (this.normal28Days.length !== 30) {
for (let day = 1; day <= daysInMonth; day++) {
days.push({text:`${day.toString().padStart(2,'0')}日`})
}
this.normal28Days = days
}else {
days = this.normal28Days
}
}else {
for (let day = 1; day <= daysInMonth; day++) {
days.push({text:`${day.toString().padStart(2,'0')}日`})
}
}
return days
}
generateYearMonthRange(start:Date,end:Date){
const range:TextCascadePickerRangeContent[] = []
let startYear = start.getFullYear()
let endYear = end.getFullYear()
let startMonth = start.getMonth() + 1
let endMonth = end.getMonth()+ 1
let startDay = start.getDate()
let endDay = end.getDate()
for (let year = startYear; year <= endYear; year++) {
let months : TextCascadePickerRangeContent[] = []
if (startYear === endYear){
for (let month = startMonth; month <= endMonth ; month++) {
let days : TextCascadePickerRangeContent[] = []
/// 计算每个月的天数
let daysInMonth = new Date(year,month,0).getDate()
if (startMonth === endMonth) {
for (let day = startDay; day <= endDay; day++) {
days.push({text:`${day.toString().padStart(2,'0')}日`})
}
}else if (month === startMonth) {
for (let day = startDay; day <= daysInMonth; day++) {
days.push({text:`${day.toString().padStart(2,'0')}日`})
}
}else if (month === endMonth) {
for (let day = 1; day <= endDay; day++) {
days.push({text:`${day.toString().padStart(2,'0')}日`})
}
}else {
days = this.getDaysWithMonth(year,month)
// for (let day = 1; day <= daysInMonth; day++) {
// days.push({text:`${day.toString().padStart(2,'0')}日`})
// }
}
if (days.length>0) {
months.push({text:`${month.toString().padStart(2,'0')}月`,children:days})
}
}
} else if (year === startYear) {
for (let month = startMonth; month <= 12 ; month++) {
let days : TextCascadePickerRangeContent[] = []
/// 计算每个月的天数
let daysInMonth = new Date(year,month,0).getDate()
if (month === startMonth) {
for (let day = startDay; day <= daysInMonth; day++) {
days.push({text:`${day.toString().padStart(2,'0')}日`})
}
}else {
days = this.getDaysWithMonth(year,month)
// for (let day = 1; day <= daysInMonth; day++) {
// days.push({text:`${day.toString().padStart(2,'0')}日`})
// }
}
if (days.length>0) {
months.push({text:`${month.toString().padStart(2,'0')}月`,children:days})
}
}
}else if (year === endYear){
for (let month = 1; month <= endMonth ; month++) {
let days : TextCascadePickerRangeContent[] = []
/// 计算每个月的天数
let daysInMonth = new Date(year,month,0).getDate()
if (month === endMonth) {
for (let day = 1; day <= endDay; day++) {
days.push({text:`${day.toString().padStart(2,'0')}日`})
}
}else {
days = this.getDaysWithMonth(year,month)
// for (let day = 1; day <= daysInMonth; day++) {
// days.push({text:`${day.toString().padStart(2,'0')}日`})
// }
}
if (days.length>0) {
months.push({text:`${month.toString().padStart(2,'0')}月`,children:days})
}
}
}else {
months = this.getMonthsWithYear(year)
}
if (months.length>0) {
range.push({
text:`${year}年`,
children:months
})
}
}
return range
}
aboutToAppear(): void {
this.generateYearMonth = this.generateYearMonthRange(this.startDate,this.endDate)
let selectedYear = this.selectedDate.getFullYear()
let selectedMonth = this.selectedDate.getMonth() +1
let selectedDay = this.selectedDate.getDate()
let nums:number[] = []
for (let index = 0; index < this.generateYearMonth.length; index++) {
const years = this.generateYearMonth[index];
if (years.text == `${selectedYear.toString()}年`) {
nums.push(index)
if (years.children) {
for (let index = 0; index < years.children.length; index++) {
const months = years.children[index];
if (months.text == `${selectedMonth.toString().padStart(2,'0')}月`) {
nums.push(index)
if (months.children) {
for (let index = 0; index < months.children.length; index++){
const days = months.children[index];
if (days.text == `${selectedDay.toString().padStart(2,'0')}日`) {
nums.push(index)
break
}
}
}
}
}
}
}
}
this.nums = nums
}
build() {
TextPicker({range:this.generateYearMonth,selected:this.nums})
.disappearTextStyle(this.disappearTextStyle)
.textStyle(this.textStyle)
.selectedTextStyle(this.selectedTextStyle)
.canLoop(false)
.onChange((value: string | string[], index: number | number[])=>{
if (typeof index === 'object') {
let year = index[0]
let month = index[1]
if (this.nums[0] !== year){
let currentYear = this.generateYearMonth[year]
if (!currentYear.children) return
if (currentYear.children.length <= this.nums[1]) {
let currentMonth = currentYear.children[currentYear.children.length-1]
if (!currentMonth.children) return
if (currentMonth.children.length <= this.nums[2]) {
this.nums = [year,currentYear.children.length-1,currentMonth.children.length-1]
}else {
this.nums = [year,currentYear.children.length-1,this.nums[2]]
}
}else {
let currentMonth = currentYear.children[this.nums[1]]
if (!currentMonth.children) return
if (currentMonth.children.length <= this.nums[2]) {
this.nums = [year,this.nums[1],currentMonth.children.length-1]
}else {
this.nums = [year,this.nums[1],this.nums[2]]
}
}
}
else if (this.nums[1]!== month){
let currentYear = this.generateYearMonth[year]
if (!currentYear.children) return
let currentMonth = currentYear.children[month]
if (!currentMonth.children) return
if (currentMonth.children.length <= this.nums[2]) {
this.nums = [this.nums[0],index[1],currentMonth.children.length-1]
}else {
this.nums = [this.nums[0],index[1],this.nums[2]]
}
}else if (this.nums[2] !== index[2]){
this.nums = [this.nums[0],this.nums[1],index[2]]
}
}
let year = this.generateYearMonth[this.nums[0]]
if (!year.children)return
let month = year.children[this.nums[1]]
if (!month.children)return
let day = month.children[this.nums[2]]
this.selectedDate = dayjs(`${(year.text as string).replace('年','')}${(month.text as string).replace('月','')}${(day.text as string).replace('日','')}`).toDate()//dayjs(`${year.text}${month.text}${day.text}`).toDate()
})
}
}