WheelPicker.ets 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. /*
  2. * 滚轮式日期选择器组件
  3. */
  4. import { YTDateUtil } from '../utils/YTDateUtil';
  5. import { UnitType } from './DatePickerEnums';
  6. @Component
  7. export struct WheelPicker {
  8. @Prop @Require date: Date;
  9. @State dateLocal: Date = new Date();
  10. upDate: (date: Date) => void = (date: Date) => {};
  11. @Prop @Require minDate: Date;
  12. @Prop @Require maxDate: Date;
  13. @Prop @Require unitType: UnitType;
  14. @State years: number[] = [];
  15. @State yearsString: string[] = [];
  16. @State months: number[] = [];
  17. @State monthsString: string[] = [];
  18. @State days: number[] = [];
  19. @State daysString: string[] = [];
  20. @State selectedYear: number = 0;
  21. @State selectedYearString: string = '';
  22. @State selectedMonth: number = 0;
  23. @State selectedMonthString: string = '';
  24. @State selectedDay: number = 0;
  25. @State selectedDayString: string = '';
  26. @State debounceYear: number = -1;
  27. @State debounceMonth: number = -1;
  28. @Prop highlightBackgroundColor:ResourceColor
  29. @Prop highlightBorderColor:ResourceColor
  30. @Prop selectedTextStyle:PickerTextStyle
  31. @Prop textStyle:PickerTextStyle
  32. aboutToAppear() {
  33. // 设置初始选中值
  34. this.selectedYear = this.date.getFullYear();
  35. this.selectedMonth = this.date.getMonth() + 1; // 月份从1开始
  36. this.selectedDay = this.date.getDate();
  37. this.selectedYearString = this.selectedYear.toString() + '年';
  38. this.selectedMonthString = YTDateUtil.padNumber(this.selectedMonth) + '月';
  39. this.selectedDayString = this.selectedDay.toString() + '日';
  40. // 初始化年份数据
  41. this.initYears();
  42. // 初始化月份数据
  43. this.initMonths();
  44. // 初始化日期数据
  45. this.initDays();
  46. }
  47. // 初始化年份数据
  48. initYears() {
  49. const minYear = this.minDate.getFullYear();
  50. const maxYear = this.maxDate.getFullYear();
  51. this.years = [];
  52. this.yearsString = [];
  53. for (let year = minYear; year <= maxYear; year++) {
  54. this.years.push(year);
  55. this.yearsString.push(year.toString() + '年');
  56. }
  57. }
  58. // 初始化月份数据
  59. initMonths() {
  60. this.months = [];
  61. this.monthsString = [];
  62. let minMonth = 1;
  63. let maxMonth = 12;
  64. if (!this.selectedYear) {
  65. this.selectedYear = this.date.getFullYear()
  66. this.selectedYearString = this.selectedYear.toString() + '年';
  67. console.log(this.date.getFullYear() + ',.,' + this.selectedYear)
  68. }
  69. // 如果是最小年份,则从最小月份开始
  70. if (this.selectedYear === this.minDate.getFullYear()) {
  71. minMonth = this.minDate.getMonth() + 1;
  72. }
  73. // 如果是最大年份,则到最大月份结束
  74. if (this.selectedYear === this.maxDate.getFullYear()) {
  75. maxMonth = this.maxDate.getMonth() + 1;
  76. }
  77. for (let month = minMonth; month <= maxMonth; month++) {
  78. //补零
  79. this.monthsString.push(YTDateUtil.padNumber(month)+'月')
  80. this.months.push(month);
  81. }
  82. // 确保选中的月份在可选范围内
  83. console.log('选择的月份是',this.selectedMonth)
  84. if (this.selectedMonth < minMonth) {
  85. this.selectedMonth = minMonth;
  86. this.selectedMonthString = YTDateUtil.padNumber(minMonth)+'月';
  87. } else if (this.selectedMonth > maxMonth) {
  88. this.selectedMonth = maxMonth;
  89. this.selectedMonthString = YTDateUtil.padNumber(minMonth)+'月';
  90. }
  91. }
  92. // 初始化日期数据
  93. initDays() {
  94. this.days = [];
  95. this.daysString = [];
  96. let minDay = 1;
  97. let maxDay = new Date(this.selectedYear, this.selectedMonth, 0).getDate(); // 获取当月天数
  98. // 如果是最小年份和最小月份,则从最小日期开始
  99. if (this.selectedYear === this.minDate.getFullYear() && this.selectedMonth === this.minDate.getMonth() + 1) {
  100. minDay = this.minDate.getDate();
  101. }
  102. // 如果是最大年份和最大月份,则到最大日期结束
  103. if (this.selectedYear === this.maxDate.getFullYear() && this.selectedMonth === this.maxDate.getMonth() + 1) {
  104. maxDay = this.maxDate.getDate();
  105. }
  106. for (let day = minDay; day <= maxDay; day++) {
  107. this.days.push(day);
  108. this.daysString.push(day.toString()+'日');
  109. }
  110. // 确保选中的日期在可选范围内
  111. if (this.selectedDay < minDay) {
  112. this.selectedDay = minDay;
  113. this.selectedDayString = this.selectedDay+'日';
  114. } else if (this.selectedDay > maxDay) {
  115. this.selectedDay = maxDay;
  116. this.selectedDayString = this.selectedDay+'日';
  117. }
  118. }
  119. // 更新日期
  120. updateDate() {
  121. this.dateLocal = new Date(this.selectedYear, this.selectedMonth - 1, this.selectedDay);
  122. this.upDate(this.dateLocal)
  123. }
  124. build() {
  125. Stack() {
  126. // 中间高亮横条
  127. Row() {
  128. }
  129. // .width(343)
  130. // .height(44)
  131. .width('100%')
  132. .height(44)
  133. .backgroundColor(this.highlightBackgroundColor)
  134. .borderRadius(44)
  135. .border({width: 1, color: this.highlightBorderColor})
  136. Row() {
  137. // 根据单位类型显示不同的选择器
  138. if (this.unitType === UnitType.YEAR || this.unitType === UnitType.YEAR_MONTH ||
  139. this.unitType === UnitType.YEAR_MONTH_DAY) {
  140. // 年份选择器
  141. TextPicker({
  142. range: this.yearsString,
  143. selected: this.yearsString.indexOf(this.selectedYearString)
  144. })
  145. .divider(null)
  146. .selectedTextStyle(this.selectedTextStyle)
  147. .textStyle(this.textStyle)
  148. .canLoop(true)
  149. .width(70)
  150. .onChange((val) => {
  151. if (this.debounceYear !== -1) {
  152. clearTimeout(this.debounceYear);
  153. }
  154. this.debounceYear = setTimeout(() => {
  155. this.selectedYear = Number((val as string).replace('年',''));
  156. this.selectedYearString = val as string;
  157. this.initMonths();
  158. this.initDays();
  159. this.updateDate();
  160. this.debounceYear = -1;
  161. }, 300); // 300ms 的防抖延迟
  162. })
  163. /* Text('年')
  164. .fontSize(16)
  165. .fontColor(Color.Black)
  166. .margin({ left: 10, right: 16 })*/
  167. }
  168. if (this.unitType === UnitType.MONTH || this.unitType === UnitType.YEAR_MONTH ||
  169. this.unitType === UnitType.MONTH_DAY || this.unitType === UnitType.YEAR_MONTH_DAY) {
  170. // 月份选择器
  171. TextPicker({
  172. range: this.monthsString,
  173. selected: this.monthsString.indexOf(this.selectedMonthString)
  174. })
  175. .divider(null)
  176. .selectedTextStyle(this.selectedTextStyle)
  177. .textStyle(this.textStyle)
  178. .canLoop(true)
  179. .width(70)
  180. .onChange((val) => {
  181. if (this.debounceMonth !== -1) {
  182. clearTimeout(this.debounceMonth);
  183. }
  184. this.debounceMonth = setTimeout(() => {
  185. //去0和月字
  186. this.selectedMonth = Number((val as string).replace(/^0+/, '').replace('月', ''));
  187. // this.selectedMonth = Number(val);
  188. this.selectedMonthString = val as string;
  189. this.initDays();
  190. this.updateDate();
  191. this.debounceMonth = -1;
  192. }, 100); // 100ms 的防抖延迟
  193. })
  194. /* Text('月')
  195. .fontSize(16)
  196. .margin({ left: 3, right: 16 })
  197. .fontColor(Color.Black)*/
  198. }
  199. if (this.unitType === UnitType.DAY || this.unitType === UnitType.MONTH_DAY ||
  200. this.unitType === UnitType.YEAR_MONTH_DAY) {
  201. // 日期选择器
  202. TextPicker({
  203. range: this.daysString,
  204. selected: this.daysString.indexOf(this.selectedDayString)
  205. })
  206. .divider(null)
  207. .selectedTextStyle(this.selectedTextStyle)
  208. .textStyle(this.textStyle)
  209. .canLoop(true)
  210. .width(70)
  211. .onChange((val) => {
  212. //去0和日字
  213. this.selectedDay = Number((val as string).replace(/^0+/, '').replace('日', ''));
  214. // this.selectedDay = Number(val);
  215. this.selectedDayString = val as string;
  216. this.updateDate();
  217. })
  218. /* Text('日')
  219. .fontSize(16)
  220. .fontColor(Color.Black)*/
  221. }
  222. }
  223. .justifyContent((this.unitType==UnitType.YEAR||this.unitType==UnitType.MONTH||this.unitType==UnitType.DAY)?FlexAlign.Center:FlexAlign.SpaceBetween)
  224. .width('100%')
  225. .padding({ left: 25, right: 25 })
  226. // .position({ x: 0, y: 90 }) // y = (224-40)/2,居中
  227. // // 上边界白色线
  228. // // Row()
  229. // // .width(320)
  230. // // .height(1)
  231. // // .backgroundColor('#fff')
  232. // // .align(Alignment.Center)
  233. // // .margin({ top: -24 }) // 48/2=24,正好到高亮条上边缘
  234. }
  235. .width('100%')
  236. .backgroundColor('#FFF')
  237. }
  238. }