|
@@ -1,42 +1,62 @@
|
|
|
-import { BasicType, DateInfo } from "../../models";
|
|
|
|
|
|
|
+import { DateInfo } from "../../models";
|
|
|
|
|
|
|
|
@Component
|
|
@Component
|
|
|
@CustomDialog
|
|
@CustomDialog
|
|
|
export struct YTCalendarPicker {
|
|
export struct YTCalendarPicker {
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 外部传入
|
|
|
|
|
+ */
|
|
|
|
|
+ // 主题色
|
|
|
|
|
+ linearInfo: LinearGradientOptions = { colors: [['#B9FD2A', 0.01], ['#F5FD6D', 1]], angle: 110 }
|
|
|
|
|
+
|
|
|
|
|
+ // 边距
|
|
|
|
|
+ cPadding: Padding | Length | LocalizedPadding = { left: 0, right: 0, top: 20, bottom: 4 }
|
|
|
|
|
+
|
|
|
|
|
+ // yyyy-mm-dd 格式的数组, 符合数组内格式的日期下会有标记
|
|
|
|
|
+ dateList: string[] = []
|
|
|
|
|
+
|
|
|
|
|
+ // 取消
|
|
|
|
|
+ onCancel: () => void = () => {}
|
|
|
|
|
+
|
|
|
|
|
+ // 确定
|
|
|
|
|
+ onConfirm: (date: Date) => void = () => {}
|
|
|
|
|
+
|
|
|
|
|
+ // 点击某一天的回调
|
|
|
|
|
+ onClickItem: (date: Date) => void = () => {}
|
|
|
|
|
+
|
|
|
|
|
+ // 是否显示头部标题
|
|
|
|
|
+ showTitle: boolean = true
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 内部方法
|
|
|
|
|
+ */
|
|
|
|
|
+
|
|
|
// 年月
|
|
// 年月
|
|
|
- @State year: number = 2025;
|
|
|
|
|
- @State month: number = 8;
|
|
|
|
|
|
|
+ @State year: number = new Date().getFullYear();
|
|
|
|
|
+ @State month: number = new Date().getMonth() + 1;
|
|
|
|
|
+
|
|
|
// 开始是星期几
|
|
// 开始是星期几
|
|
|
- @State weekStart: number = 1;
|
|
|
|
|
|
|
+ @State private weekStart: number = 1;
|
|
|
// 本月的天数
|
|
// 本月的天数
|
|
|
- @State daysInMonth: number = 31;
|
|
|
|
|
|
|
+ @State private daysInMonth: number = 31;
|
|
|
// 渲染用的月份数组
|
|
// 渲染用的月份数组
|
|
|
- @State monthArray: DateInfo[] = [];
|
|
|
|
|
- @State showDatePickerMenu: boolean = false
|
|
|
|
|
- @State selectDay: Date = new Date()
|
|
|
|
|
|
|
+ @State private monthArray: DateInfo[] = [];
|
|
|
|
|
+ // 当前选中的日期
|
|
|
|
|
+ @State private selectDay: Date = new Date()
|
|
|
|
|
+ // 显示选择日期的菜单
|
|
|
|
|
+ @State private showDatePickerMenu: boolean = false
|
|
|
|
|
+
|
|
|
|
|
+ // 弹窗控制器 -
|
|
|
|
|
+ diaLogControl?: CustomDialogController
|
|
|
|
|
+ // 星期中文映射表
|
|
|
|
|
+ private readonly WEEK_MAP = ['日', '一', '二', '三', '四', '五', '六'];
|
|
|
|
|
+ // 日期选择器的范围
|
|
|
private declare range: TextCascadePickerRangeContent[]
|
|
private declare range: TextCascadePickerRangeContent[]
|
|
|
- private years =
|
|
|
|
|
- Array.from<number, number>({ length: new Date().getFullYear() - 1970 + 1 }, (_: number, i: number) => 1970 + i)
|
|
|
|
|
|
|
+ // 年份 - 日期选择器使用
|
|
|
|
|
+ private years = Array.from<number, number>({ length: new Date().getFullYear() - 1970 + 1 }, (_: number, i: number) => 1970 + i)
|
|
|
//当前年月选择的下标
|
|
//当前年月选择的下标
|
|
|
private selectedIndex: number[] = [new Date().getFullYear() - 1970, new Date().getMonth()]
|
|
private selectedIndex: number[] = [new Date().getFullYear() - 1970, new Date().getMonth()]
|
|
|
- private linearInfo: LinearGradientOptions = {
|
|
|
|
|
- colors: [['#B9FD2A', 0.01], ['#F5FD6D', 1]],
|
|
|
|
|
- angle: 110
|
|
|
|
|
- }
|
|
|
|
|
- // 星期中文映射表
|
|
|
|
|
- private readonly WEEK_MAP = ['日', '一', '二', '三', '四', '五', '六'];
|
|
|
|
|
- // 取消
|
|
|
|
|
- onCancel: () => void = () => {
|
|
|
|
|
- }
|
|
|
|
|
- // 确定
|
|
|
|
|
- onConfirm: (date: Date) => void = () => {
|
|
|
|
|
- }
|
|
|
|
|
- // 右上角的结构
|
|
|
|
|
- @BuilderParam rightTopBuild: () => void = this.buttonRow;
|
|
|
|
|
- // yy-mm-dd 格式的数组, 符合数组内格式的日期下会有标记
|
|
|
|
|
- @Require dateList: string[] = []
|
|
|
|
|
|
|
|
|
|
- diaLogControl?: CustomDialogController
|
|
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* 回调
|
|
* 回调
|
|
@@ -60,6 +80,14 @@ export struct YTCalendarPicker {
|
|
|
// 点击单个日期
|
|
// 点击单个日期
|
|
|
clickItem(item: DateInfo){
|
|
clickItem(item: DateInfo){
|
|
|
this.selectDay = item.id
|
|
this.selectDay = item.id
|
|
|
|
|
+ this.onClickItem(this.selectDay)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 更改日期选择器的显示和隐藏
|
|
|
|
|
+ changeDatePickerMenu(show: boolean) {
|
|
|
|
|
+ animateToImmediately({ duration: 200 }, () => {
|
|
|
|
|
+ this.showDatePickerMenu = show
|
|
|
|
|
+ })
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -167,7 +195,7 @@ export struct YTCalendarPicker {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
aboutToAppear(): void {
|
|
aboutToAppear(): void {
|
|
|
- this.changeMonth(2025, 8);
|
|
|
|
|
|
|
+ this.changeMonth(this.year, this.month);
|
|
|
|
|
|
|
|
const monthsRange =
|
|
const monthsRange =
|
|
|
Array.from<number, number>({ length: 12 }, (_: number, i: number) => 1 + i).map(month => {
|
|
Array.from<number, number>({ length: 12 }, (_: number, i: number) => 1 + i).map(month => {
|
|
@@ -181,41 +209,50 @@ export struct YTCalendarPicker {
|
|
|
build() {
|
|
build() {
|
|
|
Column({ space: 20 }) {
|
|
Column({ space: 20 }) {
|
|
|
// 月份切换和头部组件
|
|
// 月份切换和头部组件
|
|
|
- Row() {
|
|
|
|
|
- // 月份切换
|
|
|
|
|
- Row({ space: 8 }) {
|
|
|
|
|
- Text(`${this.year}-${this.month.toString().padStart(2, '0')}`)
|
|
|
|
|
- .fontSize(16)
|
|
|
|
|
- .fontWeight(600)
|
|
|
|
|
-
|
|
|
|
|
- Image($r('app.media.ic_back'))
|
|
|
|
|
- .width(14)
|
|
|
|
|
- .height(8)
|
|
|
|
|
|
|
+ if(this.showTitle) {
|
|
|
|
|
+ Row() {
|
|
|
|
|
+ // 月份切换
|
|
|
|
|
+ Row({ space: 8 }) {
|
|
|
|
|
+ Text(`${this.year}-${this.month.toString().padStart(2, '0')}`)
|
|
|
|
|
+ .fontSize(16)
|
|
|
|
|
+ .fontWeight(600)
|
|
|
|
|
+ .fontColor(Color.Black)
|
|
|
|
|
+
|
|
|
|
|
+ Image($r('app.media.ic_back'))
|
|
|
|
|
+ .width(14)
|
|
|
|
|
+ .height(8)
|
|
|
|
|
+ .rotate({angle: this.showDatePickerMenu ? 90 : 270})
|
|
|
|
|
+ }
|
|
|
|
|
+ .onClick(() => {
|
|
|
|
|
+ this.changeDatePickerMenu(true)
|
|
|
|
|
+ })
|
|
|
|
|
+ .bindMenu(this.showDatePickerMenu, this.dateSelectMenu, {
|
|
|
|
|
+ onDisappear: () => {
|
|
|
|
|
+ this.changeDatePickerMenu(false)
|
|
|
|
|
+ this.year = this.range[this.selectedIndex[0]].text.valueOf() as number
|
|
|
|
|
+ this.month = this.range[this.selectedIndex[0]].children![this.selectedIndex[1]].text.valueOf() as number
|
|
|
|
|
+ this.changeMonth(this.year, this.month)
|
|
|
|
|
+ },
|
|
|
|
|
+ placement: Placement.Bottom
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ // 右上角的结构
|
|
|
|
|
+ this.buttonRow()
|
|
|
}
|
|
}
|
|
|
- .onClick(() => {
|
|
|
|
|
- this.showDatePickerMenu = true
|
|
|
|
|
- })
|
|
|
|
|
- .bindMenu(this.showDatePickerMenu, this.dateSelectMenu, {
|
|
|
|
|
- onDisappear: () => {
|
|
|
|
|
- this.showDatePickerMenu = false
|
|
|
|
|
- this.year = this.range[this.selectedIndex[0]].text.valueOf() as number
|
|
|
|
|
- this.month = this.range[this.selectedIndex[0]].children![this.selectedIndex[1]].text.valueOf() as number
|
|
|
|
|
- this.changeMonth(this.year, this.month)
|
|
|
|
|
- },
|
|
|
|
|
- placement: Placement.Bottom
|
|
|
|
|
- })
|
|
|
|
|
-
|
|
|
|
|
- // 右上角的结构
|
|
|
|
|
- this.rightTopBuild()
|
|
|
|
|
|
|
+ .width("100%")
|
|
|
|
|
+ .alignItems(VerticalAlign.Center)
|
|
|
|
|
+ .justifyContent(FlexAlign.SpaceBetween)
|
|
|
}
|
|
}
|
|
|
- .width("100%")
|
|
|
|
|
- .alignItems(VerticalAlign.Center)
|
|
|
|
|
- .justifyContent(FlexAlign.SpaceBetween)
|
|
|
|
|
|
|
|
|
|
// 周 title 的显示
|
|
// 周 title 的显示
|
|
|
Row() {
|
|
Row() {
|
|
|
ForEach(this.WEEK_MAP, (item: string, index: number) => {
|
|
ForEach(this.WEEK_MAP, (item: string, index: number) => {
|
|
|
- Text(item)
|
|
|
|
|
|
|
+ Row(){
|
|
|
|
|
+ Text(item)
|
|
|
|
|
+ .fontColor(Color.Black)
|
|
|
|
|
+ }
|
|
|
|
|
+ .layoutWeight(1)
|
|
|
|
|
+ .justifyContent(FlexAlign.Center)
|
|
|
})
|
|
})
|
|
|
}
|
|
}
|
|
|
.width("100%")
|
|
.width("100%")
|
|
@@ -225,7 +262,7 @@ export struct YTCalendarPicker {
|
|
|
Grid() {
|
|
Grid() {
|
|
|
ForEach(this.monthArray, (item: DateInfo, index: number) => {
|
|
ForEach(this.monthArray, (item: DateInfo, index: number) => {
|
|
|
GridItem() {
|
|
GridItem() {
|
|
|
- Column({ space: 3 }) {
|
|
|
|
|
|
|
+ Column({ space: 5 }) {
|
|
|
if (item.id) {
|
|
if (item.id) {
|
|
|
// 日历-单个日期的组件
|
|
// 日历-单个日期的组件
|
|
|
Row() {
|
|
Row() {
|
|
@@ -233,14 +270,14 @@ export struct YTCalendarPicker {
|
|
|
.fontSize(12)
|
|
.fontSize(12)
|
|
|
.fontColor(this.isSameDay(item.id, this.selectDay) ? Color.Black : '#979797')
|
|
.fontColor(this.isSameDay(item.id, this.selectDay) ? Color.Black : '#979797')
|
|
|
}
|
|
}
|
|
|
- .width(32)
|
|
|
|
|
|
|
+ .width("100%")
|
|
|
.aspectRatio(1)
|
|
.aspectRatio(1)
|
|
|
.borderRadius(8)
|
|
.borderRadius(8)
|
|
|
|
|
+ .alignItems(VerticalAlign.Center)
|
|
|
|
|
+ .justifyContent(FlexAlign.Center)
|
|
|
.linearGradient(this.isSameDay(item.id, this.selectDay) ? this.linearInfo : {
|
|
.linearGradient(this.isSameDay(item.id, this.selectDay) ? this.linearInfo : {
|
|
|
colors: [['#F6F6F6', 1]],
|
|
colors: [['#F6F6F6', 1]],
|
|
|
})
|
|
})
|
|
|
- .alignItems(VerticalAlign.Center)
|
|
|
|
|
- .justifyContent(FlexAlign.Center)
|
|
|
|
|
.onClick(() => {
|
|
.onClick(() => {
|
|
|
this.clickItem(item)
|
|
this.clickItem(item)
|
|
|
})
|
|
})
|
|
@@ -250,41 +287,37 @@ export struct YTCalendarPicker {
|
|
|
.width(4)
|
|
.width(4)
|
|
|
.aspectRatio(1)
|
|
.aspectRatio(1)
|
|
|
.borderRadius(2)
|
|
.borderRadius(2)
|
|
|
- .linearGradient(this.dateList.indexOf(this.formatDateToCustomString(item.id, false)) !== -1 ?
|
|
|
|
|
- this.linearInfo : null)
|
|
|
|
|
|
|
+ .linearGradient(this.dateList.indexOf(this.formatDateToCustomString(item.id, false)) !== -1 ? this.linearInfo : null)
|
|
|
} else {
|
|
} else {
|
|
|
// 空白占位符
|
|
// 空白占位符
|
|
|
Text('')
|
|
Text('')
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
- .width(49)
|
|
|
|
|
- .aspectRatio(1)
|
|
|
|
|
|
|
+ .width(32)
|
|
|
.alignItems(HorizontalAlign.Center)
|
|
.alignItems(HorizontalAlign.Center)
|
|
|
.justifyContent(FlexAlign.Center)
|
|
.justifyContent(FlexAlign.Center)
|
|
|
}
|
|
}
|
|
|
})
|
|
})
|
|
|
}
|
|
}
|
|
|
- .columnsTemplate('repeat(7, 1fr)')
|
|
|
|
|
|
|
+ .rowsGap(10)
|
|
|
|
|
+ .maxCount(6)
|
|
|
.width("100%")
|
|
.width("100%")
|
|
|
|
|
+ .columnsTemplate('repeat(7, 1fr)')
|
|
|
}
|
|
}
|
|
|
.width("100%")
|
|
.width("100%")
|
|
|
- .height(400)
|
|
|
|
|
|
|
+ .padding(this.cPadding)
|
|
|
.backgroundColor(Color.White)
|
|
.backgroundColor(Color.White)
|
|
|
- .padding({
|
|
|
|
|
- left: 15,
|
|
|
|
|
- right: 15,
|
|
|
|
|
- top: 20,
|
|
|
|
|
- bottom: 4
|
|
|
|
|
- })
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ // 日期选择菜单
|
|
|
@Builder
|
|
@Builder
|
|
|
private dateSelectMenu() {
|
|
private dateSelectMenu() {
|
|
|
Stack({ alignContent: Alignment.Center }) {
|
|
Stack({ alignContent: Alignment.Center }) {
|
|
|
TextPicker({ range: this.range, selected: this.selectedIndex })
|
|
TextPicker({ range: this.range, selected: this.selectedIndex })
|
|
|
- .selectedTextStyle({ color: '#FF353C46', font: { weight: 500, size: 16 } })
|
|
|
|
|
- .defaultPickerItemHeight(36)
|
|
|
|
|
.divider(null)
|
|
.divider(null)
|
|
|
|
|
+ .defaultPickerItemHeight(36)
|
|
|
|
|
+ .backgroundColor(Color.White)
|
|
|
|
|
+ .selectedTextStyle({ color: '#FF353C46', font: { weight: 500, size: 16 } })
|
|
|
.onScrollStop((value, index) => {
|
|
.onScrollStop((value, index) => {
|
|
|
console.log(`testLog ${value} ${index}`)
|
|
console.log(`testLog ${value} ${index}`)
|
|
|
this.selectedIndex = index as number[]
|
|
this.selectedIndex = index as number[]
|
|
@@ -303,14 +336,17 @@ export struct YTCalendarPicker {
|
|
|
.width(160)
|
|
.width(160)
|
|
|
.padding(12)
|
|
.padding(12)
|
|
|
.borderRadius(8)
|
|
.borderRadius(8)
|
|
|
|
|
+ .backgroundColor(Color.White)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ // 右上角结构 - 确定和取消按钮
|
|
|
@Builder
|
|
@Builder
|
|
|
private buttonRow() {
|
|
private buttonRow() {
|
|
|
Row({ space: 14 }) {
|
|
Row({ space: 14 }) {
|
|
|
Text("取消")
|
|
Text("取消")
|
|
|
.borderRadius(36)
|
|
.borderRadius(36)
|
|
|
.backgroundColor('#F6F6F6')
|
|
.backgroundColor('#F6F6F6')
|
|
|
|
|
+ .fontColor(Color.Black)
|
|
|
.padding({
|
|
.padding({
|
|
|
left: 20,
|
|
left: 20,
|
|
|
top: 5,
|
|
top: 5,
|
|
@@ -321,6 +357,7 @@ export struct YTCalendarPicker {
|
|
|
Text("确认")
|
|
Text("确认")
|
|
|
.borderRadius(36)
|
|
.borderRadius(36)
|
|
|
.linearGradient(this.linearInfo)
|
|
.linearGradient(this.linearInfo)
|
|
|
|
|
+ .fontColor(Color.Black)
|
|
|
.padding({
|
|
.padding({
|
|
|
left: 20,
|
|
left: 20,
|
|
|
top: 5,
|
|
top: 5,
|