Index.tsx 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538
  1. import { View, Text, Image, ScrollView, PageContainer, Swiper, SwiperItem, Switch } from "@tarojs/components";
  2. import Tabbar from "@/components/navigation/TabBar";
  3. import IndexItem from '@/features/trackTimeDuration/components/IndexItem';
  4. import Rings from "@/features/trackTimeDuration/components/Rings";
  5. import './Index.scss'
  6. import { useDispatch, useSelector } from "react-redux";
  7. import { useDidHide, useDidShow, useReady, useShareAppMessage } from "@tarojs/taro";
  8. import Taro from "@tarojs/taro";
  9. import { getInfoSuccess } from "@/store/user";
  10. import { clockHome, clockSummaryRecords, clockSummaryStats, getClockRecords, getClocks, getPlans } from "@/services/trackTimeDuration";
  11. import { updateScenario } from "@/store/time";
  12. import { setConfigs } from "@/store/common";
  13. import { setScenario, setStep } from "@/store/scenario";
  14. import { useEffect, useState } from "react";
  15. import { IconPlus, IconRadioCheck, IconRadioCross } from "@/components/basic/Icons";
  16. import { ColorType } from "@/context/themes/color";
  17. import { bigRingRadius, getBgRing, getCommon, getDot, getSchedule, ringWidth, smallRingRadius } from "@/features/trackTimeDuration/hooks/RingData";
  18. import { RealRing, CurrentDot } from "@/features/trackTimeDuration/components/Rings";
  19. import IndexConsole from "@/features/trackTimeDuration/components/IndexConsole";
  20. import Modal from '@/components/layout/Modal'
  21. import { rpxToPx } from "@/utils/tools";
  22. import RecordFastSleep from "@/features/trackTimeDuration/components/RecordFastSleep";
  23. import DayLight from "@/features/trackTimeDuration/components/DayLight";
  24. import { getInfo, latestLocation } from "@/services/user";
  25. import { TimeFormatter } from "@/utils/time_format";
  26. import WeekCalendar from "@/features/trackTimeDuration/components/WeekCalendar";
  27. import { useTranslation } from "react-i18next";
  28. import { jumpPage } from "@/features/trackTimeDuration/hooks/Common";
  29. import Layout from "@/components/layout/layout";
  30. import { ModalType, NaviBarTitleShowType, TemplateType } from "@/utils/types";
  31. import TitleView from "@/features/trackTimeDuration/components/TitleView";
  32. import ClockHeader from "@/features/trackTimeDuration/components/ClockHeader";
  33. import DurationPicker from "@/features/trackTimeDuration/components/DurationPicker";
  34. import SegmentPop from "@/features/trackTimeDuration/components/SegmentPop";
  35. import Box from "@/components/layout/Box";
  36. import DayNightCard from "@/features/trackTimeDuration/components/DayNightCard";
  37. import StageSelector from "@/features/trackTimeDuration/components/StageSelector";
  38. import { ChooseScenarioBtn } from "@/features/common/SpecBtns";
  39. import { clearNightStore, showNight } from "@/store/night";
  40. import { showDay } from "@/store/day";
  41. import { clientInfo } from "@/services/common";
  42. import { changeFastDuration, changeSleepDuration, setCurrentRecord, setSchedule } from "@/store/ring";
  43. import { checkAuthorized } from "@/utils/check_authorized";
  44. import NoData from "@/components/view/NoData";
  45. import { AtActivityIndicator } from "taro-ui";
  46. let GradientText
  47. let useNavigation;
  48. let timer
  49. let pauseTimer = false;
  50. let AppState;
  51. if (process.env.TARO_ENV == 'rn') {
  52. AppState = require("react-native").AppState
  53. GradientText = require('@/components/basic/GradientText').default
  54. useNavigation = require("@react-navigation/native").useNavigation
  55. }
  56. const defaultValue = `[{"scenario":{"name":"FAST_SLEEP","count":0,"schedule":{"fast":{"start_time":"15:00","end_time":"08:00"},"sleep":{"start_time":"22:00","end_time":"07:00"}}},"current_record":{"scenario":"FAST_SLEEP","status":"WAIT_FOR_START","fast":{"status":"WAIT_FOR_START","target_start_time":1710514800000,"target_end_time":1710576000000},"sleep":{"status":"WAIT_FOR_START","target_start_time":1710540000000,"target_end_time":1710572400000}},"wx_pub_followed":false,"time_input_schema":{"min":60,"max":1380,"step":5},"theme_color":{"fast":"#00FFFF","sleep":"#8183FF"}},{"scenarios":[{"name":"FAST","count":0,"schedule":{"fast":{"start_time":"15:00","end_time":"08:00"}}},{"name":"SLEEP","count":0,"schedule":{"sleep":{"start_time":"22:00","end_time":"07:00"}}},{"name":"FAST_SLEEP","count":0,"schedule":{"fast":{"start_time":"15:00","end_time":"08:00"},"sleep":{"start_time":"22:00","end_time":"07:00"}}}],"select_count":0,"theme_color":{"fast":"#00FFFF","sleep":"#8183FF"}}]`
  57. export default function Page() {
  58. const dispatch = useDispatch();
  59. global.dispatch = dispatch;
  60. let navigation;
  61. if (useNavigation) {
  62. navigation = useNavigation()
  63. }
  64. const { t } = useTranslation()
  65. const user = useSelector((state: any) => state.user);
  66. const time = useSelector((state: any) => state.time);
  67. const [count, setCount] = useState(0)
  68. const [homeData, setHomeData] = useState(null)
  69. const [loaded, setLoaded] = useState(false)
  70. const [showErrorPage, setErrorPage] = useState(false)
  71. const [showModal, setShowModal] = useState(false)
  72. const [modalDetail, setModalDetail] = useState<any>(null)
  73. const [showModal2, setShowModal2] = useState(false)
  74. const [modalDetail2, setModalDetail2] = useState<any>(null)
  75. const [debugInfo, setDebugInfo] = useState(null)
  76. const [records, setRecords] = useState([])
  77. const nightStore = useSelector((state: any) => state.night);
  78. useEffect(() => {
  79. timer = setInterval(() => {
  80. if (global.pauseIndexTimer || pauseTimer) {
  81. return
  82. }
  83. setCount((prevCounter) => prevCounter + 1)
  84. }, 1000)
  85. }, [])
  86. useEffect(() => {
  87. if (process.env.TARO_ENV == 'weapp') {
  88. loadWXCache()
  89. }
  90. else {
  91. loadRNCache()
  92. }
  93. if (process.env.TARO_ENV == 'rn') {
  94. AppState.addEventListener('change', handleAppStateChange);
  95. }
  96. }, [])
  97. useEffect(() => {
  98. getCheckData()
  99. global.pauseIndexTimer = !user.isLogin
  100. if (user.isLogin) {
  101. uploadUserClient();
  102. checkAuthorized();
  103. }
  104. else {
  105. dispatch(clearNightStore());
  106. }
  107. }, [user.isLogin, time.status])
  108. useReady(async () => {
  109. const userData = await getStorage('userData');
  110. if (userData) {
  111. dispatch(getInfoSuccess(JSON.parse(userData as string)) as any);
  112. getHistory()
  113. }
  114. // if (process.env.TARO_ENV == 'weapp') {
  115. // useShareAppMessage((e) => {
  116. // return {
  117. // title: t('feature.track_time_duration.common.share_title'),
  118. // path: 'pages/clock/Clock'
  119. // }
  120. // })
  121. // }
  122. })
  123. useDidShow(() => {
  124. checkTimeZone()
  125. setCount(pre => pre + 1)
  126. //resume timer
  127. pauseTimer = false
  128. if (user.isLogin){
  129. getInfo().then(res => {
  130. dispatch(getInfoSuccess(res))
  131. }).catch(e => {
  132. Taro.stopPullDownRefresh()
  133. })
  134. }
  135. })
  136. useDidHide(() => {
  137. //pause timer
  138. pauseTimer = true
  139. })
  140. global.refreshIndex = () => {
  141. setCount((prevCounter) => prevCounter + 1)
  142. }
  143. const handleAppStateChange = (nextAppState) => {
  144. checkTimeZone()
  145. };
  146. function checkTimeZone() {
  147. var split = new Date().toString().split(' ');
  148. var timeZoneFormatted = split[split.length - 2];
  149. Taro.getStorage({
  150. key: 'last_tz',
  151. success: function (res) {
  152. if (res.data && res.data != timeZoneFormatted) {
  153. if (global.currentStatus != 'WAIT_FOR_START') {
  154. Taro.showModal({
  155. title: t('feature.track_time_duration.change_tz_alert.title'),
  156. content: t('feature.track_time_duration.change_tz_alert.content', { tz: timeZoneFormatted }),
  157. showCancel: false,
  158. confirmText: t('feature.track_time_duration.change_tz_alert.confirm'),
  159. })
  160. }
  161. }
  162. },
  163. complete: function () {
  164. Taro.setStorage({ key: 'last_tz', data: timeZoneFormatted })
  165. }
  166. })
  167. }
  168. function uploadUserClient() {
  169. var systemInfo = Taro.getSystemInfoSync();
  170. var split = new Date().toString().split(' ');
  171. var timeZoneFormatted = split[split.length - 2];
  172. clientInfo({
  173. client: {
  174. client_type: process.env.TARO_ENV == 'weapp' ? 'MP' : 'APP',
  175. client_version: process.env.TARO_ENV == 'weapp' ? Taro.getAccountInfoSync().miniProgram.version : '1.0',//'1.0'
  176. wx_version:process.env.TARO_ENV == 'weapp' ?systemInfo.version:'_'
  177. },
  178. meta: {
  179. language: systemInfo.language,
  180. time_zone: {
  181. id: Intl.DateTimeFormat().resolvedOptions().timeZone,
  182. name: timeZoneFormatted
  183. },
  184. },
  185. device: {
  186. brand: systemInfo.brand,
  187. model: systemInfo.model,
  188. platform: systemInfo.platform,
  189. system: systemInfo.system
  190. },
  191. perm: {
  192. wifi_enabled: systemInfo.wifiEnabled,
  193. location_authorized: systemInfo.locationAuthorized,
  194. location_enabled: systemInfo.locationEnabled
  195. }
  196. })
  197. }
  198. function loadWXCache() {
  199. var showDayRing = Taro.getStorageSync('showDayRing') || false;
  200. var showNightRing = Taro.getStorageSync('showNightRing') || false;
  201. dispatch(showDay(showDayRing))
  202. dispatch(showNight(showNightRing))
  203. var gps = Taro.getStorageSync('gps')
  204. if (gps) {
  205. global.locationDetail = JSON.parse(gps)
  206. }
  207. var userData = Taro.getStorageSync('userData')
  208. if (userData) {
  209. dispatch(getInfoSuccess(JSON.parse(userData)));
  210. }
  211. // getCheckData()
  212. }
  213. async function loadRNCache() {
  214. var showDayRing = await getStorage('showDayRing') || false;
  215. var showNightRing = await getStorage('showNightRing') || false;
  216. dispatch(showDay(showDayRing))
  217. dispatch(showNight(showNightRing))
  218. var gps = await getStorage('gps')
  219. if (gps) {
  220. global.locationDetail = JSON.parse(gps)
  221. }
  222. var userData = await getStorage('userData')
  223. if (userData) {
  224. dispatch(getInfoSuccess(JSON.parse(userData)));
  225. }
  226. // getCheckData()
  227. }
  228. function getCheckData() {
  229. Promise.all([getClocks(), getPlans()]).then((list) => {
  230. setErrorPage(false)
  231. setCheckData(list)
  232. }).catch((e) => {
  233. setErrorPage(true)
  234. var list = JSON.parse(defaultValue)
  235. setCheckData(list)
  236. })
  237. getHistory()
  238. }
  239. function setCheckData(list: any) {
  240. setHomeData(list[0])
  241. global.homeData = list[0]
  242. global.currentStatus = list[0].current_record.status;
  243. var array = list[1].scenarios
  244. var schedule = null
  245. array.map(item => {
  246. if (item.name == 'FAST_SLEEP') {
  247. schedule = item.schedule;
  248. }
  249. })
  250. if (user.isLogin) {
  251. dispatch(updateScenario(list[0].current_record))
  252. dispatch(setConfigs(list[0].time_input_schema));
  253. dispatch(setScenario(list[0].scenario));
  254. global.scenario = list[0].scenario.name;
  255. }
  256. dispatch(setCurrentRecord(list[0].current_record))
  257. dispatch(setSchedule(schedule))
  258. setLoaded(true)
  259. }
  260. function getHistory() {
  261. if (user.isLogin)
  262. getClockRecords({
  263. page: 1,
  264. limit: 1,
  265. part_completed: true
  266. // completed: true
  267. }).then(res => {
  268. setRecords((res as any).data)
  269. })
  270. }
  271. global.indexPageRefresh = () => {
  272. getCheckData()
  273. }
  274. global.showIndexModal = (isShow: boolean, detail: any, debugNode?: any) => {
  275. global.showModal = isShow
  276. setDebugInfo(debugNode)
  277. setShowModal(isShow)
  278. setModalDetail(detail)
  279. }
  280. global.showIndexModal2 = (isShow: boolean, detail: any) => {
  281. setDebugInfo(null)
  282. global.showModal = isShow
  283. setShowModal2(isShow)
  284. setModalDetail2(detail)
  285. }
  286. global.changeTargetDuration = (duration: number, isFast: boolean) => {
  287. var obj = JSON.parse(JSON.stringify(homeData))
  288. var record = obj.current_record
  289. if (isFast) {
  290. record.fast.target_end_time = record.fast.target_start_time + duration * 60 * 1000
  291. }
  292. else {
  293. record.sleep.target_end_time = record.sleep.target_start_time + duration * 60 * 1000
  294. }
  295. setHomeData(obj)
  296. }
  297. global.updateFastSleepData = (data: any) => {
  298. if (data.id == (homeData as any).current_record.id) {
  299. var obj = JSON.parse(JSON.stringify(homeData))
  300. obj.current_record = data
  301. setHomeData(obj)
  302. }
  303. switch (data.scenario) {
  304. case 'FAST':
  305. if (data.status == 'WAIT_FOR_START') {
  306. dispatch(changeFastDuration(data.fast.target_end_time - data.fast.target_start_time))
  307. }
  308. break;
  309. case 'SLEEP':
  310. if (data.status == 'WAIT_FOR_START') {
  311. dispatch(changeSleepDuration(data.sleep.target_end_time - data.sleep.target_start_time))
  312. }
  313. break;
  314. case 'FAST_SLEEP':
  315. if (data.status == 'WAIT_FOR_START') {
  316. dispatch(changeFastDuration(data.fast.target_end_time - data.fast.target_start_time))
  317. }
  318. else if (data.status == 'ONGOING1') {
  319. debugger
  320. dispatch(changeSleepDuration(data.sleep.target_end_time - data.sleep.target_start_time))
  321. }
  322. break;
  323. }
  324. }
  325. function modalContent() {
  326. if (showModal || showModal2) {
  327. if (process.env.TARO_ENV == 'weapp') {
  328. return <Modal
  329. testInfo={debugInfo}
  330. dismiss={() => {
  331. setDebugInfo(null)
  332. setShowModal(false);
  333. setShowModal2(false);
  334. global.pauseIndexTimer = false
  335. }}
  336. confirm={() => { }}>
  337. {
  338. showModal ? modalDetail : modalDetail2
  339. }
  340. </Modal>
  341. }
  342. else if (process.env.TARO_ENV == 'rn') {
  343. return <PageContainer style={{ backgroundColor: '#1c1c1c' }}
  344. // overlayStyle='background-color:rgba(0,0,0,0.9)'
  345. // custom-style='background-color:#1c1c1c'
  346. overlayStyle={{ backgroundColor: 'rgba(0,0,0,0.9)' }}
  347. customStyle={{ backgroundColor: '#1c1c1c' }}
  348. closeOnSlideDown={false}
  349. onBeforeEnter={() => {
  350. Taro.hideTabBar();
  351. }}
  352. onBeforeLeave={() => {
  353. Taro.showTabBar();
  354. }}
  355. onClick={() => { alert('b') }}
  356. onClickOverlay={() => { alert('a') }}
  357. onAfterLeave={() => { setShowModal(false); setShowModal2(false); global.pauseIndexTimer = false }}
  358. show={showModal || showModal2} round={true} overlay={true} position='bottom'
  359. >
  360. {
  361. showModal ? modalDetail : modalDetail2
  362. }
  363. </PageContainer>
  364. }
  365. }
  366. return <View />
  367. }
  368. async function getStorage(key: string) {
  369. try {
  370. const res = await Taro.getStorage({ key });
  371. return res.data;
  372. } catch {
  373. return '';
  374. }
  375. }
  376. function more() {
  377. jumpPage('/pages/common/RecordsHistory?type=time&title=time', 'RecordsHistory', navigation, {
  378. type: 'time',
  379. title: 'time'
  380. })
  381. }
  382. function tapLogin() {
  383. if (!user.isLogin) {
  384. jumpPage('/pages/account/ChooseAuth', 'ChooseAuth')
  385. return
  386. }
  387. }
  388. function headerView() {
  389. return <ClockHeader homeData={homeData} />
  390. }
  391. var timestamp = new Date().getTime()
  392. function render() {
  393. if (!loaded) {
  394. return <View style={{ width: rpxToPx(750), height: rpxToPx(900), display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
  395. <AtActivityIndicator size={40} color="#fff"/>
  396. <Tabbar index={0} />
  397. </View>
  398. }
  399. return <Layout type={TemplateType.customHeader} header={headerView()} title={t('page.clock.title')} titleShowStyle={NaviBarTitleShowType.scrollToShow}>
  400. <View className="index_container">
  401. <Text className="count">{count}</Text>
  402. <Box>
  403. <View>
  404. <IndexItem type="FAST_SLEEP" data={homeData} time={timestamp} showStage={false} />
  405. {
  406. user.isLogin ? <IndexConsole record={homeData} /> : <StageSelector />
  407. }
  408. </View>
  409. </Box>
  410. <DayNightCard isNight={true} count={count} />
  411. {
  412. user.isLogin && records.length > 0 && <View style={{ display: 'flex', flexDirection: 'row', justifyContent: 'space-between', marginTop: rpxToPx(40), }}>
  413. {
  414. <Text className="discovery1" style={{ marginBottom: 0 }}>{t('feature.track_time_duration.record_fast_sleep.header.latest_record')}</Text>
  415. }
  416. {
  417. process.env.TARO_ENV == 'weapp' && <Text className="fast_sleep_more index_more" onClick={more}>{t('feature.track_time_duration.record_fast_sleep.header.btn_show_all')}</Text>
  418. }
  419. {
  420. process.env.TARO_ENV == 'rn' && <GradientText onClick={more} style={{ fontSize: rpxToPx(32), fontWeight: 'bold' }}>{t('feature.track_time_duration.record_fast_sleep.header.btn_show_all')}</GradientText>
  421. }
  422. </View>
  423. }
  424. {
  425. user.isLogin && records.length > 0 && <View className="fast_sleep_item_bg">
  426. <RecordFastSleep data={records[0]} type='record' index={-20000} />
  427. </View>
  428. }
  429. {
  430. loaded && !user.isLogin && <View style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', marginTop: rpxToPx(36) }}>
  431. <ChooseScenarioBtn title={t('feature.auth.login.login_now')} background={ColorType.fast} onClick={tapLogin} />
  432. </View>
  433. }
  434. {
  435. showErrorPage && <NoData refresh={() => { getCheckData() }} />
  436. }
  437. {
  438. user.isLogin && !showErrorPage && <View style={{ marginTop: rpxToPx(60), display: 'flex', flexDirection: 'column' }}>
  439. <Text className="discovery1" >周统计</Text>
  440. <WeekCalendar />
  441. </View>
  442. }
  443. <View style={{ height: 100 }} />
  444. {
  445. modalContent()
  446. }
  447. {
  448. homeData && <SegmentPop data={homeData} />
  449. }
  450. {
  451. homeData && <DurationPicker record={(homeData as any).current_record} />
  452. }
  453. <Tabbar index={0} />
  454. </View>
  455. </Layout>
  456. }
  457. // if (process.env.TARO_ENV == 'rn') {
  458. // return <ScrollView>
  459. // {
  460. // render()
  461. // }
  462. // </ScrollView>
  463. // }
  464. return render()
  465. }