Commit 40f8c0d3 authored by 周宏民's avatar 周宏民

fix: 演示功能入口 跳转等

parent 3830185b
......@@ -2,23 +2,25 @@
@-webkit-keyframes move {
0% {
-webkit-transform: translate(-90px,0%);
transform: translate(-90px,0%);
-webkit-transform: translate(-90px, 0%);
transform: translate(-90px, 0%);
}
100% {
-webkit-transform: translate(85px,0%);
transform: translate(85px,0%);
-webkit-transform: translate(85px, 0%);
transform: translate(85px, 0%);
}
}
@keyframes move {
0% {
-webkit-transform: translate(-90px,0%);
transform: translate(-90px,0%);
-webkit-transform: translate(-90px, 0%);
transform: translate(-90px, 0%);
}
100% {
-webkit-transform: translate(85px,0%);
transform: translate(85px,0%);
-webkit-transform: translate(85px, 0%);
transform: translate(85px, 0%);
}
}
......@@ -27,15 +29,46 @@
height: 100%;
position: relative;
overflow: hidden;
background: url('https://panda-water.cn/web4/assets/images/bootPage/背景.jpg')
no-repeat top center;
background: url('https://panda-water.cn/web4/assets/images/bootPage/背景.jpg') no-repeat top center;
background-size: cover;
.b_top_l {
width: 281px;
padding-left: 33px;
margin-top: 17px;
.b_top_l_btn {
width: 160px;
height: 32px;
background: rgba(110, 146, 188, 0.25);
border-radius: 16px;
text-align: center;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
font-weight: 400;
color: #FFFFFF;
img {
width: 16px;
height: 16px;
margin-right: 5px;
}
}
.b_top_l_btn:active {
opacity: 0.8;
}
}
.bootPageMain {
display: flex;
align-items: center;
flex-direction: column;
height: 100%;
width: 100%;
.bootPageHead {
height: 150px;
display: flex;
......@@ -44,18 +77,22 @@
color: #ffffff;
flex: none;
padding-top: 50px;
.bootPageTitle {
display: flex;
flex-direction: column;
margin-left: 20px;
.bootPageZh,
.bootPageEn {
font-weight: 500;
}
.bootPageZh {
font-size: 34px;
letter-spacing: 5px;
}
.bootPageEn {
font-size: 16px;
font-family: -webkit-body;
......@@ -63,6 +100,7 @@
}
}
}
.bootPageSection {
display: flex;
align-items: center;
......@@ -70,10 +108,12 @@
flex: 1;
height: calc(100% - 160px);
margin: 20px 0;
&::-webkit-scrollbar {
width: 0px;
height: 0px;
}
.bootPageUl {
display: flex;
width: 1280px;
......@@ -82,20 +122,24 @@
list-style: none;
transition: all .5s ease-out;
padding-top: 10px;
.bootPageLi {
position: relative;
width: 298px;
height: 268.8px;
margin: 10px;
&:hover {
.listMain {
transform: scale(1.1);
}
.bootProgress {
transform: scale(1.1);
bottom: -10px;
}
}
.bootPageList {
width: 100%;
height: 100%;
......@@ -108,31 +152,37 @@
font-size: 24px;
cursor: pointer;
position: relative;
span {
margin-top: 20px;
font-weight: 500;
color: #fff;
}
.listMain {
transition: all 0.2s ease-out;
display: flex;
align-items: center;
flex-direction: column;
img {
width: 298px;
height: 269px;
border-radius: 20px;
vertical-align: middle;
}
span {
font-weight: 500;
color: #fff;
}
.bootPageName {
position: absolute;
bottom: 31px;
font-weight: 500;
}
.bootPageNameEng {
font-size: 14px;
position: absolute;
......@@ -141,9 +191,11 @@
}
}
}
&.bootPageUl_5 {
width: 960px;
}
&.bootPageUl_9,
&.bootPageUl_10 {
width: 1600px;
......@@ -167,6 +219,7 @@
padding: 0 20px;
display: flex;
justify-content: end;
:global {
.cloud-using-anaylysis-btn {
cursor: pointer;
......@@ -174,11 +227,13 @@
display: flex;
flex-direction: column;
justify-content: center;
& > img {
&>img {
width: 50px;
margin: 0 25px;
}
& > span {
&>span {
color: #fff;
font-size: 14px;
width: 100%;
......@@ -189,6 +244,7 @@
}
:global {
.@{ant-prefix}-spin-nested-loading,
.@{ant-prefix}-spin-container {
height: 100%;
......@@ -206,7 +262,7 @@
bottom: 0px;
}
.bootProgress .inner{
.bootProgress .inner {
transition: all .2s ease-out;
position: absolute;
height: 100%;
......@@ -237,6 +293,7 @@
.bootPageZh {
font-size: 26px;
}
.bootPageEn {
font-size: 12px;
}
......@@ -250,9 +307,10 @@
.bootPageZh {
font-size: 30px;
}
.bootPageEn {
font-size: 14px;
}
}
}
}
}
\ No newline at end of file
......@@ -10,7 +10,7 @@ import zhCN from 'antd/es/locale/zh_CN';
import DataCarousel from '../DataCarousel';
import styles from './index.less';
const BottomItem = props => {
const { title = '', listData = [], configData = [] } = props;
const { listData = [], configData = [], onLineUrl, handToPage, handlePage } = props;
const [list, setList] = useState([]);
const [infoData, setInfoData] = useState({});
const renderNum = (num, type) => {
......@@ -26,19 +26,21 @@ const BottomItem = props => {
const renderCol = (row, rindex) => {
if (!Array.isArray(row)) return null;
return (
<div className={styles.list_item_col} key={rindex}>
<div className={styles.list_item_col}>
{row.map((col, cIndex) => (
<div key={`${rindex}-${cIndex}`} className={styles.list_item}>
<div
key={`${rindex}-${cIndex}`}
type={col['项目环境'] ? 'jump' : 'none'}
onClick={() => handToPage(col['项目环境'])}
className={styles.list_item}
>
<div className={styles.list_item_img_wrap}>
<div className={classNames(styles.list_item_img, 'list_item_img')}>
<ConfigProvider locale={zhCN}>
<Image
src={`https://panda-water.cn/CityInterface/rest/services/filedownload.svc/download/${
col['项目图片']
}`}
style={{ height: '100px', width: '100%', overflow: 'hidden' }}
/>
</ConfigProvider>
<Image
src={`${onLineUrl}CityInterface/rest/services/filedownload.svc/download/${col['项目图片']}`}
style={{ height: '100px', width: '100%', overflow: 'hidden' }}
preview={false}
/>
</div>
{col['重要程度'] === '样板' ? <div className={styles.list_item_img_tip} /> : null}
</div>
......@@ -77,10 +79,12 @@ const BottomItem = props => {
let str = i['所属城市'];
if (i['所属城市']) {
const temp = i['所属城市'].split('/');
// eslint-disable-next-line prefer-destructuring
str = temp[1];
if (str[str.length - 1] === '市') {
str = str.slice(0, str.length - 1);
} else {
// eslint-disable-next-line prefer-destructuring
str = temp[0];
}
}
......@@ -152,11 +156,13 @@ const BottomItem = props => {
config={{
direction: 'horizontal',
width: 212,
loop: false,
loop: true,
}}
/>
</div>
<div className={styles.right}>查看全部</div>
<div className={styles.right} onClick={e => handlePage(e, '项目案例')}>
查看全部
</div>
</div>
);
};
......
......@@ -130,6 +130,14 @@
padding: 12px 0 0 13px;
}
.list_item[type='jump'] {
cursor: pointer;
}
.list_item[type='jump']:active {
opacity: 0.8;
}
.list_item {
width: 204px;
height: 130px;
......@@ -169,13 +177,14 @@
width: 38px;
height: 20px;
text-align: center;
line-height: 20px;
line-height: 18px;
margin-right: 5px;
background: url('@{imgSrc}/供水.png') no-repeat center/100% 100%;
}
.list_item_info_tip[type='农饮水'] {
background: url('@{imgSrc}/农水.png') no-repeat center/100% 100%;
font-size: 10px;
}
.list_item_info_tip[type='水利'] {
......
......@@ -3,25 +3,21 @@
* @Author: hongmye
* @Date: 2023-12-26 18:34:42
*/
import { Button } from 'antd';
import React, { useMemo, useEffect, useState, memo } from 'react';
import LoginAction from '@/pages/user/login/login';
import { schemeData } from '../configData';
import styles from './index.less';
let timer;
const LeftItem = props => {
const { title = '', setSelectKey, selectKey } = props;
const [loginAction, setAction] = useState(() => new LoginAction(props));
const onSelect = row => {};
const { selectKey, onChangeScheme, handlePage } = props;
const onMouseEnter = (item, index) => {
if (timer) {
timer && clearTimeout(timer);
}
timer = setTimeout(() => {
props.onChangeScheme && props.onChangeScheme(item, index);
onChangeScheme && onChangeScheme(item, index);
}, 500);
};
const onMouseLeave = (item, index) => {
......@@ -40,7 +36,8 @@ const LeftItem = props => {
className={styles.l_list_item}
key={item.title}
type={item.title}
onClick={() => onSelect(item)}
selectType={selectKey === item.title ? 'select' : ''}
onClick={event => handlePage(event, item.type, item)}
onMouseEnter={() => onMouseEnter(item, index)}
onMouseLeave={() => onMouseLeave(item, index)}
>
......@@ -52,4 +49,5 @@ const LeftItem = props => {
</div>
);
};
export default memo(LeftItem);
......@@ -4,31 +4,46 @@
* @Date: 2023-12-26 18:34:42
*/
import React, { useMemo, useEffect, useState, memo } from 'react';
import { Tooltip } from 'antd';
import classNames from 'classnames';
import DataCarousel from '../DataCarousel';
import styles from './index.less';
const RightItem = props => {
const { listData } = props;
const { listData, handToPage } = props;
const renderRow = (row, index) => {
const rIndex = `r_${index % 7}`;
return (
<div className={styles.r_list_item} key={row['产品名称']} rIndex={rIndex}>
<div
className={styles.r_list_item}
key={row['产品名称']}
rIndex={rIndex}
type={row['产品地址'] ? 'jump' : 'none'}
onClick={() => handToPage(row['产品地址'])}
>
<div className={styles.r_list_item_title}>{row['产品名称']}</div>
<div className={styles.r_list_item_tip} />
</div>
);
};
const renderList = useMemo(
() => <div className={styles.r_list}>{listData.map((row, index) => renderRow(row, index))}</div>,
[listData],
);
useEffect(() => {}, []);
return (
<div className={styles.right_item}>
<div className={classNames(styles.right_item, 'right_item')}>
<div className={styles.r_title_wrap}>
<div className={styles.r_title_sub}>熊猫智慧水务</div>
<div className={styles.r_title}>新产品动态:</div>
</div>
{renderList}
<div className={styles.r_list}>
<DataCarousel
gap={1}
autoplay={5000}
itemHeight={50}
list={listData}
renderItem={renderRow}
config={{
loop: true,
}}
/>
</div>
</div>
);
};
......
......@@ -32,15 +32,19 @@
}
.r_list {
.r_list_item:hover {
height: 350px;
overflow: hidden;
.r_list_item[type='jump']:hover {
left: -8px;
filter: brightness(160%)
}
.r_list_item:hover .r_list_item_tip {
.r_list_item[type='jump']:hover .r_list_item_tip {
opacity: 1;
}
.r_list_item:not(:last-child) {
margin-bottom: 8px;
}
......@@ -53,12 +57,15 @@
font-weight: bold;
line-height: 40px;
position: relative;
cursor: pointer;
left: 0;
transition: all 0.3s;
}
.r_list_item:active {
.r_list_item[type='jump'] {
cursor: pointer;
}
.r_list_item[type='jump']:active {
opacity: 0.8;
}
......@@ -120,4 +127,16 @@
}
:global {
.right_item {
.swiper-wrapper {
.swiper-slide {
width: 100%;
height: 50px;
}
}
}
}
\ No newline at end of file
......@@ -20,7 +20,7 @@ import styles from './index.less';
const autoplay = 15000;
SwiperCore.use([Autoplay, Pagination, Navigation, Mousewheel, EffectCoverflow]);
const VideoItem = (props, ref) => {
const { selectKey = '' } = props;
const { selectKey = '', setSelectKey } = props;
const swiperRef = useRef(null);
const onSlideToLoop = index => {
if (swiperRef.current) {
......@@ -55,6 +55,10 @@ const VideoItem = (props, ref) => {
}
};
const onSlideChange = e => {
const title = listData[e.realIndex]?.title;
if (title && title !== selectKey) {
setSelectKey(title);
}
if (e.$el[0]) {
const videoDom = e.$el[0].querySelector('video');
videoDom.play && videoDom.play();
......
......@@ -120,7 +120,7 @@
}
.swiper-container {
width: 1100px;
width: 100%;
height: 100%;
}
}
......
......@@ -14,24 +14,28 @@ const schemeData = [
background: '',
url: '',
video: gongshuiVideo,
type: '供水',
},
{
title: '水利产品',
background: '',
url: '',
video: shuiliVideo,
type: '水利',
},
{
title: '排水产品',
background: '',
url: '',
video: paishuiVideo,
type: '排水',
},
{
title: '节水产品',
background: '',
url: '',
video: jieshuiVideo,
type: '能源',
},
];
const productData = [
......
......@@ -7,11 +7,14 @@
*/
import { FullscreenExitOutlined, FullscreenOutlined, RightOutlined } from '@ant-design/icons';
import exitImg from '@/assets/demonstration/退出.png';
import enterImg from '@/assets/demonstration/进入.png';
import { Button } from 'antd';
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 LoginAction from '@/pages/user/login/login';
import classNames from 'classnames';
import useFullScreen from './components/useFullScreen';
import styles from './index.less';
import LeftItem from './components/Left';
......@@ -19,6 +22,7 @@ import VideoItem from './components/VideoItem';
import RightItem from './components/Right';
import BottomItem from './components/Bottom';
import { platformData } from './components/configData';
const boxWidth = 1920;
const boxHeight = 911;
const projectType = ['供水', '排水', '农饮水', '水利'];
......@@ -26,15 +30,17 @@ const Demonstration = props => {
const onLineUrl = window.globalConfig?.mainserver || 'https://panda-water.cn/';
const showFullScreen = true;
const videoRef = useRef(null);
const [loginAction, setAction] = useState(() => new LoginAction(props));
const [loading, setLoading] = useState(true);
const [selectKey, setSelectKey] = useState('供水产品');
const [boxSize, setBoxSize] = useState({
scale: 1,
boxHeight: 911,
});
const [projectData, setProjectData] = useState([]);
const [configData, setConfigData] = useState([]);
const [productData, setProductData] = useState([]);
const [pattern, setPattern] = useState(true);
const [ref, isFullscreen, handleFullScreen, handleExitFullScreen] = useFullScreen(false);
// 退出
const exit = () => {
......@@ -51,26 +57,57 @@ const Demonstration = props => {
videoRef.current.onSlideToLoop(index);
}
};
const renderCenter = useMemo(
() =>
platformData.map(col => {
if (col.isCenter) {
return (
<div className={styles.center_title} style={{ flex: col.flex }} type={col.title}>
<div>{col.title}</div>
</div>
);
}
// 方案跳转
const handlePage = (event, type, row) => {
const config = props.global;
const industries = config.userInfo?.Industries || [];
if (!industries.includes(type)) {
message.error(`该用户未配置${row.title}`);
return;
}
config.uiwidgets = [];
config.widgets = [];
config.allWidgets = [];
props.instance && props.instance.updateConfig(config);
loginAction && loginAction.getUserInfoAndConfig('', true, type);
};
const handToPage = (url, type) => {
if (!url) return;
window.open(url, '_blank');
};
const renderCenter = useMemo(() => {
let list = [...platformData];
list = list.map(l => {
const item = configData.find(c => c['名称'] === l.title);
l.url = item?.['数值'];
return l;
});
return list.map(col => {
if (col.isCenter) {
return (
<div className={styles.center_col} style={{ flex: col.flex }} type={col.title}>
<img src={require(`@/assets/demonstration/${col.icon}`)} alt="" />
{col.title}
<RightOutlined />
<div className={styles.center_title} style={{ flex: col.flex }} type={col.title}>
<div>{col.title}</div>
</div>
);
}),
[],
);
}
return (
<div
onClick={() => handToPage(col.url)}
className={styles.center_col}
style={{ flex: col.flex }}
type={col.title}
isJump={col.url ? 'yes' : 'no'}
>
<img src={require(`@/assets/demonstration/${col.icon}`)} alt="" />
{col.title}
<RightOutlined />
</div>
);
});
}, [configData]);
const onResize = () => {
if (ref?.current) {
const { clientWidth, clientHeight } = ref.current;
......@@ -91,17 +128,28 @@ const Demonstration = props => {
}
};
const getData = () => {
setLoading(true);
const req1 = appService.getAccountPageList({
ignoreSite: true,
accountName: '项目案例配置表',
isAll: true,
sortFields: '重要程度',
direction: 'desc',
queryWheres: [
{
field: '演示案例',
type: '等于',
value: '是',
},
],
});
const req2 = appService.getAccountPageList({
accountName: '首页配置台账',
isAll: true,
ignoreSite: true,
});
const req3 = appService.getAccountPageList({
ignoreSite: true,
accountName: '新产品配置',
isAll: true,
sortFields: '排序',
......@@ -122,10 +170,10 @@ const Demonstration = props => {
const data2 = dataStr2 ? JSON.parse(dataStr2) : [];
const dataStr3 = result[2]?.data?.jsonData || '';
const data3 = dataStr3 ? JSON.parse(dataStr3) : [];
console.log('🚀 ~ data3:', data1, data2, data3);
setProjectData(data1);
setConfigData(data2);
setProductData(data3);
setLoading(false);
});
};
useEffect(() => {
......@@ -137,7 +185,7 @@ const Demonstration = props => {
};
}, []);
return (
<div className={styles.demonstration} ref={ref}>
<div className={classNames(styles.demonstration)} ref={ref}>
{showFullScreen ? (
<div className={styles.CV_exit} onClick={exit}>
<Button type="text" style={{ color: '#fff', fontSize: '24px' }}>
......@@ -155,15 +203,9 @@ const Demonstration = props => {
>
<div className={styles.top}>
<div className={styles.top_l}>
{pattern ? (
<div className={styles.top_l_btn}>
<img src={exitImg} alt="" /> 退出演示模式 <RightOutlined />
</div>
) : (
<div className={styles.top_l_btn}>
<img src={enterImg} alt="" /> 进入演示模式 <RightOutlined />
</div>
)}
<div className={styles.top_l_btn} onClick={() => props.setPattern && props.setPattern(false)}>
<img src={exitImg} alt="" /> 退出演示模式 <RightOutlined />
</div>
</div>
<div className={styles.top_c}>
<div className={styles.top_c_title}>熊猫智慧水务一体化解决方案</div>
......@@ -172,27 +214,65 @@ const Demonstration = props => {
<div className={styles.top_r_text}>- 引领中国智慧水务 -</div>
</div>
</div>
<div className={styles.row}>
<div className={styles.row_l}>
<LeftItem setSelectKey={setSelectKey} selectKey={selectKey} onChangeScheme={onChangeScheme} />
</div>
<div className={styles.row_c}>
<VideoItem ref={videoRef} selectKey={selectKey} setSelectKey={setSelectKey} onLineUrl={onLineUrl} />
{loading ? (
<div className={styles.loadingWrap}>
<div className={styles.loading} />
</div>
<div className={styles.row_r}>
<RightItem listData={productData} />
</div>
</div>
<div className={styles.center_wrap}>
<div className={styles.center_tip} />
<div className={styles.center}>{renderCenter}</div>
</div>
<div className={styles.bottom}>
<BottomItem listData={projectData} configData={configData} />
</div>
) : null}
{!loading ? (
<>
<div className={classNames(styles.row, 'animate__fadeInDown', 'animate__animated', 'duration-500ms')}>
<div className={styles.row_l}>
<LeftItem
setSelectKey={setSelectKey}
selectKey={selectKey}
onChangeScheme={onChangeScheme}
handlePage={handlePage}
/>
</div>
<div className={styles.row_c}>
<VideoItem ref={videoRef} selectKey={selectKey} setSelectKey={setSelectKey} />
</div>
<div className={styles.row_r}>
<RightItem listData={productData} handToPage={handToPage} />
</div>
</div>
<div className={classNames(styles.center_wrap, 'animate__fadeIn', 'animate__animated', 'duration-500ms')}>
<div className={styles.center_tip} />
<div className={styles.center}>{renderCenter}</div>
</div>
<div className={classNames(styles.bottom, 'animate__fadeInUp', 'animate__animated', 'duration-500ms')}>
<BottomItem
listData={projectData}
configData={configData}
onLineUrl={onLineUrl}
handToPage={handToPage}
handlePage={handlePage}
/>
</div>
</>
) : null}
</div>
</div>
);
};
export default Demonstration;
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));
},
});
export default connect(
mapStateToProps,
mapDispatchToProps,
)(Demonstration);
......@@ -48,6 +48,10 @@
width: 281px;
padding-left: 33px;
.top_l_btn:active {
opacity: 0.8;
}
.top_l_btn {
width: 160px;
height: 32px;
......@@ -175,7 +179,6 @@
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
position: relative;
top: 0;
transition: all 0.3s;
......@@ -187,12 +190,17 @@
}
}
.center_col:hover {
.center_col[isJump='yes'] {
cursor: pointer;
}
.center_col[isJump='yes']:hover {
top: -8px;
filter: brightness(130%)
}
.center_col:active {
.center_col[isJump='yes']:active {
opacity: 0.8;
}
......@@ -226,4 +234,58 @@
height: 290px;
overflow: hidden;
}
}
.loadingWrap {
position: absolute;
left: 50%;
top: 40%;
transform: translate(-50%, -20px);
}
.loading {
display: block;
position: relative;
width: 6px;
height: 10px;
animation: rectangle infinite 1s ease-in-out -0.2s;
background-color: #f6ff00;
}
.loading:before,
.loading:after {
position: absolute;
width: 6px;
height: 10px;
content: "";
background-color: #f6ff00;
}
.loading:before {
left: -14px;
animation: rectangle infinite 1s ease-in-out -0.4s;
}
.loading:after {
right: -14px;
animation: rectangle infinite 1s ease-in-out;
}
@keyframes rectangle {
0%,
80%,
100% {
height: 20px;
box-shadow: 0 0 #f6ff00;
}
40% {
height: 30px;
box-shadow: 0 -20px #f6ff00;
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment