JournalDetail.tsx 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  1. import { View, Image, Text, Button } from "@tarojs/components";
  2. import { useLoad, useRouter, useShareAppMessage } from "@tarojs/taro";
  3. import { useEffect, useState } from "react";
  4. import { useSelector } from "react-redux";
  5. import './JournalDetail.scss'
  6. import Taro from "@tarojs/taro";
  7. import dayjs from "dayjs";
  8. import { rpxToPx } from "@/utils/tools";
  9. import { MainColorType } from "@/context/themes/color";
  10. import TimeTitleDesc from "@/_health/components/time_title_desc";
  11. import CoverList from "@/_health/components/cover_list";
  12. import ListFooter from "@/_health/components/list_footer";
  13. import { TimeFormatter } from "@/utils/time_format";
  14. import TargetProgress from "@/_health/components/target_progress";
  15. import { getThemeColor } from "@/features/health/hooks/health_hooks";
  16. import formatMilliseconds from "@/utils/format_time";
  17. import SingleImage from "@/_health/components/single_img";
  18. import { journalDetail } from "@/services/health";
  19. import { useTranslation } from "react-i18next";
  20. import { IconShare } from "@/components/basic/Icons";
  21. import NewButton, { NewButtonType } from "@/_health/base/new_button";
  22. import { SHARE_COVER_URL } from "@/services/http/api";
  23. let useRoute;
  24. let useNavigation;
  25. let scenario = '';
  26. if (process.env.TARO_ENV == 'rn') {
  27. useRoute = require("@react-navigation/native").useRoute
  28. useNavigation = require("@react-navigation/native").useNavigation
  29. }
  30. export default function JournalDetail() {
  31. const health = useSelector((state: any) => state.health);
  32. const user = useSelector((state: any) => state.user);
  33. const [shareUser, setShareUser] = useState<any>(null)
  34. const [imgs, setImgs] = useState<any>([])
  35. const [events, setEvents] = useState<any>([])
  36. const [loaded, setLoaded] = useState(false)
  37. const { t } = useTranslation()
  38. let router
  39. let navigation;
  40. if (useNavigation) {
  41. navigation = useNavigation()
  42. }
  43. if (process.env.TARO_ENV == 'rn') {
  44. router = useRoute()
  45. }
  46. else {
  47. router = useRouter()
  48. }
  49. const [data, setData] = useState<any>()
  50. const [date, setDate] = useState<any>(router.params ? router.params.date : 0)
  51. // const [detail, setDetail] = useState(JSON.parse(router.params.detail))
  52. useEffect(() => {
  53. if (date || router.params.window) {
  54. var params: any = {
  55. window: router.params.window
  56. }
  57. if (router.params.uid) {
  58. params.share_user_id = router.params.uid
  59. }
  60. journalDetail(date, params).then(res => {
  61. if ((res as any).windows.length > 0 &&
  62. (res as any).windows[0].events.length > 0 &&
  63. (res as any).windows[0].events[0].time
  64. ) {
  65. setTitle((res as any).windows[0].events[0].time.timestamp)
  66. }
  67. if ((res as any).share_user) {
  68. setShareUser((res as any).share_user)
  69. }
  70. setData(res)
  71. updateData(res)
  72. setLoaded(true)
  73. })
  74. }
  75. }, [])
  76. if (process.env.TARO_ENV == 'weapp' && global.allowShare) {
  77. useShareAppMessage((e) => {
  78. var { timestamp } = data
  79. var shareDate = ''
  80. if (TimeFormatter.isToday(timestamp)) {
  81. shareDate = global.language == 'en' ? 'Today\'s' : '今日'
  82. }
  83. else if (TimeFormatter.isYesterday(timestamp)) {
  84. shareDate = global.language == 'en' ? 'Yesterday\'s' : '昨日'
  85. }
  86. else if (TimeFormatter.isTimestampInThisWeek(timestamp)) {
  87. shareDate = global.language == 'en' ? (dayjs(timestamp).format('dddd') + '\'s') : dayjs(timestamp).format('dddd')
  88. }
  89. else {
  90. shareDate = global.language == 'en' ? dayjs(timestamp).format('MMMM D') : dayjs(timestamp).format('MMMD日')
  91. }
  92. var title = t('health.share_all_journal', { date: shareDate })
  93. var defaultImg = SHARE_COVER_URL + 'my_journal.jpg'
  94. if (router.params.window == 'EAT') {
  95. title = t('health.share_food_journal', { date: shareDate })
  96. defaultImg = SHARE_COVER_URL + 'my_meal_journal.jpg'
  97. }
  98. else if (router.params.window == 'ACTIVE') {
  99. title = t('health.share_activity_journal', { date: shareDate })
  100. defaultImg = SHARE_COVER_URL + 'my_activity_journal.jpg'
  101. }
  102. const uid = router.params.uid
  103. var imageUrl = imgs.length > 0 ? imgs[0] : defaultImg
  104. var nickname = shareUser ? shareUser.nickname : user.nickname
  105. if (nickname.length > 10) {
  106. nickname.substring(0, 10) + '...'
  107. }
  108. return {
  109. title: nickname + ': ' + title,
  110. path: `pages/account/JournalDetail?date=${date}&uid=${uid ?? user.id}&window=${router.params.window}`,
  111. imageUrl: imageUrl
  112. // imageUrl:'/src/assets/_health/share_01.jpg'
  113. }
  114. })
  115. }
  116. // useLoad((res2) => {
  117. // console.log('share:', res2)
  118. // if (res2.date && res2.uid) {
  119. // setDate(res2.date)
  120. // journalDetail(res2.date, { window: res2.window,share_user_id:res2.uid }).then(res => {
  121. // console.log('dsasfads',res)
  122. // if ((res as any).windows.length > 0 &&
  123. // (res as any).windows[0].events.length > 0 &&
  124. // (res as any).windows[0].events[0].time
  125. // ) {
  126. // setTitle((res as any).windows[0].events[0].time.timestamp)
  127. // }
  128. // // console.log('aaaaa')
  129. // setData(res)
  130. // updateData(res)
  131. // setLoaded(true)
  132. // })
  133. // }
  134. // })
  135. function setTitle(timestamp) {
  136. var title = ''
  137. var t = parseInt(timestamp + '')
  138. if (TimeFormatter.isToday(t)) {
  139. title = TimeFormatter.getTodayUnit()
  140. }
  141. else if (TimeFormatter.isYesterday(t)) {
  142. title = TimeFormatter.getYesterdayUnit()
  143. }
  144. else {
  145. if (global.language == 'en') {
  146. title = dayjs(t).format('dddd, MMM D')
  147. }
  148. else {
  149. title = dayjs(t).format('MMMD日 dddd')
  150. }
  151. }
  152. Taro.setNavigationBarTitle({
  153. title: title
  154. })
  155. }
  156. function updateData(obj) {
  157. var array: any = []
  158. obj.windows.map(item => {
  159. item.events.map(tem => {
  160. array.push(tem)
  161. })
  162. })
  163. const sortedArray = array.sort((a, b) => {
  164. return a.time.timestamp - b.time.timestamp;
  165. });
  166. // 返回一个新数组
  167. const newArray = [...sortedArray];
  168. // const order = {
  169. // 'FAST_START': 1,
  170. // 'FAST_END': 2,
  171. // 'SLEEP_BEDTIME': 3,
  172. // 'SLEEP_WAKE_UP': 4
  173. // }
  174. // // 分离出需要排序的项和其他项
  175. // const otherItems = newArray.filter(item => !order[item.event]);
  176. // const fastStartItems = newArray.filter(item => order[item.event]);
  177. // // 排序 fastStartItems
  178. // fastStartItems.sort((a, b) => {
  179. // return (order[a.event] || 0) - (order[b.event] || 0);
  180. // });
  181. // // 合并其他项和排序后的 fastStartItems
  182. // const result = otherItems.concat(fastStartItems);
  183. let array2: any = []
  184. obj.windows.map(item => {
  185. item.events.map(event => {
  186. event.moments && event.moments.map(moment => {
  187. if (moment.media && moment.media.length > 0) {
  188. moment.media.map(media => {
  189. array2.push(media.url)
  190. })
  191. }
  192. })
  193. })
  194. })
  195. obj.imgs = array2
  196. setImgs(obj.imgs)
  197. // setEvents(result)
  198. setEvents(newArray)
  199. }
  200. function preview(url) {
  201. Taro.previewImage({
  202. current: url,
  203. urls: imgs
  204. })
  205. }
  206. function dayTag(event, moment) {
  207. // debugger
  208. // if (!data ||data.length==0) return ''
  209. // // if (event.event == 'FAST_END' || event.event == 'SLEEP_WAKE_UP') {
  210. // var data = events.filter(item => {
  211. // if (event.event == 'FAST_END') {
  212. // return item.event == 'FAST_START'
  213. // }
  214. // if (event.event == 'SLEEP_WAKE_UP') {
  215. // return item.event == 'SLEEP_BEDTIME'
  216. // }
  217. // })
  218. var begin = data.timestamp//data[0].time.timestamp
  219. var end = moment ? moment.time.timestamp : event.time.timestamp
  220. return TimeFormatter.dayTagText(begin, end)
  221. // }
  222. // return ''
  223. }
  224. function eventList(detail, index) {
  225. // const list = detail.moments
  226. return <View key={index} style={{ marginBottom: rpxToPx(24) }}>
  227. {
  228. detail.show && <TimeTitleDesc
  229. timeObj={detail.time}
  230. time={dayjs(detail.time.timestamp).format('HH:mm')}
  231. title={detail.title}
  232. dayTag={dayTag(detail, null)}
  233. desc=''
  234. />
  235. }
  236. {
  237. detail.moments && detail.moments.map((moment, j) => {
  238. return (moment.title || moment.description) && <View key={j * 10} style={{ flexDirection: 'column', display: 'flex' }}>
  239. <TimeTitleDesc
  240. showPoint={detail.show}
  241. timeObj={moment.time}
  242. time={dayjs(moment.time.timestamp).format('HH:mm')}
  243. title={moment.title}
  244. dayTag={dayTag(detail, moment)}
  245. desc={moment.description}
  246. />
  247. </View>
  248. })
  249. }
  250. </View>
  251. }
  252. function backHome() {
  253. Taro.reLaunch({
  254. url: '/pages/clock/Clock'
  255. })
  256. }
  257. if (!loaded) return <View />
  258. return <View style={{ backgroundColor: '#fff' }}>
  259. <View className="journal_detail">
  260. <Image className="header_avatar" src={shareUser ? shareUser.avatar : user.avatar} mode="aspectFill" />
  261. <View className="jounal_content">
  262. <Text className="journal_nickname">{shareUser ? shareUser.nickname : user.nickname}</Text>
  263. <View style={{ flexDirection: 'column', display: 'flex', marginTop: rpxToPx(24) }}>
  264. {
  265. events.map((item, index) => {
  266. return eventList(item, index)
  267. })
  268. }
  269. </View>
  270. <View className="img_container" style={{ marginTop: 0, marginBottom: rpxToPx(17) }}>
  271. {
  272. imgs.length == 1 ? <SingleImage url={imgs[0]} /> : <CoverList
  273. imgs={imgs}
  274. count={imgs.length}
  275. />
  276. }
  277. </View>
  278. {
  279. data.windows.map((item, index) => {
  280. return <TargetProgress key={index} showLine={true}
  281. color={getThemeColor(item.window)}
  282. showRing={true}
  283. desc={item.description}
  284. icon={
  285. null
  286. }
  287. canvasId={`${item.window}${item.window_range.start_timestamp}${index}`}
  288. startTimestamp={item.window_range.start_timestamp}
  289. endTimerstamp={item.window_range.end_timestamp}
  290. />
  291. })
  292. }
  293. <View style={{ display: 'flex', flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', marginTop: rpxToPx(17), }}>
  294. <Text className="h24" style={{ color: MainColorType.g02, lineHeight: rpxToPx(60) + 'px' }}>{t(data.publish.edited ? 'health.journal_updated' : 'health.journal_created', {
  295. date_time: global.language == 'en' ?
  296. dayjs(data.publish.timestamp).format('MMM D HH:mm') :
  297. dayjs(data.publish.timestamp).format('M月D日 HH:mm')
  298. })}</Text>
  299. {
  300. global.allowShare && <View className="share_btn_bg">
  301. <View className="share_icon_bg">
  302. <IconShare color={MainColorType.link + 'cc'} width={rpxToPx(32)} />
  303. </View>
  304. <Button className="share_btn" openType="share">1</Button>
  305. </View>
  306. }
  307. </View>
  308. {/* <Text className="h24" style={{ color: MainColorType.g02, marginTop: rpxToPx(17), lineHeight: rpxToPx(60) + 'px' }}>发布于{dayjs(data.publish_timestamp).format('M月D日 HH:mm')}</Text> */}
  309. </View>
  310. {
  311. router.params.uid && <View className="main_footer" style={{ backgroundColor: '#fff' }}>
  312. <NewButton
  313. type={NewButtonType.fill}
  314. color={MainColorType.success}
  315. title={t('health.back_home')}
  316. width={rpxToPx(646)}
  317. height={rpxToPx(96)}
  318. onClick={backHome}
  319. />
  320. </View>
  321. }
  322. </View>
  323. <ListFooter />
  324. </View>
  325. }