/* eslint-disable indent */ /* eslint-disable no-undef */ /* eslint-disable react-hooks/exhaustive-deps */ /* eslint-disable global-require */ /* * @Title: * @Author: hongmye * @Date: 2023-12-26 18:34:42 */ import { DoubleLeftOutlined, FullscreenExitOutlined, FullscreenOutlined, RightOutlined } from '@ant-design/icons'; import backImg from '@/assets/images/demonstration/返回.png'; import arrowLeftImg from '@/assets/images/demonstration/左箭头.png'; import { Button, message } from 'antd'; import React, { useMemo, useState, useEffect, useRef } from 'react'; import { cloneDeep, debounce } from 'lodash'; import { appService } from '@/api'; import { actionCreators } from '@/containers/App/store'; import { connect } from 'react-redux'; import classNames from 'classnames'; import { defaultApp } from '@/micro'; import moment from 'moment'; import LoadPage from '@/components/LoadPage'; import useFullScreen from './components/useFullScreen'; import styles from './index.less'; import LeftItem from './components/Left'; import VideoItem from './components/VideoItem'; import Iframe from './components/Iframe'; import RightItem from './components/Right'; import BottomItem from './components/Bottom'; import { platformData } from './components/configData'; const boxWidth = 1920; const boxHeight = 910; const Demonstration = props => { const onLineUrl = window.globalConfig?.mainserver || 'https://panda-water.cn/'; const showFullScreen = true; const videoRef = useRef(null); const progressRef = useRef(0); const timer = useRef(null); const [progressValue, setProgressValue] = useState(0); const progressRef2 = useRef(0); const timer2 = useRef(null); const timer3 = useRef(null); const [progressValue2, setProgressValue2] = useState(0); const [loading, setLoading] = useState(true); const [projectConfig, setProjectConfig] = useState({}); // 项目案例是否可免密跳转 const [showContent, setShowContent] = useState(false); const [jumpLoading, setJumpLoading] = useState(false); const [selectKey, setSelectKey] = useState('供水产品'); const [boxSize, setBoxSize] = useState({ scale: 1, boxHeight: 910, }); const [linkUrl, setLinkUrl] = useState(''); const [projectData, setProjectData] = useState([]); const [configData, setConfigData] = useState([]); const [productData, setProductData] = useState([]); const [newProductData, setNewProductData] = useState([]); const [productConfig, setProductConfig] = useState({}); // 项目案例是否可免密跳转 const [showAnimation, setShowAnimation] = useState(true); const [showBackBtn, setShowBackBtn] = useState(true); // 是否显示iframe 返回按钮,三维平台用 const [ref, isFullscreen, handleFullScreen, handleExitFullScreen] = useFullScreen(false); // 退出 const exit = () => { if (isFullscreen) { handleExitFullScreen && handleExitFullScreen(); } else { handleFullScreen && handleFullScreen(); } }; // 切换方案视频 const onChangeScheme = (item, index) => { if (videoRef.current) { videoRef.current.onSlideToLoop(index); } }; const jumpProgressStart = () => { if (timer2.current) { clearInterval(timer2.current); timer2.current = null; } progressRef2.current = 0; setProgressValue2(0); timer2.current = setInterval(() => { if (progressRef2.current < 97.5) { progressRef2.current += 2.5; setProgressValue2(progressRef2.current); } else { setProgressValue2(99); timer2.current && clearInterval(timer2.current); timer2.current = null; } }, 100); }; const jumpProgressEnd = () => { setProgressValue2(100); timer2.current && clearInterval(timer2.current); timer2.current = null; }; const startTiming = (time = 2) => { if (timer3.current) { clearInterval(timer3.current); timer3.current = null; } timer3.current = setTimeout(() => { setJumpLoading(false); timer2.current && clearInterval(timer2.current); timer2.current = null; }, time * 1000); }; const handToProduct = (url, name) => { console.log('🚀 ~ url, name:', url, name, productConfig); if (!productConfig?.[name]) return message.warning('该账号没有权限,请联系管理员'); setJumpLoading(true); jumpProgressStart(); setLinkUrl(url); let time = 15; if (!url.includes('user/noscret')) { time = 4; } startTiming(time); }; const handError = err => { if (err) { message.error(err); } setLinkUrl(''); setJumpLoading(false); jumpProgressEnd(); }; const onMessageBack = data => { if (!data?.type) return; console.log('onMessageBack ~ data:', data); switch (data?.type) { // 页面加载完成 // 登录成功 case 'runAfterFirstMounted': case 'loginSuccess': jumpProgressEnd(); setTimeout(() => { setJumpLoading(false); }, 100); break; case 'loginError': message.warning('登录失败,请联系管理人员'); handError(); break; case '无法连接': message.warning('该站点无法连接,请联系管理人员'); setTimeout(() => { handError(); }, 100); break; case 'showBack': setShowBackBtn(true); break; case 'hideBack': setShowBackBtn(false); break; default: break; } }; const handToPage = url => { if (!url) return message.warning('该环境未配置,请联系管理员'); if (!url.includes('https')) return; setJumpLoading(true); jumpProgressStart(); setLinkUrl(url); startTiming(4); }; const renderCenter = useMemo(() => { const list = [...platformData]; return list.map((col, index) => { if (col.isCenter) { return ( <div className={styles.center_title} style={{ flex: col.flex }} type={col.title}> <div>{col.title}</div> </div> ); } return ( <div className={styles.center_col} style={{ flex: col.flex }} type={col.title}> <div className={styles.center_top}>{col.top}</div> <div className={styles.center_item}> {index === 0 || index === 3 ? <div className={styles.center_item_tip} /> : null} <img src={require(`@/assets/images/demonstration/${col.icon}`)} alt="" /> {col.title} · <span>{col.subTitle}</span> </div> </div> ); }); }, []); const onResize = () => { if (ref?.current) { const { clientWidth, clientHeight } = ref.current; if (!boxWidth || !boxHeight) return; const xScale = clientWidth / boxWidth; const yScale = clientHeight / boxHeight; const poor = clientHeight / clientWidth - boxHeight / boxWidth; let n = Math.min(xScale, yScale); let bHeight = boxHeight; if (poor > 0.05) { bHeight = boxHeight + 30; } // 高度为偶数 bHeight = parseInt(bHeight, 10); if (bHeight % 2 !== 0) { bHeight += 1; } n = Number(n.toFixed(4)); setBoxSize({ scale: n, boxHeight: bHeight, }); } }; const getProjectConfig = () => { const params = { ignoreSite: true, accountName: '项目案例临时账号管理', isAll: true, queryWheres: [ { field: '是否禁用', type: '不等于', value: '是', }, ], }; const oid = props.global.userInfo?.cloudStationOID || props.global.userInfo?.OID; if (!oid) return; params.queryWheres.push({ field: '账号', type: '等于', value: oid.toString(), }); appService.getAccountPageList(params).then(res => { let data = res?.data?.list || []; data = data.map(d => { const obj = { ID: d.id, }; if (Array.isArray(d.webRow)) { d.webRow.forEach(w => { obj[w.fieldName] = w.fieldValue; }); } return obj; }); const obj = {}; data.forEach(d => { if (!d['项目平台名称']) return; if (!d['开始时间']) return false; if (!d['结束时间'] && moment().isAfter(d['开始时间'])) { const arr = d['项目平台名称'].split(','); arr.forEach(a => { obj[a] = true; }); return; } if (moment().isBetween(d['开始时间'], d['结束时间'])) { const arr = d['项目平台名称'].split(','); arr.forEach(a => { obj[a] = true; }); } }); setProjectConfig(obj); }); }; const getProductConfig = () => { const params = { ignoreSite: true, accountName: '产品临时账号', isAll: true, queryWheres: [ { field: '是否禁用', type: '不等于', value: '是', }, ], }; const oid = props.global.userInfo?.cloudStationOID || props.global.userInfo?.OID; if (!oid) return; params.queryWheres.push({ field: '账号', type: '模糊查询', value: oid.toString(), }); appService.getAccountPageList(params).then(res => { const data = res?.data?.list || []; const list = []; data.forEach(d => { const obj = { ID: d.id, }; let type = false; if (Array.isArray(d.webRow)) { d.webRow.forEach(w => { if (w.fieldName === '账号' && w.fieldValue) { const arr = w.fieldValue.split(','); if (arr.includes(oid.toString())) { type = true; } } obj[w.fieldName] = w.fieldValue; }); } if (type) list.push(obj); return obj; }); const obj = {}; list.forEach(d => { if (!d['产品名称']) return; const arr = d['产品名称'].split(','); arr.forEach(a => { obj[a] = true; }); }); setProductConfig(obj); }); }; const getData = () => { setLoading(true); const req1 = appService.getAccountPageList({ ignoreSite: true, accountName: '项目案例配置表', isAll: true, sortFields: '顺序', direction: 'asc', queryWheres: [ { field: '演示案例', type: '等于', value: '是', }, ], }); const req2 = appService.getAccountPageList({ ignoreSite: true, accountName: '产品配置', isAll: true, sortFields: '顺序', direction: 'asc', queryWheres: [ { field: '是否显示', type: '等于', value: '是', }, ], }); const req3 = appService.getAccountPageList({ accountName: '首页配置台账', isAll: true, ignoreSite: true, }); Promise.all([req1, req2, req3]).then(result => { const dataStr1 = result[0]?.data?.jsonData || ''; const data1 = dataStr1 ? JSON.parse(dataStr1) : []; const dataStr2 = result[1]?.data?.jsonData || ''; const data2 = dataStr2 ? JSON.parse(dataStr2) : []; const dataStr3 = result[2]?.data?.jsonData || ''; const data3 = dataStr3 ? JSON.parse(dataStr3) : []; const newList = []; const list2 = []; data2.forEach(d => { if (d['产品类型'] === '新产品') { newList.push(d); } else if (d['产品地址']) { list2.push(d); } }); setProjectData(data1); setConfigData(data3); setProductData(list2); if (newList.length <= 5) { newList.push({ 产品名称: '敬请期待...', ID: 0, }); } setNewProductData(newList); setLoading(false); }); }; const onendLoading = () => { jumpProgressEnd(); }; const iframeItem = useMemo(() => { if (!linkUrl) return null; return ( <> <div className={classNames(!jumpLoading ? styles.scaleInCenter : styles.hide, 'animate__animated')}> <Iframe linkUrl={linkUrl} onMessageBack={onMessageBack} /> </div> </> ); }, [linkUrl, jumpLoading]); useEffect(() => { if (loading && !timer.current) { timer.current = setInterval(() => { if (progressRef.current < 95) { progressRef.current += 5; setProgressValue(progressRef.current); } else { setProgressValue(99); timer.current && clearInterval(timer.current); timer.current = null; } }, 50); } if (!loading) { setProgressValue(100); timer.current && clearInterval(timer.current); timer.current = null; setTimeout(() => { setShowContent(true); }, 0); // 延迟1s去掉入场动画,解决动画会使字体模糊 setTimeout(() => { setShowAnimation(false); }, 1000); } }, [loading]); useEffect(() => { const handleToggleIndustry = event => { props.history && props.history.push(`/?client=${props.global.client}`); props.updateCurrentIndex(0); defaultApp(); }; window.share.event.on('toggleIndustry', handleToggleIndustry); return () => { window.share.event.removeListener('toggleIndustry', handleToggleIndustry); }; }, [props]); useEffect(() => { window.share.event.on('loginError', handError); // 结束跳转loading window.share.event.on('onendLoading', onendLoading); return () => { window.share.event.removeListener('loginError', handError); window.share.event.removeListener('onendLoading', onendLoading); }; }, []); useEffect(() => { if (props.global?.userInfo) { getData(); } else { timer.current && clearInterval(timer.current); timer.current = null; } window.addEventListener('resize', debounce(onResize, 300)); onResize(); return () => { window.removeEventListener('resize', onResize); timer2.current && clearInterval(timer2.current); timer2.current = null; }; }, []); useEffect(() => { getProjectConfig(); getProductConfig(); }, [props.global]); useEffect(() => {}, []); return ( <div className={classNames(styles.demonstration)} ref={ref}> {/* {!linkUrl ? ( <div className={classNames(styles.iframeExit, 'animate__animated', 'animate__fadeIn')} onClick={() => props.logout && props.logout()} > <div className={styles.iframeBackLeft}> <img src={arrowLeftImg} alt="退出" /> </div> <div className={styles.iframeExitIcon}> <img src={backImg} alt="退出" /> 退出 </div> </div> ) : null} */} {jumpLoading ? ( <div className={styles.demonstrationLoad} key="jumpLoading"> <div style={{ width: '285px' }}> <LoadPage percent={progressValue2 / 100} text="页面加载中~" /> </div> </div> ) : null} {loading || progressValue !== 100 ? ( <div className={styles.loadingWrap} key="loading"> <div style={{ width: '285px' }}> <LoadPage percent={progressValue / 100} text="数据加载中~" /> </div> </div> ) : null} {showFullScreen && !linkUrl ? ( <div className={styles.CV_exit} onClick={exit}> <Button type="text" style={{ color: '#fff', fontSize: '24px' }}> {isFullscreen ? <FullscreenExitOutlined /> : <FullscreenOutlined />} </Button> </div> ) : null} <div className={styles.demonstrationWrap} style={{ width: boxWidth, height: boxSize.boxHeight, transform: `scale(${boxSize.scale}) translate(-50%,-50%)`, }} > <div className={styles.top}> <div className={styles.top_l}> 危机创<span>奇迹</span> · 极致造<span>辉煌</span> </div> <div className={styles.top_c}> <div className={styles.top_c_title}>熊猫智慧水务一体化解决方案</div> </div> <div className={styles.top_r}> <div className={styles.top_r_text}>- 引领中国智慧水务 -</div> </div> </div> {showContent ? ( <> <div className={classNames( styles.row, showAnimation ? 'animate__fadeInDown animate__animated duration-500ms' : '', )} > <div className={styles.row_l}> <LeftItem setSelectKey={setSelectKey} selectKey={selectKey} productData={productData} onChangeScheme={onChangeScheme} handToProduct={handToProduct} /> </div> <div className={styles.row_c}> <VideoItem ref={videoRef} selectKey={selectKey} setSelectKey={setSelectKey} showContent={showContent} /> </div> <div className={styles.row_r}> <RightItem listData={newProductData} productConfig={productConfig} handToProduct={handToProduct} /> </div> </div> <div className={classNames( styles.center_wrap, showAnimation ? 'animate__fadeIn animate__animated duration-500ms' : '', )} > <div className={styles.center_tip} /> <div className={styles.center}>{renderCenter}</div> </div> <div className={classNames( styles.bottom, showAnimation ? 'animate__fadeInUp animate__animated duration-500ms' : '', )} > <BottomItem listData={projectData} configData={configData} onLineUrl={onLineUrl} projectConfig={projectConfig} handToPage={handToPage} industries={props.global?.userInfo?.Industries || []} /> </div> </> ) : null} </div> {linkUrl && showBackBtn ? ( <div className={classNames(styles.iframeExit, 'animate__animated', 'animate__fadeIn')} onClick={() => setLinkUrl('')} > <div className={styles.iframeBackLeft}> <img src={arrowLeftImg} alt="返回" /> </div> <div className={styles.iframeExitIcon}> <img src={backImg} alt="返回" /> 返回 </div> </div> ) : null} {iframeItem} </div> ); }; const mapStateToProps = state => ({ global: state.getIn(['global', 'globalConfig']), instance: state.getIn(['global', 'instance']), }); const mapDispatchToProps = dispatch => ({ updateConfig(config) { dispatch(actionCreators.getConfig(config)); }, createContext(data) { dispatch(actionCreators.createContext(data)); }, updateCurrentIndex(index) { dispatch(actionCreators.updateCurrentIndex(index)); }, logout() { dispatch(actionCreators.logout()); }, }); export default connect( mapStateToProps, mapDispatchToProps, )(Demonstration);