timeline_detail.tsx 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  1. import { View, Image, Text, Input, Textarea } from "@tarojs/components";
  2. import { useSelector } from "react-redux";
  3. import './timeline_detail.scss'
  4. import '@features/health/History.scss'
  5. import { useEffect, useState } from "react";
  6. import Taro, { useRouter } from "@tarojs/taro";
  7. import dayjs from "dayjs";
  8. import { getThemeColor } from "@/features/health/hooks/health_hooks";
  9. import { baseUrl } from "@/services/http/api";
  10. import { checkAuthorized } from "@/utils/check_authorized";
  11. import { createMoment, getEvents } from "@/services/health";
  12. import NewButton, { NewButtonType } from "../base/new_button";
  13. import { IconClose } from "@/components/basic/Icons";
  14. import { rpxToPx } from "@/utils/tools";
  15. import { MainColorType } from "@/context/themes/color";
  16. import NewModal from "../base/new_modal";
  17. import Card from "../components/card";
  18. import ChooseDateTime from "../components/choose_date_time";
  19. import TimeTitleDesc from "../components/time_title_desc";
  20. import CoverList from "../components/cover_list";
  21. import ListFooter from "../components/list_footer";
  22. let timestamp = 0;
  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 TimelineDetail() {
  31. const health = useSelector((state: any) => state.health);
  32. const user = useSelector((state: any) => state.user);
  33. const [list, setList] = useState<any>([])
  34. const [detail, setDetail] = useState<any>(null)
  35. const [desc, setDesc] = useState('')
  36. const [imgUrl, setImgUrl] = useState('')
  37. const [btnDisable, setBtnDisable] = useState(true)
  38. const [showPop, setShowPop] = useState(false)
  39. const [publish, setPublish] = useState<any>(null)
  40. const [bottom, setBottom] = useState(20)
  41. const [loaded, setLoaded] = useState(false)
  42. const [showTimePicker, setShowTimePicker] = useState(false)
  43. const [time, setTime] = useState(dayjs().format('HH:mm'))
  44. const [selTime, setSelTime] = useState(dayjs().format('HH:mm'))
  45. const [selDate, setSelDate] = useState(dayjs().format('YYYY-MM-DD'))
  46. let router
  47. let navigation;
  48. if (useNavigation) {
  49. navigation = useNavigation()
  50. }
  51. if (process.env.TARO_ENV == 'rn') {
  52. router = useRoute()
  53. }
  54. else {
  55. router = useRouter()
  56. }
  57. const { schedule_id, event_id } = router.params
  58. useEffect(() => {
  59. Taro.setNavigationBarColor({
  60. backgroundColor: showPop ? '#191919' : '#ffffff',
  61. frontColor: '#000000'
  62. })
  63. }, [showPop])
  64. useEffect(() => {
  65. Taro.onKeyboardHeightChange(res => {
  66. setBottom(res.height > 0 ? res.height : 20)
  67. })
  68. getDatas()
  69. }, [])
  70. useEffect(() => {
  71. if (desc.length > 0 || imgUrl.length > 0) {
  72. setBtnDisable(false)
  73. }
  74. else {
  75. setBtnDisable(true)
  76. }
  77. }, [desc, imgUrl])
  78. function getDatas() {
  79. getEvents(event_id).then(res => {
  80. setLoaded(true)
  81. setDetail(res)
  82. setList((res as any).moments)
  83. setPublish((res as any).publish)
  84. })
  85. }
  86. function addImage(isCamera: boolean) {
  87. Taro.chooseMedia({
  88. count: 1,
  89. sizeType: ['compressed'],
  90. mediaType: ['image'],
  91. sourceType: [isCamera ? 'camera' : 'album'],
  92. success: function (res) {
  93. chooseSuccess(res, true)
  94. // checkAuthorized()
  95. },
  96. fail: function (res) {
  97. }
  98. })
  99. }
  100. async function chooseSuccess(res, isAlbum) {
  101. var params = {
  102. event: 'add_a_picture',
  103. value: isAlbum ? 'choose_from_album_confirm' : 'use_camera_confirm',
  104. }
  105. // saveFoodCache('create', params)
  106. var savedFilePath = process.env.TARO_ENV == 'rn' ? res.tempFiles[0].path : res.tempFiles[0].tempFilePath
  107. // var savedFilePath = res.savedFilePath
  108. await Taro.setStorage({ key: 'pic', data: savedFilePath })
  109. setImgUrl(savedFilePath as any)
  110. uploadFile(savedFilePath, isAlbum ? 'album' : 'camera')
  111. }
  112. function uploadFile(path, source) {
  113. Taro.showLoading({
  114. title: '加载中'
  115. })
  116. var dot = path.lastIndexOf('.')
  117. var fileExt = dot > 0 ? path.substring(dot) : ''
  118. Taro.request({
  119. method: 'GET',
  120. url: `${baseUrl}/api/thirdparty/aliyun/oss-form-upload`,
  121. header: {
  122. 'Authorization': 'bearer ' + global.token
  123. },
  124. data: {
  125. type: 'FOOD_JOURNAL',
  126. file_ext: fileExt
  127. },
  128. success: (rsp) => {
  129. if (rsp.statusCode != 200) {
  130. Taro.showToast({
  131. title: '操作失败,请检查网络',
  132. icon: 'none'
  133. })
  134. return
  135. }
  136. Taro.uploadFile({
  137. url: rsp.data.upload_url,
  138. filePath: path,
  139. name: 'file',
  140. formData: rsp.data.fields,
  141. success: rlt => {
  142. setImgUrl(rsp.data.view_url)
  143. Taro.hideLoading()
  144. // createData(rsp.data.view_url, source)
  145. // uploadAvatar(rsp.data.view_url)
  146. // _this.changeAvatar(rsp.data.view_url);
  147. },
  148. fail: rlt => {
  149. Taro.hideLoading()
  150. Taro.showModal({
  151. content: rlt.errMsg
  152. })
  153. }
  154. })
  155. }
  156. })
  157. }
  158. function tapPost() {
  159. if (desc.length == 0 && imgUrl.length == 0) {
  160. Taro.showToast({
  161. icon: 'none',
  162. title: '请输入描述或添加图片'
  163. })
  164. return
  165. }
  166. var dt = new Date(selDate + ' ' + time + ':00')
  167. var params: any = {
  168. schedule_id: schedule_id,
  169. description: desc,
  170. start: {
  171. date: dayjs(dt.getTime()).format('YYYYMMDD'),
  172. timestamp: dt.getTime()
  173. },
  174. // real_end_time: meal.target_end_time,
  175. }
  176. if (imgUrl.length > 0) {
  177. params.media = [{
  178. url: imgUrl,
  179. type: imgUrl.indexOf('mp4') != -1 ? 'video' : 'image',
  180. source: 'album'
  181. }]
  182. }
  183. params.event_id = event_id
  184. createMoment(params).then(res => {
  185. getDatas()
  186. setImgUrl('')
  187. setDesc('')
  188. global.refreshWindow()
  189. global.refreshHistory()
  190. setShowPop(false)
  191. })
  192. }
  193. function mediaCount() {
  194. let count = 0;
  195. list && list.map(moment => {
  196. moment.media.map((obj) => {
  197. count++
  198. })
  199. })
  200. return count;
  201. }
  202. function imgList() {
  203. var array: any = []
  204. list && list.map(moment => {
  205. moment.media.map((obj) => {
  206. array.push(obj.url)
  207. })
  208. })
  209. return array;
  210. }
  211. if (!loaded) return <View />
  212. return <View style={{ display: 'flex', flex: 1 }}>
  213. <View className="detail_header">
  214. <Image className="detail_header_header"
  215. src={user.avatar}
  216. mode="aspectFill"
  217. />
  218. <View className="detail_header_content">
  219. <Text className="detail_nickname">{user.nickname}</Text>
  220. {
  221. (detail.scenario != 'MEAL' && detail.scenario != 'ACTIVITY') &&
  222. <TimeTitleDesc
  223. time={dayjs(detail.time.timestamp).format('HH:mm')}
  224. title={detail.title}
  225. />
  226. }
  227. {
  228. detail.scenario == 'ACTIVITY' && !list &&
  229. <TimeTitleDesc
  230. time={dayjs(detail.time.timestamp).format('HH:mm')}
  231. title={detail.title}
  232. />
  233. }
  234. {
  235. list && list.map((item, index) => {
  236. return <View key={index} style={{ flexDirection: 'column', display: 'flex' }}>
  237. <TimeTitleDesc
  238. time={dayjs(item.time.timestamp).format('HH:mm')}
  239. title={item.title}
  240. desc={item.description}
  241. />
  242. </View>
  243. })
  244. }
  245. {/* {
  246. <View className="media" style={{ marginRight: mediaCount() == 4 ? 80 : 0, marginTop: rpxToPx(24) }}>
  247. {
  248. list && list.map(moment => {
  249. return moment.media.map((obj, j) => {
  250. return <Image className="media_item" mode="aspectFill" onClick={() => { }} src={obj.url} key={j * 10} />
  251. })
  252. })
  253. }
  254. </View>
  255. } */}
  256. <View style={{ marginTop: rpxToPx(24) }}>
  257. <CoverList imgs={imgList()} count={mediaCount()} />
  258. </View>
  259. {
  260. publish && <View style={{display:'flex',flexDirection:'row',height:rpxToPx(60),alignItems:'center'}}>
  261. <Text className="h24 g02">发布于{dayjs(publish.timestamp).format('MM-DD HH:mm')}</Text>
  262. </View>
  263. }
  264. </View>
  265. </View>
  266. <ListFooter />
  267. {
  268. health.mode != 'ACTIVE' && health.mode != 'EAT' && <View className="add_note"><NewButton type={NewButtonType.link} title="写个笔记" onClick={() => {
  269. timestamp = new Date().getTime()
  270. setShowPop(true)
  271. }} /></View>
  272. }
  273. {
  274. showPop && <View className="publish_bg">
  275. <NewButton type={NewButtonType.img}
  276. btnStyle={{
  277. position: 'absolute', left: rpxToPx(52),
  278. top: 0,
  279. color: '#fff',
  280. width: 32,
  281. height: 32
  282. }}
  283. onClick={() => {
  284. setShowPop(false)
  285. }}>
  286. <IconClose color="#fff" width={20} height={20} />
  287. </NewButton>
  288. <View onClick={() => setShowTimePicker(true)} style={{ height: rpxToPx(88), marginTop: rpxToPx(120), width: rpxToPx(80), color: MainColorType.link }}>{time}
  289. </View>
  290. <Textarea className="myTextarea" placeholder="What's on your mind?" style={{ flex: 1, color: '#fff', caretColor: getThemeColor(health.mode) }} focus value={desc} onInput={(e) => {
  291. setDesc(e.detail.value)
  292. }} />
  293. <View className="toolbar2">
  294. {
  295. imgUrl.length > 0 && <NewButton type={NewButtonType.img} onClick={() => addImage(false)}>
  296. <Image src={imgUrl} mode="aspectFill" className="album" />
  297. </NewButton>
  298. }
  299. {
  300. imgUrl.length == 0 && <NewButton type={NewButtonType.img} onClick={() => addImage(false)}>
  301. <Image src={require('@assets/_health/album.png')} className="album"
  302. />
  303. </NewButton>
  304. }
  305. {
  306. imgUrl.length == 0 && <NewButton type={NewButtonType.img} onClick={() => addImage(true)}>
  307. <Image src={require('@assets/_health/camera.png')} className="album"
  308. /></NewButton>
  309. }
  310. <View style={{ flex: 1 }} />
  311. <View className="btn" style={{ backgroundColor: btnDisable ? '#b2b2b2' : getThemeColor(health.mode) }} onClick={tapPost}>发布</View>
  312. </View>
  313. <View style={{ height: bottom, flexShrink: 0 }} />
  314. </View>
  315. }
  316. {
  317. showTimePicker && <NewModal
  318. title='时间'
  319. dismiss={() => setShowTimePicker(false)}
  320. confirm={() => {
  321. // props.onChange({
  322. // date: selDate,
  323. // time: time,
  324. // duration: minutes,
  325. // isYesterday: isYesterday
  326. // })
  327. setTime(selTime)
  328. setShowTimePicker(false)
  329. }}
  330. themeColor={getThemeColor(health.mode)}>
  331. <Card>
  332. <ChooseDateTime title={null}
  333. disable={false}
  334. color={getThemeColor(health.mode)}
  335. expand={true}
  336. time={time}
  337. hideFooter={true}
  338. timeChange={(e) => {
  339. setSelTime(e)
  340. }}
  341. minTimestamp={new Date().getTime()}
  342. date={selDate}
  343. dateChange={(e) => {
  344. setSelDate(e)
  345. }}
  346. />
  347. </Card>
  348. </NewModal>
  349. }
  350. </View>
  351. }