ClockNew.tsx 16 KB

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