ClockNew.tsx 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438
  1. import { View, ScrollView, Swiper, SwiperItem, Image } from "@tarojs/components";
  2. import './Clock.scss'
  3. import { useEffect, useRef, useState } from "react";
  4. import TabBar from "@/components/navigation/TabBar";
  5. import { compareVersion, getTimezone, rpxToPx } from "@/utils/tools";
  6. import MainSwiper from "@/features/health/MainSwiper";
  7. import MainConsole from "@/features/health/MainConsole";
  8. import MainHistory from "@/features/health/MainHistory";
  9. import { WindowType } from "@/utils/types";
  10. import { getLatestJournal, windows } from "@/services/health";
  11. import { useDispatch, useSelector } from "react-redux";
  12. import health, { setActiveArchived, setActiveArchivedTotal, setActiveTip, setEatArchived, setEatArchivedTotal, setEatTip, setFastWithSleep, setFinishSetup, setLongFast, setRefreshs, setTitle, setWindows } from "@/store/health";
  13. import dayjs from "dayjs";
  14. import { MainColorType } from "@/context/themes/color";
  15. import NewButton, { NewButtonType } from "@/_health/base/new_button";
  16. import { getThemeColor } from "@/features/health/hooks/health_hooks";
  17. import StatusIndicator, { StatusType } from "@/_health/base/status_indicator";
  18. import { useTranslation } from "react-i18next";
  19. import StickyDateList from "@/_health/components/sticky_date_list";
  20. import NoData from "@/_health/components/no_data";
  21. import Taro, { useDidShow } from "@tarojs/taro";
  22. import { IconClose } from "@/components/basic/Icons";
  23. import showAlert from "@/components/basic/Alert";
  24. import { jumpPage } from "@/features/trackTimeDuration/hooks/Common";
  25. let AppState;
  26. if (process.env.TARO_ENV == 'rn') {
  27. AppState = require("react-native").AppState
  28. }
  29. export default function ClockNew(props: { children: any, onScroll: any }) {
  30. const [count, setCount] = useState(0)
  31. const [loaded, setLoaded] = useState(false)
  32. const [showRetry, setShowRetry] = useState(false)
  33. const [scrollLeft, setScrollLeft] = useState(rpxToPx(750) * 0)
  34. const user = useSelector((state: any) => state.user);
  35. const health = useSelector((state: any) => state.health);
  36. const [type, setType] = useState(WindowType.day)
  37. const [needShowAddTip, setNeedShowAddTip] = useState(false)
  38. const [reminderAdd, setReminderAdd] = useState(false)
  39. const [showDate, setShowDate] = useState(false)
  40. const [date, setDate] = useState('')
  41. const [isPulling, setIsPulling] = useState(false)
  42. const healthRef = useRef(health)
  43. const historyRef2 = useRef()
  44. const dispatch = useDispatch();
  45. const { t } = useTranslation()
  46. global.dispatch = dispatch;
  47. const handleAppStateChange = (nextAppState) => {
  48. if (nextAppState != 'active') {
  49. return
  50. }
  51. if (nextAppState == 'active') {
  52. checkTimeZone()
  53. refreshData()
  54. }
  55. };
  56. global.tapDone = () => {
  57. setReminderAdd(true)
  58. }
  59. useDidShow(() => {
  60. if (process.env.TARO_ENV == 'weapp') {
  61. checkTimeZone()
  62. }
  63. setTimeout(() => {
  64. checkVersionUpdate();
  65. }, 1000)
  66. })
  67. function refreshData() {
  68. global.refreshWindow()
  69. Taro.getStorage({
  70. key: 'lastRefresh',
  71. success: function (res) {
  72. if (res.data) {
  73. var oldTimestamp = parseInt(res.data)
  74. var timestamp = new Date().getTime()
  75. for (var i = 0; i < healthRef.current.refreshs.length; i++) {
  76. var item = healthRef.current.refreshs[i]
  77. if (timestamp > item && item > oldTimestamp) {
  78. global.refreshHistory()
  79. console.log('强制刷新')
  80. return
  81. }
  82. }
  83. console.log('暂不需要强制刷新')
  84. }
  85. },
  86. fail(res) {
  87. console.log('load failed', res)
  88. global.refreshHistory()
  89. },
  90. complete: function () {
  91. }
  92. })
  93. }
  94. function checkTimeZone() {
  95. if (!user.isLogin) return
  96. var timeZoneFormatted = getTimezone()
  97. Taro.getStorage({
  98. key: 'last_tz',
  99. success: function (res) {
  100. if (res.data && res.data != timeZoneFormatted) {
  101. showAlert({
  102. title: t('feature.track_time_duration.change_tz_alert.title'),
  103. content: t('feature.track_time_duration.change_tz_alert.content', { tz: timeZoneFormatted }),
  104. showCancel: false,
  105. confirmText: t('feature.track_time_duration.change_tz_alert.confirm'),
  106. })
  107. // }
  108. }
  109. },
  110. complete: function () {
  111. Taro.setStorage({ key: 'last_tz', data: timeZoneFormatted })
  112. }
  113. })
  114. }
  115. useEffect(() => {
  116. healthRef.current = health;
  117. }, [health])
  118. // useEffect(() => {
  119. // archived()
  120. // }, [health.mode])
  121. useEffect(() => {
  122. if (process.env.TARO_ENV == 'rn') {
  123. AppState.addEventListener('change', handleAppStateChange);
  124. }
  125. Taro.onAppShow(() => {
  126. refreshData()
  127. })
  128. setInterval(() => {
  129. setCount(index => index + 1)
  130. healthRef.current.refreshs.map((item) => {
  131. const strTime = dayjs(item).format('YYYY-MM-DDTHH:mm:ss')
  132. const now = dayjs().format('YYYY-MM-DDTHH:mm:ss')
  133. if (strTime == now) {
  134. getWindows()
  135. if (global.refreshHistory) {
  136. global.refreshHistory()
  137. }
  138. }
  139. })
  140. }, 1000)
  141. setTimeout(() => {
  142. checkVersionUpdate();
  143. }, 1500)
  144. }, [])
  145. useEffect(() => {
  146. getWindows();
  147. if (global.refreshHistory) {
  148. global.refreshHistory()
  149. }
  150. }, [user.isLogin])
  151. global.refreshWindow = () => {
  152. getWindows();
  153. }
  154. function getWindows() {
  155. checkAddToMini()
  156. windows().then(res => {
  157. setLoaded(true)
  158. setShowRetry(false)
  159. if (!(res as any).windows.night_day.night.target) {
  160. var date = new Date()
  161. var hour = date.getHours()
  162. if (hour >= 6 && hour < 18) {
  163. var date1 = new Date()
  164. date1.setHours(6)
  165. date1.setMinutes(0)
  166. date1.setSeconds(0)
  167. var date2 = new Date()
  168. date2.setHours(18)
  169. date2.setMinutes(0)
  170. date2.setSeconds(0);
  171. (res as any).windows.night_day.day.target = {
  172. start_timestamp: date1.getTime(),
  173. end_timestamp: date2.getTime(),
  174. duration: 12 * 60 * 60 * 1000
  175. };
  176. (res as any).windows.night_day.night.target = {
  177. start_timestamp: date2.getTime(),
  178. end_timestamp: date2.getTime() + 12 * 60 * 60 * 1000,
  179. duration: 12 * 60 * 60 * 1000
  180. }
  181. }
  182. else {
  183. var date1 = new Date()
  184. date1.setHours(18)
  185. date1.setMinutes(0)
  186. date1.setSeconds(0);
  187. (res as any).windows.night_day.day.target = {
  188. start_timestamp: date1.getTime(),
  189. end_timestamp: date1.getTime() + 12 * 60 * 60 * 1000,
  190. duration: 12 * 60 * 60 * 1000
  191. };
  192. (res as any).windows.night_day.night.target = {
  193. start_timestamp: date1.getTime() + 12 * 60 * 60 * 1000,
  194. end_timestamp: date1.getTime() + 12 * 60 * 60 * 1000 + 12 * 60 * 60 * 1000,
  195. duration: 12 * 60 * 60 * 1000
  196. }
  197. }
  198. }
  199. dispatch(setFastWithSleep((res as any).fast_with_sleep))
  200. dispatch(setWindows((res as any).windows))
  201. dispatch(setLongFast((res as any).long_fast))
  202. dispatch(setRefreshs((res as any).refresh_timestamps))
  203. dispatch(setFinishSetup((res as any).finish_setup))
  204. setIsPulling(false)
  205. }).catch(e => {
  206. setShowRetry(true)
  207. })
  208. }
  209. function checkAddToMini() {
  210. if (process.env.TARO_ENV == 'weapp' && user.isLogin) {
  211. const version = Taro.getAppBaseInfo().SDKVersion
  212. if (compareVersion(version, '2.30.3') >= 0) {
  213. wx.checkIsAddedToMyMiniProgram({
  214. success: (res) => {
  215. if (!res.added) {
  216. setNeedShowAddTip(true)
  217. }
  218. },
  219. fail: (e) => {
  220. }
  221. });
  222. }
  223. }
  224. }
  225. async function checkVersionUpdate() {
  226. if (!user.isLogin) {
  227. return
  228. }
  229. // return
  230. const showAlert1 = await getStorage('148alert') || false;
  231. Taro.setStorage({ key: '148alert', data: true })
  232. if (!showAlert1 && !health.finish_setup) {
  233. showAlert({
  234. title: t('health.verion_tip'),
  235. content: '',
  236. showCancel: false,
  237. confirmText: t('health.verion_done'),
  238. confirm: () => {
  239. jumpPage('/_health/pages/guide_begin')
  240. }
  241. })
  242. }
  243. }
  244. async function getStorage(key: string) {
  245. try {
  246. const res = await Taro.getStorage({ key });
  247. return res.data;
  248. } catch {
  249. return '';
  250. }
  251. }
  252. function tapScroll(index) {
  253. setScrollLeft(rpxToPx(750) * index)
  254. }
  255. function scroll(e) {
  256. console.log(e.detail.scrollLeft)
  257. }
  258. function pageChanged(index) {
  259. }
  260. function typeChanged(str) {
  261. }
  262. function pageTitle() {
  263. switch (health.mode) {
  264. case 'DAY':
  265. return t('health.window_day')
  266. case 'NIGHT':
  267. return t('health.night')
  268. case 'FAST':
  269. return t('health.fast')
  270. case 'EAT':
  271. return t('health.eat')
  272. case 'SLEEP':
  273. return t('health.sleep')
  274. case 'ACTIVE':
  275. return t('health.active')
  276. }
  277. }
  278. function detail() {
  279. // return <View>11111</View>
  280. if (!health.windows) {
  281. return <View />
  282. }
  283. return <StickyDateList
  284. isPulling={isPulling}
  285. showDate={showDate}
  286. date={date}
  287. disable={props.children}
  288. onRefresherRefresh={() => {
  289. global.refreshWindow()
  290. setIsPulling(true)
  291. if (global.refreshHistory) {
  292. global.refreshHistory()
  293. }
  294. }}
  295. loadMore={() => {
  296. if (historyRef2) {
  297. (historyRef2.current as any).more()
  298. }
  299. }}
  300. onScroll={e => {
  301. props.onScroll(e)
  302. if (showDate && e.detail.scrollTop > 100) {
  303. dispatch(setTitle(t('health.recents')))
  304. }
  305. else if (e.detail.scrollTop > 100) {
  306. dispatch(setTitle(t('health.today')))
  307. }
  308. else {
  309. dispatch(setTitle(''))
  310. }
  311. if (historyRef2) {
  312. (historyRef2.current as any).onScroll(e)
  313. }
  314. }}
  315. >
  316. <View style={{ display: 'flex', flexDirection: 'column' }}>
  317. {
  318. needShowAddTip && reminderAdd && user.isLogin && <View className="guide_tip h26">{t('health.add_mini_guide_tip')}
  319. <NewButton type={NewButtonType.img} btnStyle={{
  320. position: 'absolute',
  321. right: 0,
  322. top: 0,
  323. bottom: 0,
  324. width: rpxToPx(92)
  325. }} onClick={() => {
  326. setReminderAdd(false)
  327. }}>
  328. <IconClose color={MainColorType.g03} width={rpxToPx(32)} height={rpxToPx(32)} />
  329. </NewButton>
  330. </View>
  331. }
  332. <MainSwiper count={count} pageChanged={pageChanged} typeChanged={typeChanged} />
  333. {
  334. process.env.TARO_ENV == 'weapp' && <MainConsole type={type} />
  335. }
  336. <MainHistory ref={historyRef2} updateDate={(e) => {
  337. setShowDate(e.show)
  338. setDate(e.date)
  339. }} />
  340. <View style={{ height: user.isLogin ? 150 : 300 }} />
  341. {
  342. (health.mode == 'DAY' || health.mode == 'NIGHT') && <View style={{ height: 150, flexShrink: 0 }} />
  343. }
  344. {
  345. props.children
  346. }
  347. </View>
  348. </StickyDateList>
  349. }
  350. //https://blog.csdn.net/weixin_43525284/article/details/130182218
  351. if (!loaded && showRetry) return <NoData refresh={
  352. () => {
  353. getWindows();
  354. if (global.refreshHistory) {
  355. global.refreshHistory()
  356. }
  357. }
  358. } />
  359. return <View style={{ flex: 1, position: 'relative' }}>
  360. {
  361. process.env.TARO_ENV == 'weapp' ? detail() : <ScrollView style={{ flex: 1, backgroundColor: MainColorType.bg }} onScroll={e => {
  362. if (e.detail.scrollTop > 240) {
  363. dispatch(setTitle(health.mode))
  364. }
  365. else {
  366. dispatch(setTitle(''))
  367. }
  368. }}>
  369. {
  370. detail()
  371. }
  372. {
  373. props.children()
  374. }
  375. </ScrollView>
  376. }
  377. {
  378. process.env.TARO_ENV == 'weapp' && <TabBar index={0} />
  379. }
  380. </View>
  381. }