LimitPickers.tsx 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. import { PickerView, PickerViewColumn, View, Text } from "@tarojs/components";
  2. import { forwardRef, useEffect, useImperativeHandle, useState } from "react";
  3. import './LimitPickers.scss'
  4. import Taro from "@tarojs/taro";
  5. import React from "react";
  6. import { useTranslation } from "react-i18next";
  7. import { TimeFormatter } from "@/utils/time_format";
  8. // export default function Component(props: { limit: number, onChange: Function, onCancel: Function,isRealTime?:boolean,limitDay?:number,time?:number,ref?:any }) {
  9. const Component = forwardRef((props: {
  10. limit: number, onChange: Function, onCancel: Function,
  11. isRealTime?: boolean, limitDay?: number, time?: number, themeColor?: string, title?: string
  12. }, ref) => {
  13. const days: string[] = [];
  14. const today = new Date();
  15. var color = props.themeColor ? props.themeColor : '#ff0000'
  16. var alpha = alphaToHex(0.4)
  17. const [values, setValues] = useState([props.limitDay ? props.limitDay - 1 : 6, today.getHours(), today.getMinutes()])
  18. const [isDisableConfirm, setIsDisableConfirm] = useState(false)
  19. const [count, setCount] = useState(0)
  20. const { t } = useTranslation()
  21. function alphaToHex(alpha) {
  22. var alphaValue = Math.round(alpha * 255); // 将透明度乘以255并四舍五入
  23. var hexValue = alphaValue.toString(16); // 将整数转换为十六进制字符串
  24. if (hexValue.length === 1) {
  25. hexValue = "0" + hexValue; // 如果十六进制字符串只有一位,补零
  26. }
  27. return hexValue;
  28. }
  29. useEffect(() => {
  30. global.picker_time = global.set_time
  31. if (props.time) {
  32. var date = new Date(props.time)
  33. setValues([(props.limitDay ? props.limitDay - 1 : 6) - getDaysDiff(date), date.getHours(), date.getMinutes()])
  34. }
  35. }, [])
  36. // useEffect(() => {
  37. // setValues([6, today.getHours(), today.getMinutes()])
  38. // }, [props.limit])
  39. useEffect(() => {
  40. var date = new Date();
  41. if (!props.isRealTime) {
  42. date = new Date(global.set_time);
  43. }
  44. date.setDate(today.getDate() - ((props.limitDay ? props.limitDay - 1 : 6) - values[0]));
  45. date.setHours(values[1])
  46. date.setMinutes(values[2])
  47. global.picker_time = date.getTime()
  48. }, [values])
  49. for (let i = props.limitDay ? props.limitDay - 1 : 6; i >= 0; i--) {
  50. const date = new Date();
  51. date.setDate(today.getDate() - i);
  52. const month = date.getMonth() + 1;
  53. const day = date.getDate();
  54. // const weekday = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'][date.getDay()];
  55. const weekday = TimeFormatter.getDayOfWeek(date.getDay(), true);
  56. const formattedDate = global.language == 'en' ? `${weekday} ${TimeFormatter.getMonth(month)} ${day}` : `${TimeFormatter.getMonth(month)}${day}日 ${weekday}`;
  57. if (i == 0) {
  58. days.push(TimeFormatter.getTodayUnit());
  59. }
  60. else if (i == 1) {
  61. days.push(TimeFormatter.getYesterdayUnit());
  62. }
  63. else {
  64. days.push(formattedDate);
  65. }
  66. }
  67. const hours: number[] = [];
  68. for (let i = 0; i <= 23; i++) {
  69. hours.push(i);
  70. }
  71. const minutes: number[] = [];
  72. for (let i = 0; i <= 59; i++) {
  73. minutes.push(i);
  74. }
  75. function getTimestamp(dateTimeString: string): number {
  76. const timestamp = Date.parse(dateTimeString);
  77. return timestamp;
  78. }
  79. function getDaysDiff(date: Date): number {
  80. const today = new Date();
  81. today.setHours(0, 0, 0, 0);
  82. const targetDate = new Date(date.getFullYear(), date.getMonth(), date.getDate());
  83. targetDate.setHours(0, 0, 0, 0);
  84. const timeDiff = today.getTime() - targetDate.getTime();
  85. const daysDiff = Math.floor(timeDiff / (1000 * 60 * 60 * 24));
  86. return daysDiff;
  87. }
  88. function onPickerChange(e) {
  89. setValues(e.detail.value)
  90. /*
  91. var list = e.detail.value
  92. const date = new Date();
  93. date.setDate(today.getDate() - ((props.limitDay ? props.limitDay - 1 : 6) - list[0]));
  94. const year = date.getFullYear();
  95. const month = date.getMonth() + 1;
  96. const day = date.getDate();
  97. const time = `${year}-${expandZero(month)}-${expandZero(day)}T${expandZero(hours[list[1]])}:${expandZero(minutes[list[2]])}:00`;
  98. if (getTimestamp(time) > global.set_time) {
  99. Taro.showToast({
  100. icon: 'none',
  101. title: t('feature.common.toast.min_value'),
  102. })
  103. setValues([list[0], (new Date(global.set_time)).getHours(), (new Date(global.set_time)).getMinutes()])
  104. disableConfirm()
  105. }
  106. else {
  107. var limitDate = new Date(props.limit)
  108. if (getTimestamp(time) < props.limit) {
  109. Taro.showToast({
  110. icon: 'none',
  111. title: t('feature.common.toast.max_value'),
  112. })
  113. setValues([(props.limitDay ? props.limitDay - 1 : 6) - getDaysDiff(limitDate), limitDate.getHours(), limitDate.getMinutes()])
  114. disableConfirm()
  115. return
  116. }
  117. setValues(e.detail.value)
  118. }*/
  119. }
  120. function onPickerEnd(e) {
  121. // console.log(e)
  122. // console.log(values)
  123. // setValues(values)
  124. // setCount(count+1)
  125. }
  126. function cancel(e) {
  127. if (process.env.TARO_ENV == 'weapp') {
  128. e.stopPropagation()
  129. }
  130. props.onCancel()
  131. }
  132. function confirm(e) {
  133. if (process.env.TARO_ENV == 'weapp') {
  134. e.stopPropagation()
  135. }
  136. var date = new Date();
  137. date.setDate(today.getDate() - ((props.limitDay ? props.limitDay - 1 : 6) - values[0]));
  138. const year = date.getFullYear();
  139. const month = date.getMonth() + 1;
  140. const day = date.getDate();
  141. const time = `${year}-${expandZero(month)}-${expandZero(day)}T${expandZero(hours[values[1]])}:${expandZero(minutes[values[2]])}:${expandZero((new Date(global.set_time)).getSeconds())}`;
  142. if (getTimestamp(time) > global.set_time) {
  143. setValues([values[0], (new Date(global.set_time)).getHours(), (new Date(global.set_time)).getMinutes()])
  144. setTimeout(() => {
  145. setValues([values[0], (new Date(global.set_time)).getHours(), (new Date(global.set_time)).getMinutes()])
  146. }, 300);
  147. Taro.showToast({
  148. icon: 'none',
  149. title: t('feature.common.toast.min_time_value'),
  150. })
  151. return
  152. }
  153. else {
  154. var limitDate = new Date(props.limit)
  155. if (getTimestamp(time) < props.limit) {
  156. setValues([(props.limitDay ? props.limitDay - 1 : 6) - getDaysDiff(limitDate), limitDate.getHours(), limitDate.getMinutes()])
  157. setTimeout(() => {
  158. setValues([(props.limitDay ? props.limitDay - 1 : 6) - getDaysDiff(limitDate), limitDate.getHours(), limitDate.getMinutes()])
  159. }, 300)
  160. Taro.showToast({
  161. icon: 'none',
  162. title: t('feature.common.toast.max_time_value'),
  163. })
  164. return
  165. }
  166. }
  167. if (!props.isRealTime) {
  168. date = new Date(global.set_time);
  169. date.setDate(today.getDate() - ((props.limitDay ? props.limitDay - 1 : 6) - values[0]));
  170. }
  171. //
  172. date.setHours(values[1])
  173. date.setMinutes(values[2])
  174. props.onChange(date.getTime())
  175. }
  176. function getConfirmData() {
  177. var date = new Date();
  178. if (!props.isRealTime) {
  179. date = new Date(global.set_time);
  180. }
  181. date.setDate(today.getDate() - ((props.limitDay ? props.limitDay - 1 : 6) - values[0]));
  182. date.setHours(values[1])
  183. date.setMinutes(values[2])
  184. return date.getTime()
  185. }
  186. useImperativeHandle(ref, () => ({
  187. getConfirmData: getConfirmData
  188. }));
  189. function expandZero(num: number): string {
  190. return num < 10 ? `0${num}` : `${num}`;
  191. }
  192. function pickerDetail() {
  193. return <View style={{ display: 'flex', flexDirection: 'column' }}>
  194. <Text className='modal_title' style={{ color: color }}>{props.title ? props.title : '测试标题 '}</Text>
  195. <View style={{ backgroundColor: 'transparent', position: 'relative' }}>
  196. <PickerView
  197. itemStyle={{ color: '#fff', margin: 0, padding: 0 }}
  198. value={values}
  199. className="picker"
  200. maskClass="picker-mask"
  201. style={{ color: '#fff' }}
  202. onChange={onPickerChange}
  203. onPickEnd={onPickerEnd}
  204. immediateChange={true}
  205. indicatorStyle='height: 50px;color:red;'>
  206. <PickerViewColumn style='flex:0 0 45%'>
  207. {days.map(item => {
  208. return (
  209. <View style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', color: '#fff' }}>{item}</View>
  210. );
  211. })}
  212. </PickerViewColumn>
  213. <PickerViewColumn>
  214. {hours.map(item => {
  215. return (
  216. <View style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', color: '#fff' }}>{item < 10 ? `0${item}` : item}</View>
  217. );
  218. })}
  219. </PickerViewColumn>
  220. <PickerViewColumn>
  221. {minutes.map(item => {
  222. return (
  223. <View style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', color: '#fff' }}>{item < 10 ? `0${item}` : item}</View>
  224. );
  225. })}
  226. </PickerViewColumn>
  227. </PickerView>
  228. {/* <View className="point_bg1 ">
  229. <Text style={{ color: '#fff', fontSize: 16, fontWeight: 'bold' }}>:</Text>
  230. </View> */}
  231. </View>
  232. <View className='modal_operate'>
  233. <View className='modal_btn' style={{ backgroundColor: color + alpha }} onClick={cancel}>
  234. <Text className='modal_cancel_text' style={{ color: color, fontWeight: 'bold' }}>{t('feature.common.picker_cancel_btn')}</Text>
  235. </View>
  236. <View className='btn_space' />
  237. <View className='modal_btn' style={{ backgroundColor: color }} onClick={confirm}>
  238. <Text className='modal_confirm_text' style={{ color: '#000', fontWeight: 'bold' }}>{t('feature.common.picker_confirm_btn')}</Text>
  239. </View>
  240. </View>
  241. </View>
  242. }
  243. return pickerDetail()
  244. })
  245. export default React.memo(Component);;