Clock.weapp.tsx 16 KB

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