NewestLibrary.tsx 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. import React, { useEffect, useState } from 'react'
  2. import useRequest from '@ahooksjs/use-request/es'
  3. import { useHistory } from 'react-router-dom'
  4. import { ReactComponent as Close2 } from 'assets/close2.svg'
  5. import { getQueryString } from 'utils/getQueryString'
  6. import { useMedia } from 'Context/Media/MediaContext'
  7. import { useLogin2p } from 'Login2p/Login2pContext'
  8. import MasonryContainer from 'Material/components/Masonry.component'
  9. import { IItemType } from '../../Material/components/Item.component'
  10. import AudioFix from 'Activity/components/AudioFix'
  11. import { IBannerListRes, INewestList, ITagList, NewestService } from 'Newest/Newest.service'
  12. import { IAudioDetail, IPermissionItem } from 'Activity/Activity.service'
  13. import CustormSwiper from './CustomSwiper'
  14. import ColumnInfoEdit from 'Column/components/ColumnInfoEdit'
  15. import { IColumnInfo } from 'Column/Column.service'
  16. import styles from '../css/NewestIndex.module.scss'
  17. const pageSize = 20
  18. /**
  19. * 首页
  20. */
  21. const NewestLibrary: React.FC = props => {
  22. const media = useMedia()
  23. const login2p = useLogin2p()
  24. const history = useHistory()
  25. // const _pageSize = login2p.jwt ? pageSize : media.isMaxWrap ? 3 : 5
  26. const [data, setData] = useState<INewestList[]>([])
  27. const [hasMore, setHasMore] = useState<boolean>(true)
  28. const [page, setPage] = useState<number>(1) // 当前页
  29. const [audioVisible, setAudioVisible] = useState<boolean>(false)
  30. const [audioItem, setAudioItem] = useState<IAudioDetail>()
  31. const [actTagKeyword, setActTagKeyword] = useState<string>() // 活动标签/报告标签
  32. const [themeKeyword, setThemeKeyword] = useState<string>() // 主题标签
  33. const [columnCloseFlag, setColumnCloseFlag] = useState<boolean>(true) // 是否关闭专栏icon
  34. const [editInfoVisible, setEditInfoVisible] = useState<boolean>(false) // 修改专栏信息
  35. // const [tagCheckList, setTagCheckList] = useState<string[]>([]) // 记录标签归类List
  36. // const [permissionID, setPermissionID] = useState<number | undefined>(undefined) // 选中的行业
  37. let timer: NodeJS.Timeout | null = null
  38. useEffect(() => {
  39. setData([])
  40. setPage(1)
  41. // setPermissionID(undefined)
  42. setActTagKeyword(undefined)
  43. setThemeKeyword(undefined)
  44. // const pid = getQueryString('pid')
  45. // const ids = getQueryString('ids')
  46. // pid && setPermissionID(Number(pid))
  47. // ids && setActTagKeyword(ids.split(',').map(item => item))
  48. // !pid && !ids && setTagCheckList([])
  49. getNewestList({ PageSize: pageSize, CurrentIndex: 1, HashtagKeyword: themeKeyword, LabelKeyword: actTagKeyword })
  50. // eslint-disable-next-line react-hooks/exhaustive-deps
  51. }, [history.location.search])
  52. // 拉取Banner
  53. const { loading: bannerLoading, data: bannerList } = useRequest(NewestService.getBannerList, {
  54. formatResult: response => response.data.Data
  55. })
  56. // 拉取标签
  57. const { data: tagData } = useRequest(NewestService.getCustomTagList, {
  58. formatResult: response => response.data.Data
  59. })
  60. // 拉取数据
  61. const { loading: dataLoading, run: getNewestList } = useRequest(NewestService.getNewestList, {
  62. manual: true,
  63. onSuccess: res => {
  64. res.data.Data?.List &&
  65. setData(login2p.jwt ? [...data, ...res.data.Data?.List] : res.data.Data?.List.slice(0, pageSize))
  66. setHasMore(res.data.Data ? !res.data.Data?.Paging?.IsEnd : false)
  67. }
  68. })
  69. // banner数据处理
  70. const handleRenderBanner = (data?: IBannerListRes) => {
  71. if (!data) return
  72. // 计算有几组数据
  73. let listCout = 0
  74. if (data.ListA.length > 0) listCout += 1
  75. if (data.ListB.length > 0) listCout += 1
  76. if (data?.ListC?.length > 0) listCout += 1
  77. // 一块都没有呢
  78. if (listCout === 0) return
  79. // 3块都有呢,为T3模式
  80. let _ListA = data.ListA
  81. let _ListB = data.ListB
  82. let _ListC = data?.ListC
  83. // 2块呢,为T2模式
  84. if (listCout === 2) {
  85. _ListA = data.ListA.length > 0 ? data.ListA : data.ListB
  86. _ListB = data.ListA.length > 0 ? (data.ListB.length > 0 ? data.ListB : data?.ListC) : data?.ListC
  87. _ListC = []
  88. }
  89. if (listCout === 1) {
  90. _ListA = data.ListA.length > 0 ? data.ListA : data.ListB.length > 0 ? data.ListB : data?.ListC
  91. _ListB = []
  92. _ListC = []
  93. }
  94. return (
  95. <div className={styles['newest-top-banner']}>
  96. <div className={`newest-banner-box ${listCout === 1 ? 'banner-t1' : 'banner-t2'} `}>
  97. <CustormSwiper name="bannera" list={_ListA} boxSize={listCout === 1 ? 'block' : 'large'} />
  98. </div>
  99. {(_ListB.length > 0 || _ListC.length > 0) && (
  100. <div className="banner-right-t2">
  101. <div className={`newest-banner-box ${listCout === 2 ? '' : 'banner-right-t3 m-r-sm'}`}>
  102. <CustormSwiper name="bannerb" list={_ListB} boxSize={listCout === 2 ? 'middle' : 'small'} />
  103. </div>
  104. {_ListC.length > 0 && (
  105. <div className="newest-banner-box banner-right-t3 m-l-sm">
  106. <CustormSwiper name="bannerc" list={_ListC} boxSize="small" />
  107. </div>
  108. )}
  109. </div>
  110. )}
  111. </div>
  112. )
  113. }
  114. const handleLoadMoreData = () => {
  115. if (!login2p.jwt || dataLoading || !hasMore) return
  116. setPage(page + 1)
  117. getNewestList({
  118. PageSize: pageSize,
  119. CurrentIndex: page + 1,
  120. HashtagKeyword: themeKeyword,
  121. LabelKeyword: actTagKeyword
  122. })
  123. }
  124. const handleOnClick = (item: INewestList) => {
  125. if (!item) return
  126. // 视频播放
  127. if (item.Source === IItemType.Activityvideo) {
  128. const url = `${window.location.origin}/activity/video/${(item as INewestList).SourceId}`
  129. window.open(url)
  130. return
  131. }
  132. if (item.Source === IItemType.Roadshow) {
  133. const url = `${window.location.origin}/indepth/video/${item.Roadshow.ChartPermissionId}/${item.Roadshow.IndustrialManagementId}/${item.Roadshow?.Id}`
  134. window.open(url)
  135. return
  136. }
  137. // 音频播放
  138. if (item.Source === IItemType.Activityvoice && item.Activityvoice) {
  139. setAudioItem({
  140. ActivityId: item.SourceId,
  141. Name: item.Activityvoice.Title,
  142. Url: item.Activityvoice.ResourceUrl,
  143. Type: item.Activityvoice.Type
  144. })
  145. setAudioVisible(true)
  146. return
  147. }
  148. if (item.Source === IItemType.AskserieVideo && item.AskserieVideo) {
  149. setAudioItem({
  150. ActivityId: item.SourceId,
  151. Name: item.AskserieVideo.Title,
  152. Url: item.AskserieVideo.ResourceUrl,
  153. Type: item.AskserieVideo.Type
  154. })
  155. setAudioVisible(true)
  156. return
  157. }
  158. }
  159. const handleCloseAudio = () => {
  160. setAudioVisible(false)
  161. }
  162. // 标签样式
  163. const handleIncludeIds = (keyword: string, type?: 'activity' | 'theme') => {
  164. if (type === 'theme') {
  165. return themeKeyword === keyword
  166. ? 'newestindex-label-theme-item act-newestindex-theme-label'
  167. : 'newestindex-label-theme-item'
  168. }
  169. return actTagKeyword === keyword ? 'newestindex-label-item act-newestindex-label' : 'newestindex-label-item'
  170. }
  171. // 标签点击
  172. const handleClickTag = (tagItem: string, type: 'activity' | 'theme') => {
  173. const labelClick: {
  174. [key: string]: () => void
  175. } = {
  176. ['activity']: () => (tagItem === actTagKeyword ? setActTagKeyword(undefined) : setActTagKeyword(tagItem)),
  177. ['theme']: () => (tagItem === themeKeyword ? setThemeKeyword(undefined) : setThemeKeyword(tagItem))
  178. }
  179. labelClick[type]()
  180. if (timer) {
  181. clearTimeout(timer)
  182. timer = null
  183. }
  184. timer = setTimeout(() => {
  185. timer = null
  186. setData([])
  187. setPage(1)
  188. getNewestList({
  189. PageSize: pageSize,
  190. CurrentIndex: 1,
  191. HashtagKeyword: type === 'theme' ? (tagItem === themeKeyword ? undefined : tagItem) : themeKeyword,
  192. LabelKeyword: type === 'activity' ? (tagItem === actTagKeyword ? undefined : tagItem) : actTagKeyword
  193. })
  194. })
  195. // history.replace(
  196. // `${permissionID ? '?pid=' + permissionID : ''}${
  197. // IDs.length > 0 ? (permissionID ? '&' : '?') + 'ids=' + IDs.toString() : ''
  198. // }`
  199. // )
  200. }
  201. // const handleClickPermission = (permissionItem: IPermissionItem) => {
  202. // setPermissionID(permissionID === permissionItem.ChartPermissionId ? undefined : permissionItem.ChartPermissionId)
  203. // history.replace(
  204. // `${permissionID !== permissionItem.ChartPermissionId ? '?pid=' + permissionItem.ChartPermissionId : ''}${
  205. // actTagKeyword.length > 0
  206. // ? (permissionID !== permissionItem.ChartPermissionId ? '&' : '?') + 'ids=' + actTagKeyword.toString()
  207. // : ''
  208. // }`
  209. // )
  210. // }
  211. const handleDeleteIcon = (e: React.MouseEvent<SVGSVGElement, MouseEvent>) => {
  212. e.stopPropagation()
  213. setColumnCloseFlag(false)
  214. }
  215. const handleToColumn = () => {
  216. if (!login2p.userInfo?.IsImproveInformation) {
  217. setEditInfoVisible(true)
  218. return
  219. }
  220. history.push(
  221. `/column/view/${login2p.userInfo?.SpecialColumnId}${
  222. login2p.inviteCode ? '?invite_code=' + login2p.inviteCode : ''
  223. }`
  224. )
  225. }
  226. const handleSaveEditEnd = () => {
  227. handleCloseEdit()
  228. history.push(
  229. `/column/view/${login2p.userInfo?.SpecialColumnId}${
  230. login2p.inviteCode ? '?invite_code=' + login2p.inviteCode : ''
  231. }`
  232. )
  233. }
  234. const handleCloseEdit = () => {
  235. setEditInfoVisible(false)
  236. }
  237. return (
  238. <>
  239. {login2p.userInfo?.IsAuthor && columnCloseFlag ? (
  240. <div className={styles['fixed-column-wrapper']} onClick={handleToColumn}>
  241. <div className="fixed-column-text">我的专栏</div>
  242. <Close2 className="fixed-column-close" onClick={handleDeleteIcon} />
  243. </div>
  244. ) : null}
  245. {editInfoVisible ? (
  246. <ColumnInfoEdit
  247. visible={editInfoVisible}
  248. info={{ Id: login2p.userInfo?.SpecialColumnId } as IColumnInfo}
  249. onClose={handleCloseEdit}
  250. onRefresh={handleSaveEditEnd}
  251. />
  252. ) : null}
  253. <AudioFix audioDetail={audioItem as IAudioDetail} visible={audioVisible} onClose={handleCloseAudio} />
  254. {handleRenderBanner(bannerList)}
  255. {/* {tagData && tagData?.ListPermission?.length > 0 && (
  256. <div className={styles['newestindex-label-wrapper']}>
  257. {tagData?.ListPermission?.map((item: IPermissionItem) => (
  258. <div
  259. className={`newest-permission-item ${
  260. permissionID === item.ChartPermissionId ? 'newest-act-permission' : ''
  261. }`}
  262. key={item.ChartPermissionId}
  263. onClick={handleClickPermission.bind(this, item)}
  264. >
  265. {item.PermissionName}
  266. </div>
  267. ))}
  268. </div>
  269. )} */}
  270. {tagData && tagData?.List1?.length > 0 && (
  271. <div className="m-r-md g-inline-block">
  272. <div className={styles['newestindex-label-wrapper']}>
  273. {tagData?.List1?.map((item: string, index: number) => (
  274. <div className={handleIncludeIds(item)} key={index} onClick={handleClickTag.bind(this, item, 'activity')}>
  275. {item}
  276. </div>
  277. ))}
  278. </div>
  279. </div>
  280. )}
  281. {tagData && tagData?.List2?.length > 0 && (
  282. <div className="g-inline-block">
  283. <div className={styles['newestindex-label-wrapper']}>
  284. {tagData?.List2?.map((item: string, index: number) => (
  285. <div className={handleIncludeIds(item)} key={index} onClick={handleClickTag.bind(this, item, 'activity')}>
  286. {item}
  287. </div>
  288. ))}
  289. </div>
  290. </div>
  291. )}
  292. {tagData && tagData?.List3?.length > 0 && (
  293. <div className={styles['newestindex-label-wrapper']}>
  294. {tagData?.List3?.map((item: string, index: number) => (
  295. <div
  296. className={handleIncludeIds(item, 'theme')}
  297. key={index}
  298. onClick={handleClickTag.bind(this, item, 'theme')}
  299. >
  300. {item}
  301. </div>
  302. ))}
  303. </div>
  304. )}
  305. <div>
  306. <MasonryContainer
  307. loadMore={handleLoadMoreData}
  308. hasMore={hasMore}
  309. loading={dataLoading || bannerLoading}
  310. dataSource={data || []}
  311. itemType={IItemType.NormalChart}
  312. onItemClick={handleOnClick}
  313. />
  314. </div>
  315. </>
  316. )
  317. }
  318. export default NewestLibrary