Clock2.tsx 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649
  1. import { Component, PropsWithChildren, useEffect, useRef, useState } from 'react'
  2. import { View, Text, Button, Input, Picker, Swiper, SwiperItem, Icon, PageContainer, ScrollView } from '@tarojs/components'
  3. import Tabbar from "@/components/navigation/TabBar";
  4. import '../index/index.scss'
  5. import './Clock.scss'
  6. // import './context/locales/index'
  7. import '@/context/locales/index'
  8. import Taro, { useDidShow, usePageScroll, useReady, useRouter, useShareAppMessage } from '@tarojs/taro'
  9. // import ComponentA from './component'
  10. import { useDispatch, useSelector } from 'react-redux';
  11. import { getInfoSuccess, logoutSuccess } from '@/store/user';
  12. import { wxPubFollow } from '@/services/permission';
  13. import { gobalConfigs, staticResources, uploadSessionKey } from '@/services/common';
  14. import Clocks from '@/features/trackTimeDuration/components/Clock';
  15. import Console from '@/features/trackTimeDuration/components/Console';
  16. import Schedule from '@/features/trackTimeDuration/components/Schedule';
  17. import { getChecks, getClocks } from '@/services/trackTimeDuration';
  18. import { setScenario } from '@/store/scenario';
  19. import { setSpecifiedStatus, setSpecifiedState, machine } from '@/store/trackTimeMachine';
  20. import trackTimeService from '@/store/trackTimeMachine';
  21. import { setWXFollow } from '@/store/permission';
  22. import Tooltip from '@/components/view/Tooltip'
  23. import RequestType, { thirdPartRequest } from '@/services/thirdPartRequest'
  24. import { setConfigs, setTabbarStatus } from '@/store/common'
  25. import RecordFastSleep from '@/features/trackTimeDuration/components/RecordFastSleep'
  26. import Box from '@/components/layout/Box'
  27. import Layout from '@/components/layout/layout'
  28. import { CheckBoxType, NaviBarTitleShowType, TemplateType } from '@/utils/types'
  29. import { updateScenario } from '@/store/time'
  30. import { ConsoleType, changeConsoleStatus } from '@/store/console'
  31. import TitleView from '@/features/trackTimeDuration/components/TitleView'
  32. import StatusIndicator from '@/features/trackTimeDuration/components/StatusIndicator'
  33. import { useTranslation } from 'react-i18next'
  34. import SectionHeader from '@/components/layout/SectionHeader'
  35. import Header from '@/components/layout/Header'
  36. import NoData from '@/components/view/NoData'
  37. import { ColorType } from '@/context/themes/color'
  38. import { jumpPage } from '@/features/trackTimeDuration/hooks/Common'
  39. import { ChooseScenarioBtn } from '@/features/common/SpecBtns'
  40. import { rpxToPx, vibrate } from '@/utils/tools'
  41. import Modal from '@/components/layout/Modal'
  42. // import TabBar from '../../components/Tabbar';
  43. // import Rings from '@components/view/Rings';
  44. let useNavigation;
  45. let AppState;
  46. if (process.env.TARO_ENV == 'rn') {
  47. AppState = require("react-native").AppState
  48. useNavigation = require("@react-navigation/native").useNavigation
  49. }
  50. export default function IndexPage() {
  51. const dispatch = useDispatch();
  52. const { t, i18n } = useTranslation()
  53. const [checkData, setCheckData] = useState(null)
  54. const user = useSelector((state: any) => state.user);
  55. const time = useSelector((state: any) => state.time);
  56. const consoleData = useSelector((state: any) => state.console);
  57. const [counter, setCounter] = useState(0)
  58. const [timerId, setTimerId] = useState(null)
  59. const [needShowAddTip, setNeedShowAddTip] = useState(false)
  60. const [showErrorPage, setErrorPage] = useState(false)
  61. const [swiperIndex, setSwiperIndex] = useState(0)
  62. const [autoPlay, setAutoPlay] = useState(false)
  63. const [showModal, setShowModal] = useState(false)
  64. const [modalDetail, setModalDetail] = useState<any>(null)
  65. const [showModal2, setShowModal2] = useState(false)
  66. const [modalDetail2, setModalDetail2] = useState<any>(null)
  67. const [showSingleFastEnd, setShowSingleFastEnd] = useState(false)
  68. const [consoleStatus, setConsoleStatus] = useState(consoleData.status)
  69. const [showLogin, setShowLogin] = useState(false)
  70. const [showTip, setShowTip] = useState(false)
  71. const [isModal1, setIsModal1] = useState(false)
  72. const [debugInfo, setDebugInfo] = useState(null)
  73. const [loaded, setLoaded] = useState(false)
  74. let navigation;
  75. if (useNavigation) {
  76. navigation = useNavigation()
  77. }
  78. global.dispatch = dispatch;
  79. global.checkData = () => {
  80. getCheckData()
  81. }
  82. useEffect(() => {
  83. if (process.env.TARO_ENV == 'rn') {
  84. AppState.addEventListener('change', handleAppStateChange);
  85. }
  86. global.consoleType = 'idle'
  87. dispatch(staticResources() as any);
  88. // dispatch(gobalConfigs() as any);
  89. trackTimeService.onTransition(state => {
  90. if ((state.value as any).FAST_SLEEP == 'COMPLETED' ||
  91. (state.value as any).FAST == 'ONGOING' ||
  92. (state.value as any).SLEEP == 'ONGOING' ||
  93. (state.value as any).FAST_SLEEP == 'ONGOING1' ||
  94. (state.value as any).FAST_SLEEP == 'ONGOING2' ||
  95. (state.value as any).FAST_SLEEP == 'ONGOING3' ||
  96. (state.value as any).FAST == 'COMPLETED' ||
  97. (state.value as any).SLEEP == 'COMPLETED') {
  98. getCheckData()
  99. }
  100. })
  101. }, [])
  102. useEffect(() => {
  103. const currentLanguage = i18n.language;
  104. global.language = currentLanguage
  105. console.log('current language', currentLanguage)
  106. }, [])
  107. const handleAppStateChange = (nextAppState) => {
  108. checkTimeZone()
  109. };
  110. useEffect(() => {
  111. setConsoleStatus(consoleData.status)
  112. switch (consoleData.status) {
  113. // case ConsoleType.going:
  114. // setShowSingleFastEnd(true)
  115. // setTimeout(() => {
  116. // setShowSingleFastEnd(false)
  117. // setSwiperIndex(1)
  118. // setAutoPlay(true)
  119. // dispatch(changeConsoleStatus({ status: ConsoleType.end }))
  120. // }, 2000)
  121. // break
  122. case ConsoleType.end:
  123. setTimeout(() => {
  124. dispatch(changeConsoleStatus({ status: ConsoleType.idle }))
  125. }, 2000)
  126. break
  127. }
  128. }, [consoleData.status])
  129. useEffect(() => {
  130. if (user.isLogin) {
  131. //检查用户是否添加过小程序
  132. checkAddToMini();
  133. //检查session是否过期
  134. checkSession()
  135. getCheckData()
  136. }
  137. }, [user.isLogin])
  138. function checkTimeZone() {
  139. var split = new Date().toString().split(' ');
  140. var timeZoneFormatted = split[split.length - 2];
  141. Taro.getStorage({
  142. key: 'last_tz',
  143. success: function (res) {
  144. if (res.data && res.data != timeZoneFormatted) {
  145. if (global.currentStatus != 'WAIT_FOR_START') {
  146. Taro.showModal({
  147. title: t('feature.track_time_duration.change_tz_alert.title'),
  148. content: t('feature.track_time_duration.change_tz_alert.content', { tz: timeZoneFormatted }),
  149. showCancel: false,
  150. confirmText: t('feature.track_time_duration.change_tz_alert.confirm'),
  151. })
  152. }
  153. }
  154. },
  155. complete: function () {
  156. Taro.setStorage({ key: 'last_tz', data: timeZoneFormatted })
  157. }
  158. })
  159. }
  160. function checkSession() {
  161. if (process.env.TARO_ENV === 'weapp') {
  162. thirdPartRequest(RequestType.RequestTypeCheckSession).then(res => {
  163. }).catch(err => {
  164. console.log('session_key 已经失效,需要更新登录code')
  165. thirdPartRequest(RequestType.RequestTypeWXLogin).then(result => {
  166. uploadSessionKey({ type: 'WX_MP', code: (result as any).code });
  167. })
  168. })
  169. }
  170. }
  171. function checkAddToMini() {
  172. process.env.TARO_ENV == 'weapp' &&
  173. wx.checkIsAddedToMyMiniProgram({
  174. success: (res) => {
  175. if (!res.added) {
  176. setNeedShowAddTip(true)
  177. }
  178. },
  179. fail: (e) => {
  180. }
  181. });
  182. }
  183. useEffect(() => {
  184. startTimer();
  185. return () => {
  186. // 在组件卸载时清除定时器
  187. if (timerId) {
  188. clearInterval(timerId);
  189. }
  190. };
  191. }, []);
  192. const startTimer = () => {
  193. // 避免重复启动定时器
  194. if (timerId) {
  195. return;
  196. }
  197. const id = setInterval(() => {
  198. setShowLogin(true)
  199. if (global.showModal) {
  200. return
  201. }
  202. setCounter((prevCounter) => prevCounter + 1);
  203. //每天0点刷新一下打卡数据
  204. var now = new Date()
  205. if (now.getHours() == 0 && now.getMinutes() == 0) {
  206. getCheckData()
  207. }
  208. }, 1000);
  209. setTimerId(id as any);
  210. };
  211. useReady(async () => {
  212. const userData = await getStorage('userData');
  213. if (userData) {
  214. dispatch(getInfoSuccess(JSON.parse(userData as string)) as any);
  215. setTimeout(() => {
  216. checkWXPubFollow()
  217. getCheckData()
  218. }, 200)
  219. }
  220. })
  221. if (process.env.TARO_ENV == 'weapp') {
  222. useShareAppMessage((e) => {
  223. return {
  224. title: t('feature.track_time_duration.common.share_title'),
  225. path: 'pages/clock/Clock'
  226. }
  227. })
  228. }
  229. function clearTempScenarioCache() {
  230. global.schedule_fast = null
  231. global.schedule_sleep = null
  232. Taro.removeStorage({
  233. key: 'tempScenario',
  234. success: function (res) {
  235. }
  236. })
  237. }
  238. usePageScroll((e) => {
  239. })
  240. useDidShow(() => {
  241. // global.updateTab(0)
  242. global.showModal = false;
  243. if (user.isLogin) {
  244. checkWXPubFollow()
  245. // getCheckData();
  246. }
  247. clearTempScenarioCache()
  248. })
  249. global.refreshTime = () => {
  250. getCheckData()
  251. }
  252. global.showSingleFastEnd = () => {
  253. setShowSingleFastEnd(true)
  254. }
  255. function tapClock(e) {
  256. if (process.env.TARO_ENV == 'weapp') {
  257. e.stopPropagation()
  258. }
  259. if (!user.isLogin) {
  260. jumpPage('/pages/account/ChooseAuth', 'ChooseAuth', navigation)
  261. }
  262. else {
  263. vibrate()
  264. }
  265. }
  266. function tapLogin(e) {
  267. jumpPage('/pages/account/ChooseAuth', 'ChooseAuth', navigation)
  268. }
  269. function getCheckData() {
  270. var res = global.selectData
  271. setErrorPage(false)
  272. dispatch(updateScenario((res as any).current_record))
  273. dispatch(setConfigs((res as any).time_input_schema));
  274. dispatch(setScenario((res as any).scenario));
  275. if ((res as any).theme_color) {
  276. global.fastColor = (res as any).theme_color.fast
  277. global.sleepColor = (res as any).theme_color.sleep
  278. }
  279. machine.context.checkData = res as any;
  280. global.scenario = (res as any).current_record.scenario;
  281. const currentState = trackTimeService.getSnapshot();
  282. let json = {};
  283. var key = (res as any).current_record.scenario
  284. var status = (res as any).current_record.status
  285. json[key] = status
  286. currentState.value = json;
  287. machine.context.currentStatus = `${key}.${status}`;//'mixed.ON_GOING2'
  288. setCheckData(res as any)
  289. setLoaded(true)
  290. if ((res as any).current_record.status != 'ONGOING1') {
  291. setSwiperIndex(0)
  292. }
  293. else {
  294. if (global.consoleType == 'going') {
  295. setShowSingleFastEnd(true)
  296. setTimeout(() => {
  297. setShowSingleFastEnd(false)
  298. setSwiperIndex(1)
  299. setAutoPlay(true)
  300. global.consoleType = 'end'
  301. dispatch(changeConsoleStatus({ status: ConsoleType.end }))
  302. setTimeout(() => {
  303. global.consoleType = 'idle'
  304. }, 2000)
  305. }, 500)
  306. }
  307. else {
  308. }
  309. }
  310. return
  311. getClocks().then(res => {
  312. debugger
  313. setErrorPage(false)
  314. dispatch(updateScenario((res as any).current_record))
  315. dispatch(setConfigs((res as any).time_input_schema));
  316. dispatch(setScenario((res as any).scenario));
  317. if ((res as any).theme_color) {
  318. global.fastColor = (res as any).theme_color.fast
  319. global.sleepColor = (res as any).theme_color.sleep
  320. }
  321. machine.context.checkData = res as any;
  322. global.scenario = (res as any).current_record.scenario;
  323. const currentState = trackTimeService.getSnapshot();
  324. let json = {};
  325. var key = (res as any).current_record.scenario
  326. var status = (res as any).current_record.status
  327. json[key] = status
  328. currentState.value = json;
  329. machine.context.currentStatus = `${key}.${status}`;//'mixed.ON_GOING2'
  330. setCheckData(res as any)
  331. setLoaded(true)
  332. if ((res as any).current_record.status != 'ONGOING1') {
  333. setSwiperIndex(0)
  334. }
  335. else {
  336. if (global.consoleType == 'going') {
  337. setShowSingleFastEnd(true)
  338. setTimeout(() => {
  339. setShowSingleFastEnd(false)
  340. setSwiperIndex(1)
  341. setAutoPlay(true)
  342. global.consoleType = 'end'
  343. dispatch(changeConsoleStatus({ status: ConsoleType.end }))
  344. setTimeout(() => {
  345. global.consoleType = 'idle'
  346. }, 2000)
  347. }, 500)
  348. }
  349. else {
  350. }
  351. }
  352. }).catch(e => {
  353. setLoaded(true)
  354. if (!checkData) {
  355. setErrorPage(true)
  356. }
  357. else {
  358. }
  359. })
  360. }
  361. function checkWXPubFollow() {
  362. var params;
  363. if (global.forceRefreshWXPub) {
  364. params = {
  365. force_refresh: true
  366. }
  367. }
  368. global.forceRefreshWXPub = false
  369. wxPubFollow(params).then(res => {
  370. dispatch(setWXFollow((res as any).wx_pub_followed));
  371. console.log('当前的关注状态' + (res as any).wx_pub_followed);
  372. })
  373. }
  374. async function getStorage(key: string) {
  375. try {
  376. const res = await Taro.getStorage({ key });
  377. return res.data;
  378. } catch {
  379. return '';
  380. }
  381. }
  382. function schedule() {
  383. if (!user.isLogin) {
  384. return <View />
  385. }
  386. return <Schedule data={(checkData as any).current_record} />
  387. }
  388. function needSwiper() {
  389. var isNeed = time.scenario == 'FAST_SLEEP' &&
  390. (time.status == 'WAIT_FOR_START' ||
  391. time.status == 'ONGOING1' ||
  392. time.status == 'ONGOING2')
  393. if (showSingleFastEnd) {
  394. return false;
  395. }
  396. return isNeed
  397. }
  398. global.showClockModal = (isShow: boolean, detail: any, debugNode?: any) => {
  399. global.showModal = isShow
  400. setIsModal1(true)
  401. setDebugInfo(debugNode)
  402. setShowModal(isShow)
  403. setModalDetail(detail)
  404. }
  405. global.showClockModal2 = (isShow: boolean, detail: any) => {
  406. setDebugInfo(null)
  407. global.showModal = isShow
  408. setIsModal1(false)
  409. setShowModal2(isShow)
  410. setModalDetail2(detail)
  411. }
  412. function headerView() {
  413. return <TitleView title={t('page.clock.title')} showAddBtn={loaded && !showErrorPage ? true : false}>
  414. <StatusIndicator />
  415. </TitleView>
  416. }
  417. function errorView() {
  418. if (showErrorPage) {
  419. return <NoData refresh={() => { getCheckData() }} />
  420. }
  421. return <View />
  422. }
  423. function consoleView() {
  424. if (!checkData) {
  425. return <View />
  426. }
  427. return <View className='console_bg'>
  428. {
  429. needSwiper() ? <Swiper className='swiper' indicatorColor='#333'
  430. indicatorActiveColor='#999'
  431. current={swiperIndex}
  432. autoplay={autoPlay}
  433. duration={300}
  434. interval={300}
  435. indicator-offset={[0, -30]}
  436. indicator-height={30}
  437. indicatorDots={global.consoleType == 'idle'}
  438. onChange={(e) => {
  439. setSwiperIndex(e.detail.current)
  440. if (e.detail.current == 0)
  441. setAutoPlay(false)
  442. }}
  443. >
  444. <SwiperItem className='swiperItem'>
  445. <Console />
  446. </SwiperItem>
  447. <SwiperItem className='swiperItem'>
  448. <Console isNextStep={true} />
  449. </SwiperItem>
  450. </Swiper> :
  451. <Console isNextStep={showSingleFastEnd} />
  452. }
  453. </View>
  454. }
  455. usePageScroll((e) => {
  456. if (e.scrollTop > 70) {
  457. setShowTip(true)
  458. }
  459. else {
  460. setShowTip(false)
  461. }
  462. })
  463. function modalContent() {
  464. if (showModal || showModal2) {
  465. if (process.env.TARO_ENV == 'weapp') {
  466. return <Modal
  467. testInfo={debugInfo}
  468. dismiss={() => {
  469. setDebugInfo(null)
  470. setShowModal(false); setShowModal2(false)
  471. }}
  472. confirm={() => { }}>
  473. {
  474. isModal1 ? modalDetail : modalDetail2
  475. }
  476. </Modal>
  477. }
  478. else if (process.env.TARO_ENV == 'rn') {
  479. return <PageContainer style={{ backgroundColor: '#1c1c1c' }}
  480. // overlayStyle='background-color:rgba(0,0,0,0.9)'
  481. // custom-style='background-color:#1c1c1c'
  482. overlayStyle={{ backgroundColor: 'rgba(0,0,0,0.9)' }}
  483. customStyle={{ backgroundColor: '#1c1c1c' }}
  484. closeOnSlideDown={false}
  485. onBeforeEnter={() => {
  486. Taro.hideTabBar();
  487. }}
  488. onBeforeLeave={() => {
  489. Taro.showTabBar();
  490. }}
  491. onClick={() => { alert('b') }}
  492. onClickOverlay={() => { alert('a') }}
  493. onAfterLeave={() => { setShowModal(false); setShowModal2(false) }}
  494. show={showModal || showModal2} round={true} overlay={true} position='bottom'
  495. >
  496. {
  497. isModal1 ? modalDetail : modalDetail2
  498. }
  499. </PageContainer>
  500. }
  501. }
  502. return <View />
  503. }
  504. function detail() {
  505. return (
  506. <Layout type={TemplateType.customHeader} header={headerView()} title={t('page.clock.title')} titleShowStyle={NaviBarTitleShowType.scrollToShow}>
  507. <View style={{ flex: 1, flexDirection: 'column', display: 'flex', backgroundColor: '#000', color: '#fff' }}>
  508. {
  509. needShowAddTip && showTip && <Tooltip title="添加到我的小程序" closeTip={() => { setNeedShowAddTip(false) }} />
  510. }
  511. <Box>
  512. <View className='clock_bg' onClick={tapClock}>
  513. <Clocks showCoverView={!global.showModal} />
  514. </View>
  515. </Box>
  516. {
  517. !user.isLogin && showLogin && <View style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', marginTop: rpxToPx(36) }}>
  518. <ChooseScenarioBtn title={t('feature.auth.login.login_now')} background={ColorType.fast} onClick={tapLogin} />
  519. </View>
  520. }
  521. {
  522. errorView()
  523. }
  524. {
  525. user.isLogin && consoleView()
  526. }
  527. {
  528. user.isLogin && checkData && schedule()
  529. }
  530. {
  531. user.isLogin && <View style={{ backgroundColor: global.isDebug ? 'pink' : 'transparent' }}>
  532. {
  533. checkData && (checkData as any).latest_record &&
  534. <SectionHeader top={48} bottom={24} title={t('feature.track_time_duration.record_fast_sleep.header.latest_record')}>
  535. <Header title='' action={() => {
  536. jumpPage('/pages/common/RecordsHistory?type=time&title=time', 'RecordsHistory', navigation, {
  537. type: 'time',
  538. title: 'time'
  539. })
  540. }} />
  541. </SectionHeader>
  542. }
  543. </View>
  544. }
  545. {
  546. user.isLogin && checkData && (checkData as any).latest_record &&
  547. <RecordFastSleep type='latest' data={(checkData as any).latest_record} delSuccess={getCheckData} index={10000}/>
  548. }
  549. <View style={{ height: process.env.TARO_ENV == 'rn' ? 0 : 100 }} />
  550. </View>
  551. {
  552. modalContent()
  553. }
  554. </Layout>
  555. )
  556. }
  557. // if (process.env.TARO_ENV == 'rn') {
  558. // return <ScrollView>
  559. // {detail()}
  560. // </ScrollView>
  561. // }
  562. return <View>
  563. {detail()}
  564. {/* <Tabbar index={0} /> */}
  565. </View>
  566. }