moment_main.tsx 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711
  1. import TabBar from "@/components/navigation/TabBar";
  2. import { rpxToPx } from "@/utils/tools";
  3. import { View, Text, Image, ScrollView, Button, Block } from "@tarojs/components";
  4. import Taro, { useDidShow, useRouter, useShareAppMessage } from "@tarojs/taro";
  5. import { useDispatch, useSelector } from "react-redux";
  6. import { useEffect, useRef, useState } from "react";
  7. import { followUser, getFriendMoments, getMyFriends, getUserDashBoard } from "@/services/friend";
  8. import FriendGuide from "./guide";
  9. import EmptyContent from "./empty_content";
  10. import MomentItem from "./moment_item";
  11. import { useTranslation } from "react-i18next";
  12. import { windows } from "@/services/health";
  13. import { setFastWithSleep, setFinishSetup, setLongFast, setRefreshs, setWindows } from "@/store/health";
  14. import { getInfoSuccess } from "@/store/user";
  15. import showActionSheet from "@/components/basic/ActionSheet";
  16. import { jumpPage } from "@/features/trackTimeDuration/hooks/Common";
  17. import './moment.scss'
  18. import ListFooter from "@/_health/components/list_footer";
  19. import { MainColorType } from "@/context/themes/color";
  20. import dayjs from "dayjs";
  21. import { IconClose, IconMenu } from "@/components/basic/Icons";
  22. import MomentShare from "./moment_share";
  23. import NoRecord from "@/_health/components/no_record";
  24. import ShareBtn from "@/components/basic/ShareBtn";
  25. import NewButton, { NewButtonType } from "@/_health/base/new_button";
  26. import MomentDetailShare from "./moment_detail_share";
  27. import { getThemeColor } from "@/features/health/hooks/health_hooks";
  28. import shareTitle from "./moment_unit";
  29. let useRoute;
  30. let useNavigation;
  31. if (process.env.TARO_ENV == 'rn') {
  32. useRoute = require("@react-navigation/native").useRoute
  33. useNavigation = require("@react-navigation/native").useNavigation
  34. }
  35. let timer;
  36. let myScrollTop = 0
  37. export default function MomentMain() {
  38. const user = useSelector((state: any) => state.user);
  39. const observerObjBottom = Taro.createIntersectionObserver().relativeToViewport({ bottom: 100 })
  40. const [loading, setLoading] = useState(false)
  41. const [noMore, setNoMore] = useState(false)
  42. const [friends, setFriends] = useState<any>([])
  43. const [count, setCount] = useState(0)
  44. const systemInfo: any = Taro.getWindowInfo ? Taro.getWindowInfo() : Taro.getSystemInfoSync();
  45. const navigationBarHeight = systemInfo.statusBarHeight + 44;
  46. const [itemLayouts, setItemLayouts] = useState<any>([])
  47. const [itemHeights, setItemHeights] = useState<any>([])
  48. const [isPulling, setIsPulling] = useState(false)
  49. const [pageTop, setPageTop] = useState(0)
  50. const scrollRef = useRef()
  51. let router
  52. let navigation;
  53. if (useNavigation) {
  54. navigation = useNavigation()
  55. }
  56. if (process.env.TARO_ENV == 'rn') {
  57. router = useRoute()
  58. }
  59. else {
  60. router = useRouter()
  61. }
  62. const [loaded, setLoaded] = useState(false)
  63. const [homeType, setHomeType] = useState('NO_FRIEND')
  64. const [dashBoard, setDashBoard] = useState<any>(null)
  65. const [moments, setMoments] = useState<any>([])
  66. const [page, setPage] = useState(1)
  67. const [endSignal, setEndSignal] = useState(0)
  68. const [closeGuide, setCloseGuide] = useState(false)
  69. const [showGuide,setShowGuide] = useState(false)
  70. const [showShareGuide, setShowShareGuide] = useState(false)
  71. const [shareInfo, setShareInfo] = useState<any>(null)
  72. const query = Taro.createSelectorQuery()
  73. const dispatch = useDispatch()
  74. const { t } = useTranslation()
  75. const momentsRef = useRef(moments)
  76. useEffect(() => {
  77. dayjs.locale(global.language == 'en' ? 'en' : 'zh-cn');
  78. require('moment/locale/en-gb')
  79. require('moment/locale/zh-cn')
  80. timer = setInterval(() => {
  81. setCount(count => count + 1)
  82. }, 1000)
  83. Taro.eventCenter.on('followUser', listenFollowUser)
  84. Taro.eventCenter.on('unfollowUser', listenUnfollowUser)
  85. Taro.eventCenter.on('refreshMoments', refreshMoments)
  86. Taro.eventCenter.on('moment_share', momentShare)
  87. Taro.eventCenter.on('refresh_timeline', refreshItem)
  88. //Taro.eventCenter.trigger('refresh_timeline',(res as any).feed_item)
  89. return () => {
  90. Taro.eventCenter.off('followUser')
  91. Taro.eventCenter.off('unfollowUser')
  92. Taro.eventCenter.off('refreshMoments')
  93. Taro.eventCenter.off('moment_share')
  94. Taro.eventCenter.off('refresh_timeline')
  95. clearInterval(timer)
  96. }
  97. }, [])
  98. useEffect(() => {
  99. momentsRef.current = moments;
  100. }, [moments])
  101. function listenFollowUser(e) {
  102. myFriends()
  103. }
  104. function listenUnfollowUser(e) {
  105. myFriends()
  106. }
  107. function refreshMoments(e) {
  108. myFriends()
  109. }
  110. function refreshItem(e) {
  111. if (!e) return
  112. const { link, moment, user } = e
  113. var list = JSON.parse(JSON.stringify(momentsRef.current))
  114. list.map((item) => {
  115. if (item.link.event_id == link.event_id) {
  116. if (link) {
  117. item.link = e.link
  118. }
  119. if (moment) {
  120. item.moment = e.moment
  121. }
  122. if (user) {
  123. item.user = e.user
  124. }
  125. }
  126. })
  127. setMoments(list)
  128. }
  129. function momentShare(e) {
  130. setShareInfo(e)
  131. setShowShareGuide(true)
  132. // var dt = scrollRef.current
  133. // query.select(`#myscrollview`).boundingClientRect().exec(res=>{
  134. // debugger
  135. // })
  136. }
  137. useEffect(() => {
  138. myFriends()
  139. if (router.params.type == 'share') {
  140. if (global.shareTicket) {
  141. Taro.getShareInfo({
  142. shareTicket: global.shareTicket,
  143. success(result) {
  144. updateRelation(result)
  145. },
  146. })
  147. }
  148. else {
  149. updateRelation(null)
  150. }
  151. }
  152. }, [user.isLogin])
  153. useEffect(() => {
  154. if (moments.length == 0) return
  155. setTimeout(() => {
  156. measureItemLayouts()
  157. }, 300)
  158. observerObjBottom.observe('#footer', (res) => {
  159. setEndSignal(endSignal => endSignal + 1)
  160. // if (moments.length==0) return
  161. // loadMore()
  162. })
  163. }, [moments])
  164. useEffect(() => {
  165. if (moments.length == 0) return
  166. loadMore()
  167. }, [endSignal])
  168. function measureItemLayouts() {
  169. if (moments.length <= 10) {
  170. moments.forEach((item, index) => {
  171. query.select(`#history2-${index}`).boundingClientRect()
  172. });
  173. query.exec((res) => {
  174. var layouts: any = []
  175. var heights: any = []
  176. res.forEach((rect, index) => {
  177. if (rect) {
  178. layouts[index] = rect.top + myScrollTop
  179. heights[index] = rect.height
  180. }
  181. });
  182. setItemLayouts(layouts)
  183. setItemHeights(heights)
  184. })
  185. }
  186. else {
  187. moments.forEach((item, index) => {
  188. if (index >= itemLayouts.length) {
  189. query.select(`#history2-${index}`).boundingClientRect()
  190. }
  191. });
  192. query.exec((res) => {
  193. var layouts: any = []
  194. var heights: any = []
  195. res.forEach((rect, index) => {
  196. if (rect) {
  197. layouts[index] = rect.top + myScrollTop
  198. heights[index] = rect.height
  199. }
  200. });
  201. setItemLayouts([...itemLayouts, ...layouts])
  202. setItemHeights([...itemHeights, ...heights])
  203. })
  204. }
  205. }
  206. function onScroll(e) {
  207. // var top = e.detail.scrollTop
  208. // myScrollTop = top
  209. var top = e.detail.scrollTop - e.detail.deltaY
  210. myScrollTop = e.detail.scrollTop
  211. setPageTop(top)
  212. }
  213. useDidShow(() => {
  214. getDashBoard()
  215. })
  216. function myFriends() {
  217. if (!user.isLogin) {
  218. setLoaded(true)
  219. Taro.hideLoading()
  220. return
  221. }
  222. setItemHeights([])
  223. setItemLayouts([])
  224. getDashBoard()
  225. getMoments(1)
  226. }
  227. function onRefresh() {
  228. setIsPulling(true)
  229. getMoments(1)
  230. getDashBoard()
  231. }
  232. function getMoments(index) {
  233. setPage(index)
  234. getFriendMoments({
  235. page: index,
  236. limit: 10
  237. }).then(res => {
  238. setIsPulling(false)
  239. if (index == 1) {
  240. setMoments((res as any).data)
  241. }
  242. else {
  243. setMoments([...moments, ...(res as any).data])
  244. }
  245. setLoading(false)
  246. if ((res as any).data.length == 0) {
  247. setNoMore(true)
  248. }
  249. else {
  250. setNoMore(false)
  251. }
  252. }).catch(e => {
  253. setIsPulling(false)
  254. setLoading(false)
  255. setLoaded(true)
  256. Taro.hideLoading()
  257. })
  258. }
  259. function getDashBoard() {
  260. getUserDashBoard().then(res => {
  261. setLoaded(true)
  262. setHomeType((res as any).homepage_type)
  263. setDashBoard(res)
  264. Taro.hideLoading()
  265. }).catch(e => {
  266. setLoaded(true)
  267. Taro.hideLoading()
  268. })
  269. }
  270. function updateRelation(obj) {
  271. if (!user.isLogin) {
  272. Taro.setStorageSync('share_uid', router.params.uid)
  273. Taro.setStorageSync('share_info', JSON.stringify(obj))
  274. return
  275. }
  276. if (user.id != router.params.uid) {
  277. var params: any = {
  278. follow_origin: obj ? 'WECHAT_GROUP_CHAT' : 'WECHAT_PRIVATE_CHAT',
  279. user_id: router.params.uid,
  280. }
  281. if (obj) {
  282. params.wechat = obj
  283. }
  284. followUser(params).then(res => {
  285. myFriends()
  286. })
  287. }
  288. }
  289. function loadMore() {
  290. if (loading) return;
  291. if (noMore) return;
  292. setLoading(true)
  293. var index = page;
  294. index++;
  295. setPage(index)
  296. getMoments(index)
  297. }
  298. function more() {
  299. showActionSheet({
  300. title: '',
  301. itemList: ['个人主页', '我的搭子', '消息通知'],
  302. success: (index) => {
  303. switch (index) {
  304. case 0:
  305. jumpPage('/_moment/pages/home?uid=' + user.id)
  306. break;
  307. case 1:
  308. jumpPage('/_moment/pages/relation')
  309. break
  310. case 2:
  311. jumpPage('/_moment/pages/message')
  312. break
  313. }
  314. }
  315. })
  316. }
  317. function friendGuide() {
  318. return <View style={{ position: 'fixed', left: 0, top: 0, width: rpxToPx(750), height: '100vh', zIndex: 100 }}>
  319. <View style={{ height: navigationBarHeight, width: rpxToPx(750), backgroundColor: '#fff' }} />
  320. {/* <View onClick={() => {
  321. setCloseGuide(true)
  322. }}>关闭</View> */}
  323. {
  324. user.isLogin && <View style={{
  325. position: 'absolute', left: 10, top: navigationBarHeight - 44, width: 44, height: 44,
  326. display: 'flex', alignItems: 'center', justifyContent: 'center'
  327. }}
  328. onClick={() => {
  329. // setCloseGuide(true)
  330. setShowGuide(false)
  331. }}
  332. >
  333. <IconClose color="#000" width={30} height={30} />
  334. </View>
  335. }
  336. <FriendGuide closeShare={()=>{
  337. setTimeout(()=>{
  338. setShowGuide(false)
  339. },500)
  340. }}/>
  341. {
  342. process.env.TARO_ENV == 'weapp' && <TabBar index={4} />
  343. }</View>
  344. }
  345. function empty() {
  346. return <View style={{ position: 'fixed', left: 0, top: 0, width: rpxToPx(750), height: '100vh', zIndex: 100 }}>
  347. <View style={{ height: navigationBarHeight, width: rpxToPx(750), backgroundColor: '#fff' }} />
  348. {
  349. user.isLogin && <View style={{
  350. position: 'absolute', left: 10, top: navigationBarHeight - 44, width: 44, height: 44,
  351. display: 'flex', alignItems: 'center', justifyContent: 'center'
  352. }}
  353. onClick={() => {
  354. setCloseGuide(true)
  355. }}
  356. >
  357. <IconClose color="#000" width={30} height={30} />
  358. </View>
  359. }
  360. <EmptyContent friends={dashBoard.friends} />
  361. {
  362. process.env.TARO_ENV == 'weapp' && <TabBar index={4} />
  363. }
  364. </View>
  365. }
  366. function shareGuideContent() {
  367. console.log(shareInfo)
  368. return <Block><View className="share_guide_bg" style={{ top: 0 }} onClick={(e) => {
  369. if (process.env.TARO_ENV == 'weapp') {
  370. e.stopPropagation()
  371. }
  372. setShowShareGuide(false)
  373. }}>
  374. <View className="share_guide_card" onClick={(e) => {
  375. if (process.env.TARO_ENV == 'weapp') {
  376. e.stopPropagation()
  377. }
  378. }}>
  379. <Image className="share_guide_avatar" mode="aspectFill" src={shareInfo.join.user.avatar} />
  380. <View className="h34 bold" style={{ marginTop: rpxToPx(60), marginBottom: rpxToPx(60) }}>{shareTitle(t, shareInfo.join.user)}</View>
  381. <ShareBtn onClick={() => {
  382. setShowShareGuide(false)
  383. }}>
  384. <NewButton
  385. title="分享给微信好友"
  386. type={NewButtonType.fill}
  387. width={rpxToPx(480)}
  388. height={rpxToPx(96)}
  389. color={MainColorType.success}
  390. onClick={() => {
  391. }}
  392. />
  393. </ShareBtn>
  394. </View>
  395. </View>
  396. </Block>
  397. }
  398. function listDetail() {
  399. return <View >
  400. <View style={{
  401. position: 'fixed',
  402. top: 0,
  403. left: 0,
  404. zIndex: 10,
  405. height: navigationBarHeight, width: rpxToPx(750), backgroundColor: '#f5f5f5', display: 'flex',
  406. flexDirection: 'column', justifyContent: 'flex-end'
  407. }}>
  408. <View style={{ height: 44, width: rpxToPx(750), position: 'relative', display: 'flex', flexDirection: 'row', alignItems: 'center', justifyContent: 'center' }}>
  409. <View style={{ fontWeight: 'bold', }}>{t('health.moments')}</View>
  410. <View onClick={more} style={{ position: 'absolute', left: 10, top: 0, bottom: 0, width: 44, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
  411. <IconMenu color="#000" width={rpxToPx(40)} />
  412. </View>
  413. <View onClick={()=>{
  414. setShowGuide(true)
  415. }} style={{ position: 'absolute', left: 54, top: 0, bottom: 0, width: 44, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
  416. <Image src={require('@assets/_health/wechat.png')} style={{ width: rpxToPx(48), height: rpxToPx(48) }} />
  417. {/* <Button openType="share" style={{ position: 'absolute', left: 0, right: 0, top: 0, bottom: 0, opacity: 0 }} /> */}
  418. </View>
  419. </View>
  420. </View>
  421. <ScrollView style={{
  422. marginTop: navigationBarHeight,
  423. height: '90vh'
  424. }}
  425. enableBackToTop
  426. ref={scrollRef}
  427. id="myscrollview"
  428. scrollY={showShareGuide ? false : true}
  429. refresherEnabled={true}
  430. upperThreshold={70}
  431. // scrollTop={showShareGuide ? pageTop : undefined}
  432. // lowerThreshold={140}
  433. refresherBackground={MainColorType.g05}
  434. onRefresherRefresh={onRefresh}
  435. refresherTriggered={isPulling}
  436. onScroll={onScroll}
  437. onScrollToUpper={() => {
  438. // setPage(1)
  439. // if (moments.length > 10) {
  440. // setMoments(moments.slice(0, 10))
  441. // setItemHeights(itemHeights.slice(0, 10))
  442. // setItemLayouts(itemLayouts.slice(0, 10))
  443. // }
  444. }}
  445. // onScrollToLower={props.loadMore}
  446. >
  447. <View style={{ backgroundColor: '#fff', minHeight: '100vh', paddingTop: rpxToPx(30), paddingBottom: 100 }}>
  448. {
  449. dashBoard && dashBoard.new_message && <View className="new_message_bg">
  450. <View className="new_message" onClick={() => {
  451. jumpPage('/_moment/pages/message')
  452. }}>
  453. {
  454. dashBoard.new_message.avatars.map((item, index) => {
  455. return <Image className="message_avatar" src={item} key={index} style={{ zIndex: 9 - index, marginLeft: index == 0 ? rpxToPx(8) : -15 }} />
  456. })
  457. }
  458. <View className="h26 bold" style={{ color: '#fff', minWidth: rpxToPx(260), textAlign: 'center' }}>{dashBoard.new_message.message_tip}</View>
  459. </View>
  460. </View>
  461. }
  462. {
  463. moments.map((item, index) => {
  464. if (itemLayouts.length >= index + 1 && pageTop > 0 && index > 5) {
  465. if (Math.abs(itemLayouts[index] - pageTop) > 2500) {
  466. return <View style={{ height: itemHeights[index] }} id={`history—temp-${index}`}>
  467. </View>
  468. }
  469. }
  470. return <View key={index} id={`history2-${index}`}>
  471. <MomentItem data={item} del={
  472. () => {
  473. var list = JSON.parse(JSON.stringify(moments))
  474. list.splice(index, 1)
  475. setMoments(list)
  476. }
  477. } />
  478. </View>
  479. })
  480. }
  481. {
  482. moments.length == 0 && <NoRecord style={{ marginTop: rpxToPx(160) }} />
  483. }
  484. <ListFooter noMore={noMore} loading={loading} />
  485. <View id="footer" style={{ width: 1, height: 1 }}></View>
  486. </View>
  487. </ScrollView>
  488. <Block>
  489. {
  490. showShareGuide && <MomentDetailShare user={shareInfo.join.user} btnColor={getThemeColor(shareInfo.join.window)}
  491. cover={shareInfo.moment && shareInfo.moment.media && shareInfo.moment.media.length > 0 ? shareInfo.moment.media[0].url : null} />
  492. }
  493. </Block>
  494. <Block>
  495. {
  496. showShareGuide && shareGuideContent()
  497. }
  498. </Block>
  499. {
  500. process.env.TARO_ENV == 'weapp' && <TabBar index={4} />
  501. }
  502. {/* {
  503. homeType == 'NO_FRIEND' && !closeGuide && friendGuide()
  504. } */}
  505. {
  506. showGuide && friendGuide()
  507. }
  508. {
  509. homeType == 'NO_MOMENT' && !closeGuide && empty()
  510. }
  511. </View>
  512. }
  513. function content() {
  514. if (!loaded) {
  515. return <View >
  516. {
  517. process.env.TARO_ENV == 'weapp' && <TabBar index={4} />
  518. }
  519. </View>
  520. }
  521. if (!user.isLogin) {
  522. return friendGuide()
  523. }
  524. return listDetail()
  525. return <View >
  526. <View style={{
  527. position: 'fixed',
  528. top: 0,
  529. left: 0,
  530. zIndex: 10,
  531. height: navigationBarHeight, width: rpxToPx(750), backgroundColor: '#fff', display: 'flex',
  532. flexDirection: 'column', justifyContent: 'flex-end'
  533. }}>
  534. <View style={{ height: 44, width: rpxToPx(750), position: 'relative', display: 'flex', flexDirection: 'row', alignItems: 'center', justifyContent: 'center' }}>
  535. <View>{t('health.moments')}</View>
  536. <View onClick={more} style={{ position: 'absolute', left: 0, top: 0, bottom: 0, width: 80, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>More</View>
  537. </View>
  538. </View>
  539. <View style={{ backgroundColor: '#fff', minHeight: '100vh', paddingTop: navigationBarHeight, marginTop: rpxToPx(60), paddingBottom: 100 }}>
  540. {
  541. dashBoard && dashBoard.new_message && <View className="new_message_bg">
  542. <View className="new_message" onClick={() => {
  543. jumpPage('/_moment/pages/message')
  544. }}>
  545. {
  546. dashBoard.new_message.avatars.map((item, index) => {
  547. return <Image className="message_avatar" src={item} key={index} style={{ zIndex: 9 - index, marginLeft: index == 0 ? rpxToPx(8) : -15 }} />
  548. })
  549. }
  550. <View className="h26 bold" style={{ color: '#fff', minWidth: rpxToPx(260), textAlign: 'center' }}>{dashBoard.new_message.message_tip}</View>
  551. </View>
  552. </View>
  553. }
  554. {
  555. moments.map((item, index) => {
  556. if (itemLayouts.length >= index + 1 && pageTop > 0) {
  557. if (Math.abs(itemLayouts[index] - pageTop) > 2000) {
  558. return <View style={{ height: itemHeights[index] }} id={`history-${index}`}>
  559. </View>
  560. }
  561. // if (Math.abs(itemLayouts[index] - pageTop) > 1500) {
  562. // return <View style={{
  563. // height: itemHeights[index], display: 'flex',
  564. // paddingLeft: rpxToPx(40),
  565. // paddingRight: rpxToPx(40),
  566. // boxSizing: 'border-box',
  567. // flexDirection: 'row'
  568. // }} id={`history-${index}`}>
  569. // <TimelineDate timestamp={item.window_range.start_timestamp}
  570. // pre_timestamp={index > 0 ? list[index - 1].window_range.start_timestamp : null}
  571. // />
  572. // <View style={{
  573. // display: 'flex', flexDirection: 'column', flex: 1,
  574. // width: rpxToPx(552), height: itemHeights[index] - rpxToPx(60), backgroundColor: '#fafafa'
  575. // }}>
  576. // </View>
  577. // </View>
  578. // }
  579. }
  580. return <View key={index} id={`history-{index}`}>
  581. <MomentItem data={item} />
  582. </View>
  583. })
  584. }
  585. <ListFooter noMore={noMore} loading={loading} />
  586. </View>
  587. {
  588. process.env.TARO_ENV == 'weapp' && <TabBar index={4} />
  589. }
  590. </View>
  591. }
  592. return <View>
  593. {
  594. content()
  595. }
  596. <MomentShare />
  597. </View>
  598. return <View>
  599. <ScrollView scrollY style={{ height: '100vh' }}>
  600. <Button openType="share">分享</Button>
  601. <View>好友数量{count}</View>
  602. {
  603. friends.map((item, index) => {
  604. return <View key={index}>
  605. <Image src={item.avatar} style={{ width: 70, height: 70 }} />
  606. <Text>{item.nickname}</Text>
  607. <Text>{item.relation}</Text>
  608. </View>
  609. })
  610. }
  611. <View style={{ height: '100vh', backgroundColor: 'pink', width: rpxToPx(750) }} id="a"></View>
  612. <View style={{ height: '100vh', backgroundColor: 'blue', width: rpxToPx(750) }} id="b"></View>
  613. <View style={{ height: '100vh', backgroundColor: 'yellow', width: rpxToPx(750) }} id="c"></View>
  614. <View style={{ height: '100vh', backgroundColor: 'green', width: rpxToPx(750) }} id="d"></View>
  615. <View style={{ height: '100vh', backgroundColor: 'red', width: rpxToPx(750) }} id="e"></View>
  616. </ScrollView>
  617. {
  618. process.env.TARO_ENV == 'weapp' && <TabBar index={4} />
  619. }
  620. </View>
  621. }