ActivityTypeDetail.tsx 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495
  1. import React, { useEffect, useState } from 'react'
  2. import { useHistory } from 'react-router-dom'
  3. import useRequest from '@ahooksjs/use-request/es'
  4. import dayjs from 'dayjs'
  5. import { Col, Row, Tag, Spin, Modal, message } from 'antd'
  6. import { PlayCircleOutlined } from '@ant-design/icons'
  7. import { ReactComponent as CityImg } from 'assets/city.svg'
  8. import NewImg from 'assets/new.png'
  9. import { useLogin2p } from 'Login2p/Login2pContext'
  10. import { ActivityService, IActivityTypeDetailRes, IArticleListItem, IListndustrialItem } from './Activity.service'
  11. import NoPermission, { INewPermissionType, ISpecialType, ITryType } from 'Material/components/NoPermission'
  12. import AudioControler from './components/AudioControler'
  13. import ActivityBtnComponent, { IStateStringType } from './components/ActivityBtn.component'
  14. import ResearchActivity from 'Community/components/ResearchActivity'
  15. import NButton from 'components/NButton/NButton'
  16. import { setWxShare } from 'utils/wxConfig'
  17. import PayNoPermission from 'Material/components/PayNoPermission'
  18. import Countdown from 'Material/components/Countdown'
  19. import PayProcessModel from 'Material/components/PayProcessModel'
  20. import styles from './css/ActivityTypeDetail.module.scss'
  21. export interface IActivityTypeDetail {
  22. activityID: number
  23. }
  24. /**活动详情页 */
  25. const ActivityTypeDetail: React.FC<IActivityTypeDetail> = props => {
  26. const { activityID } = props
  27. const login2p = useLogin2p()
  28. const history = useHistory()
  29. const [refreshFlag, setRefreshFlag] = useState<boolean>(false)
  30. const [visibleLink, setVisibleLink] = useState<boolean>(false)
  31. const [openContinuePay, setOpenContinuePay] = useState<boolean>(false) // 去继续支付
  32. useEffect(() => {
  33. const code = sessionStorage.getItem('invite_code') || login2p.inviteCode
  34. activityID && run(activityID, code || undefined)
  35. // eslint-disable-next-line react-hooks/exhaustive-deps
  36. }, [activityID])
  37. // 活动详情
  38. const {
  39. data,
  40. loading: activityDetailLoading,
  41. refresh: refreshDetail,
  42. run
  43. } = useRequest(ActivityService.getActivityTypeDetail, {
  44. manual: true,
  45. formatResult: response => response.data.Data,
  46. onSuccess: res => {
  47. res?.Detail && setWxShare(res?.Detail.ActivityName, res?.Detail.ActivityTimeText, res?.Detail.ShareImg)
  48. handleToOtherPage()
  49. }
  50. })
  51. // 取消订单
  52. const { run: postOrderCancel } = useRequest(ActivityService.postOrderCancel, {
  53. manual: true,
  54. formatResult: response => response.data,
  55. onSuccess: res => {
  56. res.Success ? refreshDetail() : message.error(res.Msg || res.ErrMsg)
  57. }
  58. })
  59. // 查看视频
  60. const handleToVideoPage = () => {
  61. if (!data?.Detail.VideoDetail) return
  62. const url = `${window.location.origin}/activity/video/${data?.Detail.VideoDetail.Id}`
  63. window.open(url)
  64. }
  65. // 易董活动跳转地址
  66. const handleToOtherPage = () => {
  67. if (!data?.Detail?.YidongActivityUrl) return
  68. const aLink = document.createElement('a')
  69. aLink.href = data?.Detail.YidongActivityUrl
  70. aLink.target = '_blank'
  71. aLink.click()
  72. }
  73. // 是否存在多篇报告
  74. const handleArticleLink = () => {
  75. if (data?.Detail?.ArticleList.length === 1) {
  76. const url = `${window.location.origin}/material/info/${data?.Detail?.ArticleList[0]?.ArticleId}`
  77. window.open(url)
  78. } else {
  79. setVisibleLink(true)
  80. }
  81. }
  82. const handleClickLink = (item: IArticleListItem) => {
  83. const url = `${window.location.origin}/material/info/${item.ArticleId}`
  84. window.open(url)
  85. }
  86. // 关闭多篇报告的打开
  87. const handleToClose = () => {
  88. setVisibleLink(false)
  89. }
  90. const handleToIndepthPage = (item: IListndustrialItem) => {
  91. // 没有这个页面
  92. if (!item.IsJump) return
  93. // history.push(
  94. // `/indepth/info/${item.ChartPermissionId}/${item.IndustrialManagementId}${
  95. // login2p.inviteCode ? '?invite_code=' + login2p.inviteCode : ''
  96. // }`
  97. // )
  98. }
  99. const formatLinkText = (url: string) => {
  100. return url.indexOf('http') >= 0 ? (
  101. <a href={url} target="_blank" rel="noreferrer" className="detail-link">
  102. {url}
  103. </a>
  104. ) : (
  105. url
  106. )
  107. }
  108. // 登录报名
  109. const handleToShowMore = () => {
  110. if (!login2p.jwt) {
  111. history.push(`/login2p?next=${encodeURIComponent(window.location.pathname + window.location.search)}`)
  112. return
  113. }
  114. }
  115. const handleToRefresh = () => {
  116. // todo
  117. refreshDetail()
  118. setRefreshFlag(!refreshFlag)
  119. setOpenContinuePay(false)
  120. }
  121. // 取消订单
  122. const handleCancelOrder = () => {
  123. if (!data?.OrderCode) return
  124. postOrderCancel(data.OrderCode)
  125. }
  126. // 继续支付
  127. const handleToContinuePay = () => {
  128. if (!data?.OrderCode) return
  129. // todo 打开支付码
  130. setOpenContinuePay(true)
  131. }
  132. const formatCountdown = <Countdown countdown={data?.PayTimeCountdown || 0} />
  133. return (
  134. <div className={styles['activity-detail-page']}>
  135. <Spin spinning={activityDetailLoading}>
  136. <Row>
  137. <Col
  138. xs={{ span: 24, offset: 0 }}
  139. sm={{ span: 24, offset: 0 }}
  140. md={{ span: 24, offset: 0 }}
  141. lg={{ span: 20, offset: 2 }}
  142. xl={{ span: 20, offset: 2 }}
  143. >
  144. <Row wrap={false} gutter={24} justify="start">
  145. <Col flex={1} className="m-b-sm">
  146. {data?.Detail ? (
  147. <div
  148. className={`activity-detail-content ${
  149. data?.HasPermission !== INewPermissionType.OK && data?.IsShowWxPay
  150. ? 'activity-content-nopower'
  151. : ''
  152. }`}
  153. >
  154. {data.OrderCode && data.PayTimeCountdown > 0 && (
  155. <div className="activity-wait-pay-wrapper">
  156. <div className="com-fw-bold com-fz18 m-b-xs">待支付</div>
  157. <div className="com-fw-bold com-fz18">
  158. 剩余支付时间:
  159. <span className="countdown-text">
  160. <Countdown countdown={data.PayTimeCountdown} />
  161. </span>
  162. </div>
  163. <div className="g-flex g-flex-center">
  164. <NButton type="default" size="large" className="m-t-md m-r-md" onClick={handleCancelOrder}>
  165. 取消订单
  166. </NButton>
  167. <NButton type="primary" size="large" className="m-t-md" onClick={handleToContinuePay}>
  168. 去支付
  169. </NButton>
  170. </div>
  171. <PayProcessModel
  172. dataInfo={data}
  173. tryType={ITryType.Activity}
  174. continuePayFlag={openContinuePay}
  175. onRefresh={handleToRefresh}
  176. />
  177. </div>
  178. )}
  179. <div className="activity-detail-title">
  180. {data?.Detail?.IsResearchPoints ? (
  181. <span className={`mfyx-label-normal mfyx-label-kd no-wrap`}>扣点</span>
  182. ) : data?.Detail?.IsExternalLabel ? (
  183. <span className={`mfyx-label-normal mfyx-label-wbzy no-wrap`}>外部资源</span>
  184. ) : null}
  185. <span className="com-fz18">{data?.Detail.ActivityName}</span>
  186. </div>
  187. <div className="activity-detail-list">
  188. {data?.Detail.VoiceDetail && (
  189. <div className="audio-div">
  190. <AudioControler audioDetail={data?.Detail.VoiceDetail} />
  191. </div>
  192. )}
  193. {data?.Detail.VideoDetail && (
  194. <div className="audio-div">
  195. <div className="custom-video" onClick={handleToVideoPage}>
  196. <PlayCircleOutlined className="video-control-play" />
  197. <div className="video-name m-r-lg">{data?.Detail.VideoDetail.Title}</div>
  198. <div className="video-duration">
  199. {dayjs(data?.Detail.VideoDetail.VideoDuration * 1000 - 28800000).format(
  200. data?.Detail.VideoDetail.VideoDuration >= 3600 ? 'HH:mm:ss' : 'mm:ss'
  201. )}
  202. </div>
  203. </div>
  204. </div>
  205. )}
  206. <div className="activity-detail-line">
  207. <span className="activity-detail-label">活动类型:</span>
  208. <span className="g-va-middle no-wrap">{data?.Detail.ActivityTypeName}</span>
  209. {data?.Detail.City && (
  210. <div className="city-wrapper g-va-middle">
  211. <CityImg fill="#faa12f" className="city-img" />
  212. <span className="g-va-middle">{data?.Detail.City}</span>
  213. </div>
  214. )}
  215. </div>
  216. <div className="activity-detail-line">
  217. <span className="activity-detail-label">产业标签:</span>
  218. {data?.Detail.Label && <span className="m-r-md"> {data?.Detail.Label}</span>}
  219. <div>
  220. {data?.Detail?.Listndustrial?.map(item => (
  221. <React.Fragment key={item.IndustrialManagementId}>
  222. <Tag
  223. color={item.IsJump ? 'blue' : 'default'}
  224. className={`tag-ml ${item.IsJump ? 'com-cursor-p' : ''}`}
  225. onClick={handleToIndepthPage.bind(this, item)}
  226. >
  227. {item.IndustryName}
  228. </Tag>
  229. {item.IndustryNewLabel && <img src={NewImg} alt="新的" className="new-flag" />}
  230. </React.Fragment>
  231. ))}
  232. </div>
  233. </div>
  234. <div className="activity-detail-line">
  235. <span className="activity-detail-label">活动时间:</span>
  236. {data?.Detail.ActivityTimeText}
  237. </div>
  238. {data?.Detail.DistinguishedGuest && (
  239. <div className="activity-detail-line">
  240. <span className="activity-detail-label">嘉宾:</span>
  241. {data?.Detail.DistinguishedGuest}
  242. </div>
  243. )}
  244. {data?.Detail.Host && (
  245. <div className="activity-detail-line">
  246. <span className="activity-detail-label">主持人:</span>
  247. {data?.Detail.Host}
  248. </div>
  249. )}
  250. {data?.Detail.Speaker && (
  251. <div className="activity-detail-line">
  252. <span className="activity-detail-label">主讲人:</span>
  253. {data?.Detail.Speaker}
  254. </div>
  255. )}
  256. {data?.Detail.Expert && (
  257. <div className="activity-detail-line">
  258. <span className="activity-detail-label">专家背景:</span>
  259. <div dangerouslySetInnerHTML={{ __html: data?.Detail.Expert }} className="reset-pm" />
  260. </div>
  261. )}
  262. {login2p.jwt && data?.HasPermission === INewPermissionType.OK && data?.Detail.Address && (
  263. <div className="activity-detail-line">
  264. <span className="activity-detail-label">活动地点:</span>
  265. {data.Detail.ActivityTypeId === 4
  266. ? data.Detail.IsSignup
  267. ? data?.Detail.Address
  268. : '请报名获取'
  269. : data?.Detail.Address}
  270. </div>
  271. )}
  272. {data?.Detail.MainlandTell && (
  273. <div className="activity-detail-line">
  274. <span className="activity-detail-label">大陆拨入:</span>
  275. <span className="detail-link">{data?.Detail.MainlandTell}</span>
  276. </div>
  277. )}
  278. {data?.Detail.HongKongTell && (
  279. <div className="activity-detail-line">
  280. <span className="activity-detail-label">香港拨入:</span>
  281. <span className="detail-link">{data?.Detail.HongKongTell}</span>
  282. </div>
  283. )}
  284. {data?.Detail.TaiwanTell && (
  285. <div className="activity-detail-line">
  286. <span className="activity-detail-label">台湾拨入:</span>
  287. <span className="detail-link">{data?.Detail.TaiwanTell}</span>
  288. </div>
  289. )}
  290. {data?.Detail.AmericaTell && (
  291. <div className="activity-detail-line">
  292. <span className="activity-detail-label">美国拨入:</span>
  293. <span className="detail-link">{data?.Detail.AmericaTell}</span>
  294. </div>
  295. )}
  296. {login2p.jwt &&
  297. data?.HasPermission === INewPermissionType.OK &&
  298. data?.Detail.ParticipationCode && (
  299. <div className="activity-detail-line">
  300. <span className="activity-detail-label">拨入密码:</span>
  301. {!!data?.Detail.IsLimitPeople
  302. ? data.Detail.IsSignup
  303. ? data?.Detail.ParticipationCode
  304. : '请报名获取'
  305. : data?.Detail.ParticipationCode}
  306. </div>
  307. )}
  308. {login2p.jwt &&
  309. data?.HasPermission === INewPermissionType.OK &&
  310. data?.Detail.OnlineParticipation && (
  311. <div className="activity-detail-line">
  312. <span className="activity-detail-label">网络参会:</span>
  313. {!!data?.Detail.IsLimitPeople &&
  314. !data.Detail.IsSignup &&
  315. [1, 2].includes(data.Detail.ActivityTypeId) ? (
  316. '请报名获取'
  317. ) : (
  318. <a
  319. href={data?.Detail.OnlineParticipation}
  320. target="_blank"
  321. rel="noreferrer"
  322. className="detail-link"
  323. >
  324. {data?.Detail.OnlineParticipation}
  325. </a>
  326. )}
  327. </div>
  328. )}
  329. {login2p.jwt &&
  330. data?.HasPermission === INewPermissionType.OK &&
  331. data?.Detail.LinkParticipants && (
  332. <div className="activity-detail-line">
  333. <span className="activity-detail-label">链接参会:</span>
  334. {!!data?.Detail.IsLimitPeople
  335. ? data.Detail.IsSignup
  336. ? formatLinkText(data?.Detail.LinkParticipants)
  337. : '请报名获取'
  338. : formatLinkText(data?.Detail.LinkParticipants)}
  339. </div>
  340. )}
  341. {(data?.Detail?.ArticleList?.length || 0) > 0 && (
  342. <div className="activity-detail-line">
  343. <span className="activity-detail-label">相关报告:</span>
  344. <div onClick={handleArticleLink} className="detail-btn-link">
  345. 点击查看
  346. </div>
  347. </div>
  348. )}
  349. {data?.Detail.Theme && (
  350. <div className="activity-detail-line">
  351. <span className="activity-detail-label">主题:</span>
  352. <div dangerouslySetInnerHTML={{ __html: data?.Detail.Theme }} className="reset-pm" />
  353. </div>
  354. )}
  355. {login2p.jwt &&
  356. data?.HasPermission === INewPermissionType.OK &&
  357. data?.Detail.TencentConferenceNumber && (
  358. <div className="activity-detail-line">
  359. <span className="activity-detail-label">腾讯会议号:</span>
  360. <div className="detail-link">
  361. {!!data?.Detail.IsLimitPeople || data.Detail.IsYidongConduct
  362. ? data.Detail.IsSignup
  363. ? data?.Detail.TencentConferenceNumber
  364. : '请报名获取'
  365. : data?.Detail.TencentConferenceNumber}
  366. </div>
  367. </div>
  368. )}
  369. {data?.Detail.AppAttendance && (
  370. <div className="activity-detail-line">
  371. <span className="activity-detail-label">App参会:</span>
  372. {data.Detail.AppAttendance}
  373. </div>
  374. )}
  375. {login2p.jwt &&
  376. data?.HasPermission === INewPermissionType.OK &&
  377. data?.Detail.ConferencePassword && (
  378. <div className="activity-detail-line">
  379. <span className="activity-detail-label">会议密码:</span>
  380. {!!data?.Detail.IsLimitPeople
  381. ? data.Detail.IsSignup
  382. ? data.Detail.ConferencePassword
  383. : '请报名获取'
  384. : data.Detail.ConferencePassword}
  385. </div>
  386. )}
  387. {data?.Detail.Highlights && (
  388. <div className="activity-detail-line">
  389. <span className="activity-detail-label">活动亮点:</span>
  390. <div dangerouslySetInnerHTML={{ __html: data?.Detail.Highlights }} className="reset-pm" />
  391. </div>
  392. )}
  393. {data?.Detail.Remarks && (
  394. <div className="activity-detail-line">
  395. <span className="activity-detail-label">备注:</span>
  396. <div dangerouslySetInnerHTML={{ __html: data?.Detail.Remarks }} className="reset-pm" />
  397. </div>
  398. )}
  399. </div>
  400. {login2p.jwt &&
  401. data.HasPermission === INewPermissionType.OK &&
  402. data?.Detail.ActiveState !== IStateStringType.End &&
  403. data?.Detail && (
  404. <div className="detail-btn-wrapper">
  405. <ActivityBtnComponent
  406. item={data?.Detail}
  407. btnGrous="detail"
  408. onChangeSomething={refreshDetail}
  409. />
  410. </div>
  411. )}
  412. {!login2p.jwt && (
  413. <div className="detail-btn-wrapper">
  414. <NButton type="primary" onClick={handleToShowMore} size="login-large" className="m-center">
  415. 请登录后报名
  416. </NButton>
  417. </div>
  418. )}
  419. {!activityDetailLoading &&
  420. login2p.jwt &&
  421. data?.HasPermission !== INewPermissionType.OK &&
  422. data?.IsShowWxPay ? (
  423. <div className="activity-paynopermission-wrapper">
  424. <div className="white-wrapper" />
  425. <div className="white-bg">
  426. <PayNoPermission
  427. dataInfo={data as IActivityTypeDetailRes}
  428. tryType={ITryType.Activity}
  429. onRefresh={handleToRefresh}
  430. />
  431. </div>
  432. </div>
  433. ) : null}
  434. </div>
  435. ) : null}
  436. {!activityDetailLoading &&
  437. login2p.jwt &&
  438. data?.HasPermission !== INewPermissionType.OK &&
  439. !data?.IsShowWxPay ? (
  440. <NoPermission
  441. hasPermission={data?.HasPermission}
  442. detailID={activityID}
  443. specialType={
  444. data?.IsResearchSpecial
  445. ? ISpecialType.ResearchSpecial
  446. : data?.IsResearch
  447. ? ISpecialType.ResearchActivity
  448. : ISpecialType.Activity
  449. }
  450. tryType={ITryType.Activity}
  451. border={true}
  452. />
  453. ) : null}
  454. </Col>
  455. <Col flex={'542px'} xs={0} sm={0} md={0} lg={0} xl={24} xxl={24}>
  456. <ResearchActivity isRefresh={refreshFlag} />
  457. </Col>
  458. </Row>
  459. </Col>
  460. </Row>
  461. </Spin>
  462. <Modal
  463. open={visibleLink}
  464. title="请选择报告"
  465. onCancel={handleToClose}
  466. destroyOnClose={true}
  467. maskClosable={false}
  468. footer={null}
  469. centered
  470. >
  471. <div>
  472. {data?.Detail?.ArticleList?.map(item => (
  473. <p key={item.ArticleId} onClick={handleClickLink.bind(this, item)} className="detail-dialog-link">
  474. {item.Title}
  475. </p>
  476. ))}
  477. </div>
  478. </Modal>
  479. </div>
  480. )
  481. }
  482. export default ActivityTypeDetail