index.tsx 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. import React, { useState, useEffect, useMemo } from 'react'
  2. import styles from './index.module.scss'
  3. import classNames from 'classnames'
  4. import http from '@/utils/http'
  5. import { useHistory, useLocation } from 'react-router-dom'
  6. import StartVideo from './component/startVideo'
  7. import like from './image/icon_like.png'
  8. import share from './image/icon_share.png'
  9. import intro from './image/icon_intro.png'
  10. import arrow from './image/arrow.png'
  11. import { message } from 'antd'
  12. import { Intro, MapIntro } from './component/Intro'
  13. import { Preview } from './component/Preview'
  14. import isMobile from '@/utils/isMobile'
  15. import Panoramic from './component/Panoramic'
  16. const imgArrTemp = [
  17. { src: 'Bao-0.png', title: '基本情况' },
  18. { src: 'Bao-1.jpg', title: '休息洽谈区' },
  19. { src: 'Bao-2.jpg', title: '汇报展示厅' },
  20. { src: 'Bao-3.jpg', title: '会议室' },
  21. { src: 'Bao-4.jpg', title: '智慧教室' },
  22. { src: 'Bao-5.jpg', title: '共享工作室' },
  23. { src: 'Bao-6.jpg', title: '共享办公区' },
  24. { src: 'Bao-7.jpg', title: '贵宾接待室' },
  25. { src: 'Bao-8.jpg', title: '茶憩文印室' },
  26. { src: 'Bao-9.jpg', title: '休闲展览区' },
  27. { src: 'Bao-10.jpg', title: '走廊' }
  28. ]
  29. const imgArrTemp2 = [
  30. { src: 'nan-0.png', title: '基本情况' },
  31. { src: 'nan-1.jpg', title: '校史走廊' },
  32. { src: 'nan-2.jpg', title: '校友之家' },
  33. { src: 'nan-3.jpg', title: '专家办公室' },
  34. { src: 'nan-4.jpg', title: '智慧教室' },
  35. { src: 'nan-5.jpg', title: '开放办公区' },
  36. { src: 'nan-6.jpg', title: '会议室' }
  37. ]
  38. function Layout({ setIsFloor }: { setIsFloor: (isFloor: boolean) => void }) {
  39. const history = useHistory()
  40. return (
  41. <div className={classNames(styles.layout, isMobile() && styles.layoutMobile)}>
  42. <div className='back' onClick={() => setIsFloor(false)}>
  43. <img src={require('./image/back.png')} alt='' />
  44. </div>
  45. <div className='layout-container'>
  46. <div
  47. className='floor-1'
  48. onClick={() => {
  49. history.push('/home?m=SG-NqtcxoVBj5C')
  50. setTimeout(() => {
  51. window.location.reload()
  52. }, 200)
  53. }}
  54. >
  55. <span>楼层23</span>
  56. </div>
  57. <div
  58. className='floor-2'
  59. onClick={() => {
  60. history.push('/home?m=SG-dwRgbFq7Fiz')
  61. setTimeout(() => {
  62. window.location.reload()
  63. }, 200)
  64. }}
  65. >
  66. <span>楼层22</span>
  67. </div>
  68. <img src={arrow} alt='' className='arrow' />
  69. </div>
  70. </div>
  71. )
  72. }
  73. function A0Base() {
  74. const location = useLocation()
  75. const [isEnd, setIsEnd] = useState(location.state ?? false)
  76. const [showIntro, setShowIntro] = useState(false)
  77. const [isFloor, setIsFloor] = useState(false)
  78. const [isPreview, setIsPreview] = useState<[boolean, string]>([false, ''])
  79. const [likeCount, setLikeCount] = useState(0)
  80. const [isLike, setIsLike] = useState(false)
  81. const [isMouseMove, setIsMouseMove] = useState(false)
  82. const floor22sceneCode = 'SG-dwRgbFq7Fiz'
  83. // const floor23sceneCode = 'SG-NqtcxoVBj5C'
  84. useEffect(() => {
  85. http.get(`https://count.4dage.com/api/count/detail/${floor22sceneCode}`).then(res => {
  86. setLikeCount(res.data.starSum)
  87. })
  88. }, [])
  89. const handleIntroClick = (isShow: boolean) => {
  90. setShowIntro(isShow)
  91. }
  92. const handleShareClick = () => {
  93. try {
  94. if (window.isSecureContext && navigator.clipboard) {
  95. navigator.clipboard.writeText(window.location.href).then(() => {
  96. message.success('链接已复制到剪贴板')
  97. })
  98. } else {
  99. // 回退到旧方法
  100. const textArea = document.createElement('textarea')
  101. textArea.value = window.location.href
  102. document.body.appendChild(textArea)
  103. textArea.select()
  104. document.execCommand('copy')
  105. document.body.removeChild(textArea)
  106. message.success('链接已复制到剪贴板')
  107. }
  108. } catch (err) {
  109. console.error('复制失败:', err)
  110. // 可提示用户手动复制
  111. message.error('浏览器不支持自动复制,请手动复制当前链接')
  112. }
  113. }
  114. const handleLikeClick = () => {
  115. if (isLike) return
  116. setIsLike(true)
  117. setTimeout(() => {
  118. http.get(`https://count.4dage.com/api/count/saveStar/${floor22sceneCode}`).then(res => {
  119. setLikeCount(likeCount + 1)
  120. setIsLike(false)
  121. })
  122. }, 2000)
  123. }
  124. const isWeChat = useMemo(() => /MicroMessenger/i.test(navigator.userAgent), [])
  125. return (
  126. <>
  127. {!isEnd && !isWeChat ? (
  128. <StartVideo setIsEnd={setIsEnd} />
  129. ) : (
  130. <div
  131. className={classNames(styles.A0base, isMobile() && styles.A0baseMobile)}
  132. style={{
  133. backgroundImage: isFloor
  134. ? isMobile()
  135. ? `url(${require('./image/M_bg_floor.png')})`
  136. : `url(${require('./image/bg_floor.png')})`
  137. : isMobile()
  138. ? `url(${require('./image/M_bg_map.png')})`
  139. : `none`
  140. }}
  141. >
  142. {isFloor && !showIntro && <Layout setIsFloor={setIsFloor} />}
  143. <Panoramic
  144. setIsFloor={setIsFloor}
  145. setIsPreview={setIsPreview}
  146. isDisolay={!isFloor && !isPreview[0]}
  147. setIsMouseMove={setIsMouseMove}
  148. />
  149. {showIntro &&
  150. (isFloor ? (
  151. <Intro handleIntroClick={handleIntroClick} />
  152. ) : (
  153. <MapIntro handleIntroClick={handleIntroClick} />
  154. ))}
  155. {isPreview[0] && (
  156. <Preview
  157. imgArr={isPreview[1] === 'baoan' ? imgArrTemp : imgArrTemp2}
  158. setIsPreview={setIsPreview}
  159. type={isPreview[1]}
  160. />
  161. )}
  162. {/* logo */}
  163. <div
  164. className='A0_logo'
  165. style={{
  166. display: isPreview[0] || (isMobile() && showIntro) || isFloor ? 'none' : 'block'
  167. }}
  168. >
  169. <img src={require('./image/logo.png')} alt='' />
  170. </div>
  171. {/* 克劳德 */}
  172. <div className='A0_cloud1'>
  173. <img
  174. className={classNames(isMouseMove && 'a0_cloud1move')}
  175. src={require('./image/cloud1.png')}
  176. alt=''
  177. />
  178. <img
  179. className={classNames(isMouseMove && 'a0_cloud1move2')}
  180. src={require('./image/cloud1.png')}
  181. alt=''
  182. />
  183. <img
  184. className={classNames(isMouseMove && 'a0_cloud1move3')}
  185. src={require('./image/cloud1.png')}
  186. alt=''
  187. />
  188. </div>
  189. <div className={classNames('A0_cloud2', isMouseMove && 'a0_cloud2move')}>
  190. <img
  191. style={{}}
  192. className={classNames(isMouseMove && 'a0_cloud1move4')}
  193. src={require('./image/cloud2.png')}
  194. alt=''
  195. />
  196. <img
  197. className={classNames(isMouseMove && 'a0_cloud1move5')}
  198. style={{
  199. position: 'absolute',
  200. right: '0',
  201. bottom: '-37%'
  202. }}
  203. src={require('./image/cloud2.png')}
  204. alt=''
  205. />
  206. <img
  207. className={classNames(isMouseMove && 'a0_cloud1move5')}
  208. style={{
  209. position: 'absolute',
  210. right: '0px',
  211. bottom: '84px'
  212. }}
  213. src={require('./image/cloud1.png')}
  214. alt=''
  215. />
  216. </div>
  217. {/* 图标栏 */}
  218. <div
  219. className='A0_iconBar'
  220. style={{ display: isPreview[0] || (isMobile() && showIntro) ? 'none' : 'flex' }}
  221. >
  222. <div className='A0_icon' onClick={() => handleLikeClick()}>
  223. <div
  224. className={classNames(isLike ? 'addLikeAc' : '', 'addLike')}
  225. style={{ opacity: !isLike ? 0 : 1 }}
  226. >
  227. +1
  228. </div>
  229. <img className='A0_icon_like' src={like} alt='' />
  230. <div>{likeCount}次赞</div>
  231. </div>
  232. <div className='A0_icon'>
  233. <img
  234. className='A0_icon_intro'
  235. onClick={() => setShowIntro(true)}
  236. src={intro}
  237. alt=''
  238. />
  239. <div>简介</div>
  240. </div>
  241. <div className='A0_icon' onClick={() => handleShareClick()}>
  242. <img className='A0_icon_share' src={share} alt='' />
  243. <div>分享</div>
  244. </div>
  245. </div>
  246. </div>
  247. )}
  248. </>
  249. )
  250. }
  251. const MemoA0Base = React.memo(A0Base)
  252. export default MemoA0Base