ClockIndex.tsx 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617
  1. import { jumpPage } from "@/features/trackTimeDuration/hooks/Common";
  2. import { View, Image, ScrollView, Swiper, SwiperItem, Block } from "@tarojs/components";
  3. import './ClockIndex.scss'
  4. import TabBar from "@/components/navigation/TabBar";
  5. import { IconClose, IconNext } from "@/components/basic/Icons";
  6. import { rpxToPx } from "@/utils/tools";
  7. import { useDispatch, useSelector } from "react-redux";
  8. import { useEffect, useRef, useState } from "react";
  9. import { homeInfo, windows } from "@/services/health";
  10. import dayjs from "dayjs";
  11. import 'dayjs/locale/zh-cn';
  12. import 'dayjs/locale/en';
  13. import { setActions, setEvents, setSceanrioList, setTimeData } from "@/store/record";
  14. import { TimeFormatter } from "@/utils/time_format";
  15. import { getInfo } from "@/services/user";
  16. import Taro from "@tarojs/taro";
  17. import ChooseActions from "./components/choose_actions";
  18. import NewButton, { NewButtonType } from "@/_health/base/new_button";
  19. import { BASE_IMG_URL } from "@/services/http/api";
  20. import { useTranslation } from "react-i18next";
  21. import NoData from "@/_health/components/no_data";
  22. import IndexTab from "./components/index_tab";
  23. import TimeRecord from "@/_record/pages/time_record";
  24. import RecordTime from "./components/record_time";
  25. import RecordLog from "./components/record_log";
  26. import PickerCard from "@/_record/components/picker_card";
  27. import LogPublish from "./components/log_publish";
  28. import RecordTimeResult from "./components/record_time_result";
  29. import { setFastWithSleep, setWindows } from "@/store/health";
  30. import { MainColorType } from "@/context/themes/color";
  31. var timer
  32. let useNavigation, LinearGradient;
  33. let pickerConfirm;
  34. if (process.env.TARO_ENV == 'rn') {
  35. useNavigation = require("@react-navigation/native").useNavigation
  36. LinearGradient = require('react-native-linear-gradient').default
  37. }
  38. export default function ClockIndex() {
  39. const systemInfo: any = Taro.getWindowInfo ? Taro.getWindowInfo() : Taro.getSystemInfoSync();
  40. const navigationBarHeight = systemInfo.statusBarHeight + 44;
  41. const screenHeight = systemInfo.screenHeight
  42. const safeAreaInsets = systemInfo.safeArea; // 获取安全区域信息
  43. // 计算底部安全区域的高度
  44. const bottomSafeAreaHeight = systemInfo.windowHeight - safeAreaInsets.bottom;
  45. const user = useSelector((state: any) => state.user);
  46. const record = useSelector((state: any) => state.record);
  47. const [loaded, setLoaded] = useState(false)
  48. const [showRetry, setShowRetry] = useState(false)
  49. const [home, setHome] = useState<any>(null)
  50. const [count, setCount] = useState(0)
  51. const [currentTimeData, setCurrentTimeData] = useState<any>(null)
  52. const [showChoose, setShowChoose] = useState(false)
  53. const [selScenario, setSelScenario] = useState('')
  54. const [selTag, setSelTag] = useState<any>(null)
  55. const [scenarios, setScenarios] = useState<any>([])
  56. const [tabs, setTabs] = useState<any>([])
  57. const dispatch = useDispatch();
  58. const { t } = useTranslation()
  59. global.dispatch = dispatch;
  60. const [showDatePicker, setShowDatePicker] = useState(false)
  61. const [showDurationPicker, setShowDurationPicker] = useState(false)
  62. const [showEndDatePicker, setShowEndDatePicker] = useState(false)
  63. const [pickerTitle, setPickerTitle] = useState('')
  64. const [pickerValue, setPickerValue] = useState<any>(null)
  65. const [showLogPublish, setShowLogPublish] = useState(false)
  66. const startPickerRef = useRef(showDatePicker)
  67. const endPickerRef = useRef(showEndDatePicker)
  68. const durationPickerRef = useRef(showDurationPicker)
  69. const [tags, setTags] = useState<any>([])
  70. const [addTag, setAddTag] = useState(false)
  71. const [showTimeResult, setShowTimeResult] = useState(false)
  72. const [timeResult, setTimeResult] = useState<any>(null)
  73. const [current, setCurrent] = useState(-1)
  74. const currentRef = useRef(current)
  75. const [swiperHeight] = useState(screenHeight - navigationBarHeight - rpxToPx(108) - rpxToPx(112) - bottomSafeAreaHeight + 4)
  76. dayjs.locale(global.language == 'en' ? 'en' : 'zh-cn');
  77. let navigation;
  78. if (useNavigation) {
  79. navigation = useNavigation()
  80. }
  81. useEffect(() => {
  82. getHomeData()
  83. }, [user.isLogin])
  84. useEffect(()=>{
  85. currentRef.current = current
  86. },[current])
  87. useEffect(() => {
  88. startPickerRef.current = showDatePicker
  89. endPickerRef.current = showEndDatePicker
  90. durationPickerRef.current = showDurationPicker
  91. }, [showDatePicker, showDurationPicker, showEndDatePicker])
  92. useEffect(() => {
  93. downloadFile()
  94. }, [])
  95. function downloadFile() {
  96. Taro.downloadFile({
  97. url: BASE_IMG_URL + 'cp_check_f.png',
  98. success: (res) => {
  99. if (res.statusCode === 200) {
  100. global.checkFastImg = res.tempFilePath
  101. } else {
  102. }
  103. },
  104. fail: (err) => {
  105. }
  106. });
  107. Taro.downloadFile({
  108. url: BASE_IMG_URL + 'cp_check_s.png',
  109. success: (res) => {
  110. if (res.statusCode === 200) {
  111. global.checkSleepImg = res.tempFilePath
  112. } else {
  113. }
  114. },
  115. fail: (err) => {
  116. }
  117. });
  118. }
  119. function getHomeData() {
  120. getWindows()
  121. homeInfo().then(res => {
  122. setLoaded(true)
  123. setHome(res)
  124. setCount(1)
  125. dispatch(setEvents((res as any).events))
  126. dispatch(setActions((res as any).actions))
  127. dispatch(setSceanrioList((res as any).scenarios))
  128. if ((res as any).scenarios) {
  129. setScenarios((res as any).scenarios)
  130. var active_scenario = (res as any).active_scenario
  131. setTabs((res as any).scenarios.map(((item, index) => {
  132. if (item.scenario == active_scenario && currentRef.current == -1) {
  133. setCurrent(index)
  134. }
  135. return item.title
  136. })))
  137. }
  138. setShowRetry(false)
  139. }).catch(e => {
  140. setShowRetry(true)
  141. setCurrent(0)
  142. })
  143. }
  144. function getWindows() {
  145. windows().then(res => {
  146. // setLoaded(true)
  147. // setShowRetry(false)
  148. // if (!(res as any).windows.night_day.night.target) {
  149. // var date = new Date()
  150. // var hour = date.getHours()
  151. // if (hour >= 6 && hour < 18) {
  152. // var date1 = new Date()
  153. // date1.setHours(6)
  154. // date1.setMinutes(0)
  155. // date1.setSeconds(0)
  156. // var date2 = new Date()
  157. // date2.setHours(18)
  158. // date2.setMinutes(0)
  159. // date2.setSeconds(0);
  160. // (res as any).windows.night_day.day.target = {
  161. // start_timestamp: date1.getTime(),
  162. // end_timestamp: date2.getTime(),
  163. // duration: 12 * 60 * 60 * 1000
  164. // };
  165. // (res as any).windows.night_day.night.target = {
  166. // start_timestamp: date2.getTime(),
  167. // end_timestamp: date2.getTime() + 12 * 60 * 60 * 1000,
  168. // duration: 12 * 60 * 60 * 1000
  169. // }
  170. // }
  171. // else {
  172. // var date1 = new Date()
  173. // date1.setHours(18)
  174. // date1.setMinutes(0)
  175. // date1.setSeconds(0);
  176. // (res as any).windows.night_day.day.target = {
  177. // start_timestamp: date1.getTime(),
  178. // end_timestamp: date1.getTime() + 12 * 60 * 60 * 1000,
  179. // duration: 12 * 60 * 60 * 1000
  180. // };
  181. // (res as any).windows.night_day.night.target = {
  182. // start_timestamp: date1.getTime() + 12 * 60 * 60 * 1000,
  183. // end_timestamp: date1.getTime() + 12 * 60 * 60 * 1000 + 12 * 60 * 60 * 1000,
  184. // duration: 12 * 60 * 60 * 1000
  185. // }
  186. // }
  187. // }
  188. dispatch(setFastWithSleep((res as any).fast_with_sleep))
  189. dispatch(setWindows((res as any).windows))
  190. // dispatch(setLongFast((res as any).long_fast))
  191. // dispatch(setRefreshs((res as any).refresh_timestamps))
  192. // dispatch(setFinishSetup((res as any).finish_setup))
  193. }).catch(e => {
  194. })
  195. }
  196. useEffect(() => {
  197. getInfo()
  198. Taro.eventCenter.on('refreshClockIndex', getHomeData)
  199. if (timer) {
  200. clearInterval(timer)
  201. }
  202. timer = setInterval(() => {
  203. if (startPickerRef.current || endPickerRef.current || durationPickerRef.current) {
  204. return
  205. }
  206. // console.log(showDatePicker , showDurationPicker , showEndDatePicker)
  207. setCount(pre => pre + 1)
  208. }, 1000)
  209. return () => {
  210. clearInterval(timer)
  211. Taro.eventCenter.off('refreshClockIndex')
  212. }
  213. }, [])
  214. useEffect(() => {
  215. Taro.eventCenter.trigger('hideTab', showChoose)
  216. }, [showChoose])
  217. useEffect(() => {
  218. getTime()
  219. }, [count])
  220. useEffect(() => {
  221. if (currentTimeData) {
  222. dispatch(setTimeData(currentTimeData))
  223. }
  224. }, [currentTimeData])
  225. function tapItem(index) {
  226. if (!user.isLogin) {
  227. jumpPage('/_account/pages/ChooseAuth', 'ChooseAuth', navigation)
  228. return
  229. }
  230. var scenarioObj = scenarios[index]
  231. switch (scenarioObj.scenario) {
  232. case 'MEAL':
  233. setShowChoose(true)
  234. setSelScenario('MEAL')
  235. break;
  236. case 'ACTIVITY':
  237. setShowChoose(true)
  238. setSelScenario('ACTIVITY')
  239. break;
  240. case 'FAST':
  241. jumpPage(`/_record/pages/time_record?scenario=FAST`, 'TimeRecord', navigation, {
  242. scenario: 'FAST'
  243. })
  244. break
  245. case 'SLEEP':
  246. jumpPage(`/_record/pages/time_record?scenario=SLEEP`, 'TimeRecord', navigation, {
  247. scenario: 'SLEEP'
  248. })
  249. break
  250. case 'METRIC':
  251. jumpPage('/pages/metric/Metric')
  252. break
  253. case 'MOVE':
  254. jumpPage('/_health/pages/move')
  255. break;
  256. }
  257. }
  258. function getTime() {
  259. if (!home) return
  260. var now = dayjs().format('HH:mm')
  261. for (var i = 0; i < home.time_messages.length; i++) {
  262. var obj = home.time_messages[i]
  263. if (now >= obj.start_time && now < obj.end_time) {
  264. setCurrentTimeData(obj)
  265. return
  266. }
  267. }
  268. setCurrentTimeData(home.time_messages[home.time_messages.length - 1])
  269. }
  270. function getBackground() {
  271. var time = record.time
  272. if (!time) return '#fff'
  273. const { background_colors } = time
  274. if (!background_colors) {
  275. return '#fff'
  276. }
  277. else if (background_colors.length == 1) {
  278. return background_colors[0]
  279. }
  280. return `linear-gradient(to bottom, ${background_colors[0]}, ${background_colors[1]})`
  281. }
  282. function itemTime(item) {
  283. if (item.event && item.event.status == 'OG') {
  284. return TimeFormatter.countdown(item.event.time.start_timestamp)
  285. }
  286. return ''
  287. }
  288. function pickerColor(){
  289. var obj = scenarios[current]
  290. if (obj.theme_color) {
  291. return obj.theme_color
  292. }
  293. return MainColorType.orange
  294. }
  295. function showPicker(type, title, value, confirm) {
  296. setPickerTitle(title)
  297. setPickerValue(value)
  298. // setPickerFunc(confirm)
  299. pickerConfirm = confirm
  300. switch (type) {
  301. case 'duration':
  302. setShowDurationPicker(true)
  303. break
  304. case 'start':
  305. setShowDatePicker(true)
  306. break
  307. case 'end':
  308. setShowEndDatePicker(true)
  309. break
  310. }
  311. }
  312. function hidePicker() {
  313. setShowDatePicker(false)
  314. setShowEndDatePicker(false)
  315. setShowDurationPicker(false)
  316. }
  317. const array = global.language == 'en' ? ['Eat', 'Workout', 'Fast', 'Sleep'] : ['饮食', '运动', '断食', '睡眠']
  318. if (!loaded && showRetry) return <View style={{ position: 'relative' }}>
  319. <View style={{ height: navigationBarHeight }} />
  320. <IndexTab items={array} current={current} onChanged={(index) => {
  321. setCurrent(index)
  322. }} />
  323. <NoData refresh={
  324. () => {
  325. getHomeData()
  326. }
  327. } />
  328. </View>
  329. function bgView() {
  330. if (process.env.TARO_ENV == 'weapp') {
  331. return <View className="main_bg" style={{ background: getBackground() }} />
  332. }
  333. var time = record.time
  334. if (!time) return <View />
  335. const { background_colors } = time
  336. if (!background_colors) {
  337. return <View />
  338. }
  339. else if (background_colors.length == 1) {
  340. return <View />
  341. }
  342. return <LinearGradient style={{
  343. position: 'absolute',
  344. left: 0,
  345. top: 0,
  346. width: rpxToPx(750),
  347. height: screenHeight,
  348. zIndex: 0,
  349. pointerEvents: 'none'
  350. }}
  351. colors={[background_colors[0], background_colors[1]]}
  352. start={{ x: 0, y: 0 }}
  353. end={{ x: 0, y: 1 }} pointerEvents="none" />
  354. }
  355. // function swiperHeight() {
  356. // return screenHeight - navigationBarHeight - rpxToPx(108) - rpxToPx(112) - bottomSafeAreaHeight + 4
  357. // }
  358. if (!loaded) return <View />
  359. return <View style={{ position: 'relative' }}>
  360. {
  361. bgView()
  362. }
  363. <View style={{ height: navigationBarHeight }} />
  364. <IndexTab items={tabs} current={current} onChanged={(index) => {
  365. setCurrent(index)
  366. }} />
  367. <Swiper style={{ height: swiperHeight, width: rpxToPx(750) }} current={current} onChange={e => {
  368. setCurrent(e.detail.current)
  369. }}>
  370. {
  371. scenarios.map((item, index) => {
  372. return <SwiperItem key={index}>
  373. {
  374. item.scenario == 'FAST' && <RecordTime scenario="FAST"
  375. event={item.event}
  376. theme_color={item.theme_color}
  377. contentHeight={swiperHeight}
  378. showPicker={showPicker}
  379. hidePicker={hidePicker}
  380. complete={info => {
  381. setTimeResult(info)
  382. setSelScenario('FAST')
  383. setShowTimeResult(true)
  384. }}
  385. count={count} />
  386. }
  387. {
  388. item.scenario == 'SLEEP' && <RecordTime scenario="SLEEP"
  389. event={item.event}
  390. theme_color={item.theme_color}
  391. contentHeight={swiperHeight}
  392. showPicker={showPicker} hidePicker={hidePicker}
  393. complete={info => {
  394. setTimeResult(info)
  395. setSelScenario('SLEEP')
  396. setShowTimeResult(true)
  397. }}
  398. count={count} />
  399. }
  400. {
  401. item.scenario == 'MEAL' && <RecordLog scenario="MEAL"
  402. tags={item.tags}
  403. contentHeight={swiperHeight}
  404. showPublish={(scenario, tag, tags, addTag) => {
  405. setAddTag(addTag)
  406. setShowLogPublish(true)
  407. setSelScenario(scenario)
  408. setSelTag(tag)
  409. setTags(tags)
  410. }} />
  411. }
  412. {
  413. item.scenario == 'ACTIVITY' && <RecordLog
  414. tags={item.tags}
  415. scenario="ACTIVITY"
  416. contentHeight={swiperHeight}
  417. showPublish={(scenario, tag, tags, addTag) => {
  418. setAddTag(addTag)
  419. setShowLogPublish(true)
  420. setSelScenario(scenario)
  421. setSelTag(tag)
  422. setTags(tags)
  423. }} />
  424. }
  425. </SwiperItem>
  426. })
  427. }
  428. {/* <SwiperItem>
  429. <RecordTime scenario="FAST"
  430. contentHeight={swiperHeight()}
  431. showPicker={showPicker}
  432. hidePicker={hidePicker}
  433. complete={info => {
  434. setTimeResult(info)
  435. setScenarios('FAST')
  436. setShowTimeResult(true)
  437. }}
  438. count={count} />
  439. </SwiperItem>
  440. <SwiperItem>
  441. <RecordTime scenario="SLEEP"
  442. contentHeight={swiperHeight()}
  443. showPicker={showPicker} hidePicker={hidePicker}
  444. complete={info => {
  445. setTimeResult(info)
  446. setScenarios('SLEEP')
  447. setShowTimeResult(true)
  448. }}
  449. count={count} />
  450. </SwiperItem>
  451. <SwiperItem>
  452. <RecordLog scenario="MEAL" contentHeight={swiperHeight()} showPublish={(scenario, tag, tags, addTag) => {
  453. setAddTag(addTag)
  454. setShowLogPublish(true)
  455. setSelScenario(scenario)
  456. setSelTag(tag)
  457. setTags(tags)
  458. }} />
  459. </SwiperItem>
  460. <SwiperItem>
  461. <RecordLog scenario="ACTIVITY" contentHeight={swiperHeight()} showPublish={(scenario, tag, tags, addTag) => {
  462. setAddTag(addTag)
  463. setShowLogPublish(true)
  464. setSelScenario(scenario)
  465. setSelTag(tag)
  466. setTags(tags)
  467. }} />
  468. </SwiperItem> */}
  469. </Swiper>
  470. {
  471. showChoose && <ChooseActions
  472. close={() => {
  473. setShowChoose(false)
  474. }}
  475. quick={() => {
  476. jumpPage(`/_record/pages/log_record?scenario=${selScenario}&quick=1`, 'LogRecord', navigation, {
  477. scenario: selScenario,
  478. quick: 1
  479. })
  480. }}
  481. chooseImg={(array) => {
  482. jumpPage(`/_record/pages/log_record?scenario=${selScenario}&imgs=${JSON.stringify(array)}`, 'LogRecord', navigation, {
  483. scenario: selScenario,
  484. imgs: JSON.stringify(array)
  485. })
  486. }}
  487. chooseText={() => {
  488. jumpPage(`/_record/pages/log_record?scenario=${selScenario}&only_text=1`, 'LogRecord', navigation, {
  489. scenario: selScenario,
  490. only_text: 1
  491. })
  492. }}
  493. />
  494. }
  495. <Block>
  496. {
  497. showDurationPicker && <PickerCard onClose={() => { setShowDurationPicker(false) }}
  498. color={pickerColor()}
  499. value={pickerValue}
  500. type="duration"
  501. title={pickerTitle}
  502. onConfirm={(e) => {
  503. // pickerFunc(e)
  504. pickerConfirm(e)
  505. }}
  506. />
  507. }
  508. </Block>
  509. <Block>
  510. {
  511. showDatePicker && <PickerCard onClose={() => { setShowDatePicker(false) }}
  512. color={pickerColor()}
  513. value={pickerValue}
  514. type="datetime"
  515. title={pickerTitle}
  516. onConfirm={(e) => {
  517. // pickerFunc(e)
  518. pickerConfirm(e)
  519. }}
  520. />
  521. }
  522. </Block>
  523. <Block>
  524. {
  525. showEndDatePicker && <PickerCard onClose={() => { setShowEndDatePicker(false) }}
  526. color={pickerColor()}
  527. value={pickerValue}
  528. type="datetime"
  529. title={pickerTitle}
  530. onConfirm={(e) => {
  531. // pickerFunc(e)
  532. pickerConfirm(e)
  533. }}
  534. />
  535. }
  536. </Block>
  537. <Block>
  538. {
  539. showLogPublish && <LogPublish scenario={selScenario}
  540. tags={tags}
  541. tag={selTag}
  542. addTag={addTag}
  543. onClose={() => {
  544. setShowLogPublish(false)
  545. }} />
  546. }
  547. </Block>
  548. <Block>
  549. {
  550. showTimeResult && <RecordTimeResult
  551. showPicker={showPicker}
  552. hidePicker={hidePicker}
  553. onClose={() => setShowTimeResult(false)}
  554. scenario={selScenario}
  555. info={timeResult}
  556. goEat={() => {
  557. setCurrent(0)
  558. setShowTimeResult(false)
  559. }}
  560. />
  561. }
  562. </Block>
  563. {
  564. process.env.TARO_ENV == 'weapp' && <TabBar index={0} />
  565. }
  566. </View>
  567. }