Metric.tsx 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456
  1. import { View, Text, Image, PageContainer } from "@tarojs/components";
  2. import './Metric.scss'
  3. import { useDispatch, useSelector } from "react-redux";
  4. import { useEffect, useRef, useState } from "react";
  5. import Taro from "@tarojs/taro";
  6. import { metricCards, metricFollows, metricGroups, uploadMetric, uploadSteps } from "@/services/trackSomething";
  7. import { TimeFormatter } from "@/utils/time_format";
  8. import MetricItem from "./MetricItem";
  9. import NoData from "@/components/view/NoData";
  10. import Layout from "@/components/layout/layout";
  11. import { MetricModalType, ModalType, NaviBarTitleShowType, TemplateType } from "@/utils/types";
  12. import { useTranslation } from "react-i18next";
  13. import { jumpPage } from "@/features/trackTimeDuration/hooks/Common";
  14. import TitleView from "@/features/trackTimeDuration/components/TitleView";
  15. import { setTabbarStatus } from "@/store/common";
  16. import MetricModalChoose from "./MetricModalChoose";
  17. import MetricModalOrder from './MetricModalOrder';
  18. import MetricModalAdd from "./MetricModalAdd";
  19. import MetricModalTime from "./MetricModalTime";
  20. import Modal from "@/components/layout/Modal";
  21. import { rpxToPx } from "@/utils/tools";
  22. let useNavigation;
  23. if (process.env.TARO_ENV == 'rn') {
  24. useNavigation = require("@react-navigation/native").useNavigation
  25. }
  26. export default function Component(props: any) {
  27. const { t } = useTranslation()
  28. const user = useSelector((state: any) => state.user);
  29. const [list, setList] = useState([])
  30. const [metricItem, setMetricItem] = useState({})
  31. const [strTime, setStrTime] = useState('')
  32. const [time, setTime] = useState(0)
  33. const [showErrorPage, setErrorPage] = useState(false)
  34. const [setupTime, setSetupTime] = useState(0)
  35. const [triggered, setTriggered] = useState(true)
  36. const [count, setCount] = useState(0)
  37. const [showPageContainer, setShowPageContainer] = useState(false)
  38. const [modalType, setModalType] = useState(MetricModalType.none)
  39. const [themeColor, setThemeColor] = useState('#00ffff')
  40. const [groups, setGroups] = useState([])
  41. const [orignalGroups, setOrignalGroups] = useState([])
  42. const [limits, setLimits] = useState(null)
  43. const [orders, setOrders] = useState([])
  44. const [newOrders, setNewOrders] = useState([])
  45. const [resultOrders, setResultOrders] = useState([])
  46. const [tempMetricItem, setTempMetricItem] = useState(null)
  47. const [loaded, setLoaded] = useState(false)
  48. const dispatch = useDispatch();
  49. let navigation;
  50. if (useNavigation) {
  51. navigation = useNavigation()
  52. }
  53. //未登录<->已登录 状态切换时,执行一次授权检查
  54. useEffect(() => {
  55. getCards();
  56. getGroups();
  57. const now = new Date();
  58. const nextMidnight = new Date(now.getFullYear(), now.getMonth(), now.getDate() + 1, 0, 0, 0);
  59. const timeUntilMidnight = nextMidnight.getTime() - now.getTime();
  60. setTimeout(() => {
  61. setCount(count + 1)
  62. }, timeUntilMidnight);
  63. }, [user.isLogin])
  64. const openModal = () => {
  65. setSetupTime(new Date().getTime())
  66. setModalType(MetricModalType.add)
  67. setShowPageContainer(true)
  68. };
  69. global.refreshMetric = () => {
  70. getCards()
  71. }
  72. function getCards() {
  73. setTriggered(true)
  74. metricCards().then(res => {
  75. Taro.stopPullDownRefresh()
  76. setErrorPage(false)
  77. setList((res as any).cards)
  78. setTriggered(false)
  79. if ((res as any).cards.length > 0) {
  80. var obj = (res as any).cards[0]
  81. setThemeColor(obj.theme_color)
  82. }
  83. var list: any = [];
  84. (res as any).cards.map(item => {
  85. list.push({
  86. name: item.name,
  87. code: item.code,
  88. is_following: true
  89. })
  90. })
  91. setOrders(list)
  92. setResultOrders(list)
  93. setLoaded(true)
  94. }).catch(e => {
  95. Taro.stopPullDownRefresh()
  96. if (list.length == 0) {
  97. setErrorPage(true)
  98. }
  99. setTriggered(false)
  100. setLoaded(false)
  101. })
  102. }
  103. function getGroups() {
  104. metricGroups().then(res => {
  105. var array = (res as any).groups
  106. setOrignalGroups(JSON.parse(JSON.stringify(array)))
  107. setGroups(array)
  108. setLimits((res as any).num_options_limit)
  109. setNewOrders([])
  110. })
  111. }
  112. //ts 把数组items: [{code: "_walk", value: 2180},{code: "_walk", value: 4444}]中的value取出来,/分割,组成字符串,如2180/4444
  113. function getValues(items) {
  114. var values = ''
  115. items.map((item, index) => {
  116. if (index == 0) {
  117. values = item.value
  118. }
  119. else {
  120. values = values + '/' + item.value
  121. }
  122. })
  123. return values
  124. }
  125. function goDetail(item) {
  126. if (user.isLogin) {
  127. if (!item.latest_record) {
  128. return
  129. }
  130. jumpPage('/pages/common/RecordsHistory?type=metric&refreshList=getCards&code=' + item.code + `&title=${item.name}` + '&themeColor=' + item.theme_color)
  131. }
  132. else {
  133. jumpPage('/pages/account/ChooseAuth', 'ChooseAuth', navigation)
  134. }
  135. }
  136. function record(item: any) {
  137. if (user.isLogin) {
  138. var now = new Date();
  139. var t = (now.getHours() < 10 ? '0' + now.getHours() : now.getHours()) + ":" + (now.getMinutes() < 10 ? '0' + now.getMinutes() : now.getMinutes());
  140. // setStrTime(t)
  141. setStrTime(TimeFormatter.dateTimeFormate(now.getTime()))
  142. setTime(now.getTime())
  143. setMetricItem(item)
  144. openModal()
  145. }
  146. else {
  147. jumpPage('/pages/account/ChooseAuth', 'ChooseAuth', navigation)
  148. }
  149. }
  150. function chooseTime(e) {
  151. setTime(e);
  152. setStrTime(TimeFormatter.dateTimeFormate(e))
  153. }
  154. const limitDay = 500
  155. const limit = new Date().getTime() - limitDay * 3600 * 1000 * 24;
  156. function detail() {
  157. return <View>
  158. <View className="metric_container">
  159. {
  160. list.map((item: any, index: number) => {
  161. var unit = ''
  162. var value = t('feature.track_something.metric.no_record')
  163. var desc = t('feature.track_something.metric.check_unlock_data')
  164. var showDetail = false;
  165. if (item.latest_record) {
  166. unit = item.schemas[0].default_unit
  167. value = getValues(item.latest_record.items)
  168. desc = TimeFormatter.dateDescription(item.latest_record.timestamp, true)
  169. showDetail = true
  170. }
  171. if (!user.isLogin) {
  172. value = t('feature.track_something.metric.un_login')
  173. desc = t('feature.track_something.metric.login_can_check')
  174. }
  175. return <MetricItem title={item.name}
  176. value={value}
  177. unit={unit}
  178. desc={desc}
  179. btnText={t('feature.track_something.btn_record')}
  180. isDisabled={false}
  181. showDetail={showDetail}
  182. themeColor={item.theme_color}
  183. onClickDetail={() => { goDetail(item) }}
  184. onClick={() => { record(item) }}
  185. />
  186. })
  187. }
  188. {
  189. user.isLogin && <View className="add_more" onClick={addBtnClick}>
  190. <Image style={{ width: rpxToPx(48), height: rpxToPx(48) }} src={require('@assets/images/add2.png')} />
  191. <Text className="add_more_text">添加更多</Text>
  192. </View>
  193. }
  194. </View>
  195. <View className="space_width" ></View>
  196. </View>
  197. }
  198. function addBtnClick() {
  199. Taro.showActionSheet({
  200. itemList: [t('feature.track_something.metric.choose_metric'),
  201. t('feature.track_something.metric.order')]
  202. })
  203. .then(res => {
  204. switch (res.tapIndex) {
  205. case 0:
  206. global.metricAdd = true
  207. setModalType(MetricModalType.choose)
  208. setShowPageContainer(true)
  209. break;
  210. case 1:
  211. global.metricAdd = false
  212. setModalType(MetricModalType.order)
  213. setShowPageContainer(true)
  214. break;
  215. }
  216. })
  217. .catch(err => {
  218. console.log(err.errMsg)
  219. })
  220. }
  221. function headerView() {
  222. return <TitleView title={t('page.metric.title')} showAddBtn={loaded && !showErrorPage ? true : false} onClick={addBtnClick}>
  223. </TitleView>
  224. }
  225. function metricModalContent() {
  226. debugger
  227. switch (modalType) {
  228. case MetricModalType.choose:
  229. return <MetricModalChoose
  230. themeColor={themeColor}
  231. cancel={modalCancel}
  232. confirm={modalConfirm}
  233. array={groups}
  234. orders={orders}
  235. newOrders={newOrders}
  236. limit={limits}
  237. />
  238. case MetricModalType.order:
  239. return <MetricModalOrder
  240. themeColor={themeColor}
  241. cancel={modalOrderCancel}
  242. confirm={modalOrderConfirm}
  243. array={resultOrders} />
  244. case MetricModalType.add:
  245. return <MetricModalAdd
  246. item={tempMetricItem ? tempMetricItem : metricItem}
  247. strTime={strTime}
  248. showPicker={(tempItem) => {
  249. var temp = JSON.parse(JSON.stringify(tempItem))
  250. temp.schemas.map(item => {
  251. if (item.tempValue) {
  252. item.default_value = item.tempValue
  253. }
  254. })
  255. setTempMetricItem(temp)
  256. setModalType(MetricModalType.time)
  257. }}
  258. cancel={modalAddCancel}
  259. confirm={modalAddConfirm} />
  260. case MetricModalType.time:
  261. return <MetricModalTime
  262. item={metricItem}
  263. time={time}
  264. limit={limit}
  265. limitDay={limitDay}
  266. cancel={() => {
  267. setModalType(MetricModalType.add)
  268. }}
  269. confirm={(e) => {
  270. chooseTime(e)
  271. setModalType(MetricModalType.add)
  272. }}
  273. />
  274. }
  275. return <View />
  276. }
  277. function modalCancel() {
  278. setShowPageContainer(false)
  279. onPageContainerCancel()
  280. }
  281. function modalConfirm(datas, newOrders, resultOrders, groups) {
  282. setOrders(datas)
  283. setGroups(groups)
  284. setNewOrders(newOrders)
  285. setResultOrders(resultOrders)
  286. setModalType(MetricModalType.order)
  287. }
  288. function modalOrderCancel() {
  289. if (global.metricAdd) {
  290. setModalType(MetricModalType.choose)
  291. }
  292. else {
  293. setShowPageContainer(false)
  294. onPageContainerCancel()
  295. }
  296. }
  297. function modalOrderConfirm(datas) {
  298. var array: any = []
  299. datas.map(item => {
  300. array.push(item.code)
  301. })
  302. metricFollows({ codes: array }).then(res => {
  303. getCards()
  304. getGroups()
  305. setList((res as any).cards)
  306. // setOrignalGroups(groups)
  307. })
  308. setShowPageContainer(false)
  309. }
  310. function modalAddCancel() {
  311. setShowPageContainer(false)
  312. onPageContainerCancel()
  313. }
  314. function modalAddConfirm(result) {
  315. setShowPageContainer(false)
  316. var date = new Date(time)
  317. var strDate = (date.getFullYear() + '') + (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : (date.getMonth() + 1)) + (date.getDate() < 10 ? '0' + date.getDate() : date.getDate());
  318. var array: any[] = [];
  319. result.schemas.map((item, index) => {
  320. array.push({
  321. code: item.code,
  322. value: item.tempValue && item.tempValue > 0 ? item.tempValue : item.default_value
  323. })
  324. })
  325. var params = {
  326. code: result.code,
  327. timestamp: time,
  328. date: strDate,
  329. items: array,
  330. extra: {
  331. set_time: setupTime,
  332. confirm_time: new Date().getTime()
  333. }
  334. }
  335. global.postBtnUpdateStatus('normal');
  336. uploadMetric(params).then(res => {
  337. // getCards();
  338. result.schemas.map((item, index) => {
  339. item.tempValue = ''
  340. })
  341. list.map((item, index) => {
  342. if ((item as any).code == (res as any).code) {
  343. (item as any).latest_record = (res as any).latest_record;
  344. (item as any).schemas = (res as any).schemas;
  345. }
  346. })
  347. setList(JSON.parse(JSON.stringify(list)))
  348. global.postBtnUpdateStatus('idle');
  349. setTimeout(() => {
  350. setCount(count + 1)
  351. }, 31000)
  352. })
  353. }
  354. function onPageContainerCancel() {
  355. if (modalType == MetricModalType.choose || modalType == MetricModalType.order) {
  356. debugger
  357. var array: any = [];
  358. list.map(item => {
  359. array.push({
  360. name: (item as any).name,
  361. code: (item as any).code,
  362. is_following: true
  363. })
  364. })
  365. // debugger
  366. setOrders(array)
  367. setNewOrders([])
  368. setGroups(JSON.parse(JSON.stringify(orignalGroups)))
  369. // setGroups(orignalGroups)
  370. }
  371. else {
  372. setTempMetricItem(null)
  373. }
  374. }
  375. return <View style={{ position: 'relative' }}>
  376. <Layout children={showErrorPage ? <NoData refresh={() => { getCards() }} /> : detail()}
  377. title={t('page.metric.title')}
  378. type={TemplateType.customHeader}
  379. header={headerView()}
  380. refresh={() => { getCards() }}
  381. triggered={triggered}
  382. titleShowStyle={NaviBarTitleShowType.scrollToShow}
  383. />
  384. {
  385. showPageContainer && <Modal dismiss={() => {
  386. onPageContainerCancel()
  387. setShowPageContainer(false)
  388. }} confirm={() => { }}>
  389. {
  390. metricModalContent()
  391. }
  392. </Modal>
  393. }
  394. {/* <PageContainer style={{ backgroundColor: '#1c1c1c' }}
  395. overlayStyle='background-color:rgba(0,0,0,0.9)'
  396. custom-style='background-color:#1c1c1c'
  397. closeOnSlideDown={false}
  398. show={showPageContainer} round={true} overlay={true} position='bottom'
  399. onClickOverlay={onPageContainerCancel}
  400. onAfterLeave={() => { setShowPageContainer(false); setModalType(MetricModalType.none) }}
  401. onBeforeEnter={() => { dispatch(setTabbarStatus(false));Taro.hideTabBar() }}
  402. onBeforeLeave={() => { dispatch(setTabbarStatus(true));Taro.showTabBar() }}
  403. >
  404. {
  405. metricModalContent()
  406. }
  407. </PageContainer> */}
  408. </View>
  409. }