Metric.tsx 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411
  1. import { View, Text, ScrollView } from "@tarojs/components";
  2. import './Metric.scss'
  3. import { setAuth } from "../hooks/werun";
  4. import { usePullDownRefresh, useReady } from "@tarojs/taro";
  5. import { useSelector } from "react-redux";
  6. import { useEffect, useRef, useState } from "react";
  7. import Taro from "@tarojs/taro";
  8. import { metricCards, uploadMetric, uploadSteps } from "@/services/trackSomething";
  9. import { TimeFormatter } from "@/utils/time_format";
  10. import MetricItem from "./MetricItem";
  11. import { get } from "http";
  12. import Modal from "@/components/layout/Modal";
  13. import PickerViews from "@/components/input/PickerViews";
  14. import LimitPickers from "@/components/input/LimitPickers";
  15. import SlidngScale from "@/components/input/SlidngScale";
  16. import NoData from "@/components/view/NoData";
  17. import { alphaToHex } from "@/utils/tools";
  18. import Layout from "@/components/layout/layout";
  19. import { NaviBarTitleShowType, TemplateType } from "@/utils/types";
  20. import { useTranslation } from "react-i18next";
  21. export default function Component(props: any) {
  22. const { t } = useTranslation()
  23. const user = useSelector((state: any) => state.user);
  24. const [list, setList] = useState([])
  25. const [isModalOpen, setIsModalOpen] = useState(false);
  26. const [isTimePickerOpen, setIsTimePickerOpen] = useState(false);
  27. const [pickerValue, setPickerValue] = useState([]);
  28. const [pickerItems, setPickerItems] = useState([]);
  29. const [isPoint, setIsPoint] = useState(false)
  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 limitPickerRef = useRef<any>(null);
  37. //未登录<->已登录 状态切换时,执行一次授权检查
  38. useEffect(() => {
  39. getCards();
  40. }, [user.isLogin])
  41. const openModal = () => {
  42. setSetupTime(new Date().getTime())
  43. setIsModalOpen(true);
  44. };
  45. const closeModal = () => {
  46. setIsModalOpen(false);
  47. };
  48. global.refreshMetric = () => {
  49. getCards()
  50. }
  51. function getCards() {
  52. setTriggered(true)
  53. console.log('get Cards')
  54. metricCards().then(res => {
  55. Taro.stopPullDownRefresh()
  56. setErrorPage(false)
  57. setList((res as any).cards)
  58. setTriggered(false)
  59. }).catch(e => {
  60. Taro.stopPullDownRefresh()
  61. if (list.length == 0) {
  62. setErrorPage(true)
  63. }
  64. setTriggered(false)
  65. // console.log('请求超时')
  66. })
  67. }
  68. //ts 把数组items: [{code: "_walk", value: 2180},{code: "_walk", value: 4444}]中的value取出来,/分割,组成字符串,如2180/4444
  69. function getValues(items) {
  70. var values = ''
  71. items.map((item, index) => {
  72. if (index == 0) {
  73. values = item.value
  74. }
  75. else {
  76. values = values + '/' + item.value
  77. }
  78. })
  79. return values
  80. }
  81. function goDetail(item) {
  82. if (user.isLogin) {
  83. if (!item.latest_record) {
  84. return
  85. }
  86. Taro.navigateTo({
  87. url: '/pages/common/RecordsHistory?type=metric&refreshList=getCards&code=' + item.code + `&title=${item.name}`
  88. })
  89. }
  90. else {
  91. Taro.navigateTo({
  92. url: '/pages/account/ChooseAuth'
  93. })
  94. }
  95. }
  96. function record(item: any) {
  97. if (user.isLogin) {
  98. var now = new Date();
  99. var t = (now.getHours() < 10 ? '0' + now.getHours() : now.getHours()) + ":" + (now.getMinutes() < 10 ? '0' + now.getMinutes() : now.getMinutes());
  100. setStrTime(t)
  101. setTime(now.getTime())
  102. setMetricItem(item)
  103. openModal()
  104. console.log(item)
  105. }
  106. else {
  107. Taro.navigateTo({
  108. url: '/pages/account/ChooseAuth'
  109. })
  110. }
  111. }
  112. function pointPicker(item: any) {
  113. var min = item.min
  114. var max = item.max
  115. var step = item.step
  116. var value = item.default_value
  117. console.log(value)
  118. var items: number[] = []
  119. var items2: number[] = []
  120. var value0Index = 0
  121. var value1Index = 0
  122. for (var i = min; i <= max; i++) {
  123. if (i == Math.floor(value)) {
  124. value0Index = i - min
  125. }
  126. items.push(i)
  127. // items2.push(i)
  128. }
  129. for (var i = 0; i <= 9; i++) {
  130. items2.push(i)
  131. }
  132. value1Index = Math.round(10 * (value - Math.floor(value)));
  133. console.log(value1Index)
  134. setPickerValue([value0Index, value1Index] as any)
  135. setPickerItems([items, items2] as any)
  136. setIsPoint(true)
  137. openModal()
  138. }
  139. function singlePicker(item: any) {
  140. var min = item.min
  141. var max = item.max
  142. var step = 1//item.step
  143. var value = item.default_value
  144. var items: number[] = []
  145. for (var i = min; i <= max; i += step) {
  146. if (i == value) {
  147. setPickerValue([i - min] as any)
  148. }
  149. items.push(i)
  150. }
  151. setPickerItems([items] as any)
  152. setIsPoint(false)
  153. openModal()
  154. }
  155. function pickerChanged(e) {
  156. closeModal();
  157. var params = {}
  158. var date = new Date(time)
  159. var strDate = (date.getFullYear() + '') + (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : (date.getMonth() + 1)) + (date.getDate() < 10 ? '0' + date.getDate() : date.getDate());
  160. if ((metricItem as any).schemas[0].type == 'DECIMAL') {
  161. var array = pickerItems;
  162. var value = array[0][e[0]] + '.' + array[1][e[1]]
  163. console.log(value)
  164. params = {
  165. code: (metricItem as any).code,
  166. timestamp: time,
  167. date: strDate,
  168. items: [{ code: (metricItem as any).schemas[0].code, value: value }]
  169. }
  170. }
  171. else if ((metricItem as any).schemas.length > 1) {
  172. }
  173. else {
  174. var array = pickerItems;
  175. var value = array[0][e[0]] + ''
  176. console.log(value)
  177. params = {
  178. code: (metricItem as any).code,
  179. timestamp: time,
  180. date: strDate,
  181. items: [{ code: (metricItem as any).schemas[0].code, value: value }]
  182. }
  183. }
  184. uploadMetric(params).then(res => {
  185. list.map((item, index) => {
  186. if ((item as any).code == (res as any).code) {
  187. (item as any).latest_record = (res as any).latest_record
  188. }
  189. })
  190. setList(list)
  191. // getCards();
  192. })
  193. }
  194. function showTimePicker() {
  195. setIsTimePickerOpen(true)
  196. }
  197. function chooseTime(e) {
  198. setTime(e);
  199. setStrTime(TimeFormatter.formatTimestamp(e))
  200. setIsTimePickerOpen(false)
  201. }
  202. function cancelModal() {
  203. (metricItem as any).schemas.map((item, index) => {
  204. item.tempValue = ''
  205. })
  206. closeModal()
  207. }
  208. function confirmModal() {
  209. closeModal()
  210. var date = new Date(time)
  211. var strDate = (date.getFullYear() + '') + (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : (date.getMonth() + 1)) + (date.getDate() < 10 ? '0' + date.getDate() : date.getDate());
  212. var array: any[] = [];
  213. (metricItem as any).schemas.map((item, index) => {
  214. array.push({
  215. code: item.code,
  216. value: item.tempValue && item.tempValue > 0 ? item.tempValue : item.default_value
  217. })
  218. })
  219. var params = {
  220. code: (metricItem as any).code,
  221. timestamp: time,
  222. date: strDate,
  223. items: array,
  224. extra: {
  225. set_time: setupTime,
  226. confirm_time: new Date().getTime()
  227. }
  228. }
  229. global.postBtnUpdateStatus('normal');
  230. uploadMetric(params).then(res => {
  231. // getCards();
  232. (metricItem as any).schemas.map((item, index) => {
  233. item.tempValue = ''
  234. })
  235. list.map((item, index) => {
  236. if ((item as any).code == (res as any).code) {
  237. (item as any).latest_record = (res as any).latest_record;
  238. (item as any).schemas = (res as any).schemas;
  239. }
  240. })
  241. setList(JSON.parse(JSON.stringify(list)))
  242. global.postBtnUpdateStatus('idle');
  243. })
  244. }
  245. const limit = new Date().getTime() - 180 * 3600 * 1000 * 24;
  246. function detail() {
  247. return <View>
  248. <View className="metric_container">
  249. {
  250. list.map((item: any, index: number) => {
  251. var unit = ''
  252. var value = '无记录'
  253. var desc = '记录解锁趋势'
  254. var showDetail = false;
  255. if (item.latest_record) {
  256. unit = item.schemas[0].default_unit
  257. value = getValues(item.latest_record.items)
  258. desc = TimeFormatter.formatTimestamp(item.latest_record.timestamp)
  259. showDetail = true
  260. }
  261. return <MetricItem title={item.name}
  262. value={value}
  263. unit={unit}
  264. desc={desc}
  265. btnText={t('feature.track_something.btn_record')}
  266. isDisabled={false}
  267. showDetail={showDetail}
  268. themeColor={item.theme_color}
  269. onClickDetail={() => { goDetail(item) }}
  270. onClick={() => { record(item) }}
  271. />
  272. })
  273. }
  274. </View>
  275. <View className="space_width" >11</View>
  276. </View>
  277. }
  278. // return showErrorPage ? <NoData refresh={() => { getCards() }} /> : detail()
  279. return <View style={{ position:'relative' }}>
  280. <Layout children={showErrorPage ? <NoData refresh={() => { getCards() }} /> : detail()}
  281. title={t('page.metric.title')}
  282. type={TemplateType.flex}
  283. refresh={() => { getCards() }}
  284. triggered={triggered}
  285. titleShowStyle={NaviBarTitleShowType.scrollToShow}
  286. />
  287. {
  288. isModalOpen && <Modal dismiss={closeModal} title={(metricItem as any).name}
  289. themeColor={(metricItem as any).theme_color}
  290. confirm={confirmModal}>
  291. <View style={{
  292. display: 'flex', flexDirection: 'column',
  293. width: '100%', color: '#000'
  294. }}>
  295. <Text className='modal_title' style={{ color: (metricItem as any).theme_color }}>{(metricItem as any).name ? (metricItem as any).name : '测试标题 '}</Text>
  296. <View style={{ position: 'relative' }}>
  297. {
  298. (metricItem as any).schemas.map((item, index) => {
  299. return <View key={index}>
  300. {
  301. (metricItem as any).schemas.length > 1 && <Text style={{
  302. textAlign: 'center', width: '100%', display: 'flex',
  303. justifyContent: 'center', color: (metricItem as any).theme_color
  304. }}>{item.name}</Text>
  305. }
  306. <SlidngScale step={item.step} min={item.min} max={item.max} default_value={item.default_value}
  307. unit={item.default_unit}
  308. themeColor={(metricItem as any).theme_color}
  309. changed={(e) => { item.tempValue = e }} />
  310. </View>
  311. })
  312. }
  313. </View>
  314. <View className="change_time_bg ">
  315. <View className="gray1 time_bg" onClick={showTimePicker}>
  316. <Text className="time" >{strTime}</Text>
  317. </View>
  318. </View>
  319. <View className='modal_operate'>
  320. <View className='modal_btn' style={{ backgroundColor: (metricItem as any).theme_color + alphaToHex(0.4) }} onClick={cancelModal}>
  321. <Text className='modal_cancel_text' style={{ color: (metricItem as any).theme_color }}>取消</Text>
  322. </View>
  323. <View className='btn_space' />
  324. <View className='modal_btn' style={{ backgroundColor: (metricItem as any).theme_color }} onClick={confirmModal}>
  325. <Text className='modal_confirm_text' style={{ color: '#000' }}>确定</Text>
  326. </View>
  327. </View>
  328. {/* <View style={{ marginBottom: 20, marginTop: 20, display: 'flex', flexDirection: 'row', width: '100%' }}>
  329. <Text style={{ flex: 1, textAlign: 'center', height: 50 }} onClick={cancelModal}>取消</Text>
  330. <Text style={{ flex: 1, textAlign: 'center', height: 50 }} onClick={confirmModal}>确认</Text>
  331. </View> */}
  332. </View>
  333. </Modal>
  334. }
  335. {
  336. isTimePickerOpen && <Modal
  337. themeColor={(metricItem as any).theme_color}
  338. dismiss={() => setIsTimePickerOpen(false)} confirm={() => {
  339. var picker = limitPickerRef.current;
  340. chooseTime((picker as any).getConfirmData());
  341. setIsTimePickerOpen(false);
  342. }}>
  343. <LimitPickers ref={limitPickerRef}
  344. isRealTime={true} time={time} limit={limit}
  345. title={t('feature.track_something.picker_datetime')}
  346. themeColor={(metricItem as any).theme_color}
  347. limitDay={180} onCancel={() => { setIsTimePickerOpen(false) }}
  348. onChange={(e) => {
  349. chooseTime(e)
  350. // pickerConfirm(e)
  351. // hidePicker()
  352. }} />
  353. </Modal>
  354. }
  355. </View>
  356. }