Commit aed7975f authored by 周宏民's avatar 周宏民

feat: 演示功能引导页

parent 7cc86af7
Pipeline #85139 waiting for manual action with stages
......@@ -45,6 +45,8 @@ export const API = {
IS_OPEN_YANSHI: '/PandaCore/GCK/Demonstrate/IsOpenYanshi', // 获取是否开启演示模式服务
GET_WEB_CONFIG: '/PandaOMS/OMS/GetIntegratedLoginbyName',
GET_WEB_TICKET: '/PandaOMS/OMS/GetTicketByToken',
GET_ACCOUNT_PAGE_LIST: '/PandaWorkFlow/WorkFlow/AccountManage/GetAccountPageList',
};
const services = {
......@@ -232,6 +234,11 @@ const services = {
method: constants.REQUEST_METHOD_GET,
type: constants.REQUEST_HTTP,
},
getAccountPageList: {
url: API.GET_ACCOUNT_PAGE_LIST,
method: constants.REQUEST_METHOD_POST,
type: constants.REQUEST_METHOD_POST,
},
};
export const searchAutoCity = keywords => {
......
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
This diff was suppressed by a .gitattributes entry.
/*
* @Title:
* @Author: hongmye
* @Date: 2023-12-26 18:34:42
*/
import { Image, Tooltip, message } from 'antd';
import React, { useMemo, useEffect, useState } from 'react';
import classNames from 'classnames';
import DataCarousel from '../DataCarousel';
import styles from './index.less';
const BottomItem = props => {
const { listData = [], configData = [], onLineUrl, handToPage, handlePage, industries = [] } = props;
const isJump = industries.includes('项目案例');
const [list, setList] = useState([]);
const [infoData, setInfoData] = useState({});
const renderNum = (num, type) => {
const numStr = num ? num.toString() : '0';
const arr = numStr.split('');
return arr.map(a => (
<div className={styles.l_item_num_item} type={type}>
{a}
</div>
));
};
const toPage = url => {
if (!isJump) return message.warning('该用户没有权限!');
handToPage(url);
};
const toMore = (e, url) => {
if (!isJump) return message.warning('该用户没有权限!');
handlePage(e, '项目案例');
};
const renderCol = (row, rindex) => {
if (!Array.isArray(row)) return null;
return (
<div className={styles.list_item_col}>
{row.map((col, cIndex) => (
<Tooltip title={col['项目环境'] && isJump ? '点击体验' : ''} color="#1685FF">
<div
key={`${rindex}-${cIndex}`}
type={col['项目环境'] && isJump ? 'jump' : 'none'}
onClick={() => toPage(col['项目环境'])}
alt="点击体验"
className={styles.list_item}
>
<div className={styles.list_item_img_wrap}>
<div className={classNames(styles.list_item_img, 'list_item_img')}>
<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>
<div className={styles.list_item_info_wrap}>
<div className={styles.list_item_info_tip} type={col['所属行业']}>
{col['所属行业'] === '能源' ? '节水' : col['所属行业']}
</div>
<div className={styles.list_item_info_name}>
<Tooltip title={col['客户名称']} color="#1685FF">
{col['客户名称']}
</Tooltip>
</div>
<div className={styles.list_item_info_address}>{col['城市']}</div>
</div>
</div>
</Tooltip>
))}
</div>
);
};
const spliceArr = (arr, num) => {
const reArr = [];
arr.map(item => {
if (!reArr[reArr.length - 1] || reArr[reArr.length - 1].length === num) {
// 新行添加
reArr.push([]);
}
if (reArr[reArr.length - 1].length !== num) {
// 长度不够则直接添加
reArr[reArr.length - 1].push(item);
}
return null;
});
return reArr;
};
useEffect(() => {
const arr = [];
listData.forEach(i => {
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];
}
}
if (str[str.length - 1] === '市') {
str = str.slice(0, str.length - 1);
}
i['城市'] = str;
arr.push(i);
});
setList(spliceArr(arr, 2));
}, [listData]);
useEffect(() => {
const obj = {
项目数量: '',
服务客户: '',
覆盖省份: '',
};
configData.forEach(c => {
if (obj[c['名称']] === '') {
obj[c['名称']] = c['数值'];
}
});
setInfoData(obj);
}, [configData]);
return (
<div className={classNames(styles.bottom_item, 'demo_bottom_item')}>
<div className={styles.left}>
<div className={styles.l_title_wrap}>
<div className={styles.l_title_sub}>熊猫智慧水务</div>
<div className={styles.l_title}>项目落地保障:</div>
</div>
<div className={styles.l_list}>
<div className={styles.l_item}>
<div className={styles.l_item_title} type="项目数量">
项目数量:
</div>
<div className={styles.l_item_num_list}>{renderNum(infoData['项目数量'], '项目数量')}</div>
<div className={styles.l_item_num_unit}></div>
</div>
<div className={styles.l_item}>
<div className={styles.l_item_title} type="服务客户">
服务客户:
</div>
<div className={styles.l_item_num_list}>{renderNum(infoData['服务客户'], '服务客户')}</div>
<div className={styles.l_item_num_unit} type="add">
+
</div>
</div>
<div className={styles.l_item}>
<div className={styles.l_item_title} type="覆盖省份">
覆盖省份:
</div>
<div className={styles.l_item_num_list}>{renderNum(infoData['覆盖省份'], '覆盖省份')}</div>
<div className={styles.l_item_num_unit} type="add">
+
</div>
</div>
</div>
</div>
<div className={styles.center}>
<DataCarousel
gap={1}
autoplay={5000}
itemHeight={270}
list={list}
renderItem={renderCol}
config={{
direction: 'horizontal',
width: 1520,
loop: false,
slidesPerView: 7,
}}
/>
</div>
<div className={styles.right} onClick={e => toMore(e)}>
查看全部
</div>
</div>
);
};
export default BottomItem;
@imgSrc: '@/assets/images/demonstration';
.bottom_item {
display: flex;
width: 100%;
height: 100%;
overflow: hidden;
padding: 0 28px 10px;
background: url('@{imgSrc}/bottom_bg.png') no-repeat left top;
background-size: calc(100% - 62px) 42px;
.left {
flex: none;
width: 288px;
height: 100%;
display: flex;
flex-direction: column;
overflow: hidden;
background: url('@{imgSrc}/项目落地保障.png') no-repeat center center;
background-size: 100% 100%;
padding: 25px 15px 20px 25px;
.l_title_wrap {
flex: none;
width: 100%;
.l_title_sub {
background: url('@{imgSrc}/tip.png') no-repeat left center;
background-size: 35px 36px;
padding-left: 35px;
font-size: 16px;
height: 36px;
line-height: 36px;
}
.l_title {
font-size: 22px;
font-family: Microsoft YaHei;
font-weight: bold;
color: #FBD84D;
line-height: 32px;
background: linear-gradient(0deg, #FFD270 0%, #FFFFFF 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
}
.l_list {
height: 100%;
padding: 10px 0;
display: flex;
flex-direction: column;
justify-content: space-around;
.l_item {
display: flex;
align-items: center;
}
.l_item_title {
padding-left: 20px;
}
.l_item_num_list {
display: flex;
}
.l_item_num_item {
width: 32px;
height: 36px;
line-height: 36px;
text-align: center;
margin-right: 5px;
font-size: 24px;
font-weight: bold;
}
.l_item_num_unit {
font-size: 14px;
font-weight: 400;
align-self: flex-end;
}
.l_item_num_unit[type='add'] {
font-size: 24px;
font-weight: bold;
align-self: center;
}
.l_item_title[type='项目数量'] {
background: url('@{imgSrc}/项目数量.png') no-repeat left center;
background-size: 14px 14px;
}
.l_item_num_item[type='项目数量'] {
background: url('@{imgSrc}/项目数量num.png') no-repeat center/100% 100%;
}
.l_item_title[type='服务客户'] {
background: url('@{imgSrc}/服务客户.png') no-repeat left center;
background-size: 14px 14px;
}
.l_item_num_item[type='服务客户'] {
background: url('@{imgSrc}/服务客户num.png') no-repeat center/100% 100%;
}
.l_item_title[type='覆盖省份'] {
background: url('@{imgSrc}/覆盖省份.png') no-repeat left center;
background-size: 14px 14px;
}
.l_item_num_item[type='覆盖省份'] {
background: url('@{imgSrc}/覆盖省份num.png') no-repeat center/100% 100%;
}
}
}
.center {
flex: 1;
height: 100%;
overflow: hidden;
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;
border: 1px solid rgba(71, 88, 114, 0.8);
border-radius: 10px;
overflow: hidden;
margin-right: 8px;
margin-bottom: 8px;
.list_item_img_wrap {
width: 100%;
height: 100px;
overflow: hidden;
position: relative;
.list_item_img_tip {
position: absolute;
right: 0;
top: 0;
width: 57px;
height: 19px;
background: url('@{imgSrc}/案例.png') no-repeat center/100% 100%;
}
}
.list_item_info_wrap {
display: flex;
width: 100%;
overflow: hidden;
align-items: center;
padding: 3px 8px 0;
font-size: 12px;
font-weight: 400;
.list_item_info_tip {
flex: none;
width: 38px;
height: 20px;
text-align: center;
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%;
}
.list_item_info_tip[type='能源'] {
background: url('@{imgSrc}/节水.png') no-repeat center/100% 100%;
}
.list_item_info_tip[type='排水'] {
background: url('@{imgSrc}/排水.png') no-repeat center/100% 100%;
}
.list_item_info_name {
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.list_item_info_address {
flex: none;
font-size: 12px;
font-weight: 400;
color: #ACCDF0;
line-height: 1;
padding-left: 4px;
border-left: 1px solid rgba(216, 234, 253, 0.4);
}
}
}
.right {
flex: none;
height: 100%;
overflow: hidden;
width: 44px;
height: 100%;
background: url('@{imgSrc}/查看全部.png') no-repeat center/100% 100%;
writing-mode: vertical-rl;
text-align: center;
display: flex;
align-items: center;
justify-content: center;
letter-spacing: 2px;
cursor: pointer;
}
}
:global {
.demo_bottom_item {
.swiper-wrapper {
display: flex;
.swiper-slide {
width: 212px;
}
}
.list_item_img {
.panda-console-base-image {
width: 100%;
}
img {
width: 100%;
height: 100%;
}
}
}
}
\ No newline at end of file
/*
* @Title:数据列表轮播组件
* @Author: hongmye
* @Date: 2023-02-08 16:03:42
*/
import PandaEmpty from '@wisdom-components/empty';
import classNames from 'classnames';
import React, { useEffect, useRef, useState } from 'react';
import 'swiper/components/navigation/navigation.min.css';
import 'swiper/components/pagination/pagination.min.css';
import SwiperCore, { Autoplay, Mousewheel, Navigation, Pagination } from 'swiper/core';
import { Swiper, SwiperSlide } from 'swiper/react';
import 'swiper/swiper.min.css';
import styles from './index.less';
SwiperCore.use([Autoplay, Pagination, Navigation, Mousewheel]);
const DataCarousel = ({ list, itemHeight, renderItem, config, autoplay, onSwiper, showEmpty = true }) => {
const autoplayConfig = {
delay: autoplay,
disableOnInteraction: false,
};
const contentRef = useRef(null);
const swiperRef = useRef(null);
const [listData, setListData] = useState([]);
useEffect(() => {
setListData(list);
}, [list]);
return (
<div
className={classNames(styles.dataCarousel, 'dataCarousel')}
style={{ width: '100%', height: '100%' }}
ref={contentRef}
>
<div className={classNames(styles.dataCarouselSwiper)} style={{ width: '100%', height: '100%' }}>
{listData && listData.length ? (
<Swiper
slidesPerView="auto"
autoplay={autoplay * 1 && listData.length > 1 ? autoplayConfig : false}
loop
height={itemHeight}
direction="vertical"
onSlideChange={e => {}}
mousewheel
onSwiper={swiper => {
swiperRef.current = swiper;
onSwiper && onSwiper(swiper);
// 鼠标悬浮暂停效果
swiper.$el[0].addEventListener('mouseover', () => swiper.autoplay.stop());
// 鼠标移开后继续自动滚屏效果
swiper.$el[0].addEventListener('mouseleave', () => {
listData.length > 1 && autoplay * 1 ? swiper.autoplay.start() : '';
});
}}
{...config}
>
{listData.map((item, index) => (
<SwiperSlide key={index} virtualIndex={index} onClick={() => {}}>
{renderItem(item, index + 1)}
</SwiperSlide>
))}
</Swiper>
) : showEmpty ? (
<div style={{ paddingTop: 10 }}>
<PandaEmpty />
</div>
) : null}
</div>
</div>
);
};
export default DataCarousel;
@root-entry-name: 'default';
@import '~antd/es/style/themes/index.less';
.dataCarousel {
width: 100%;
height: 100%;
overflow-y: auto;
.dataCarouselSwiper {
overflow-y: auto;
}
}
.dataCarousel {
:global {
.swiper-container {
width: 100%;
height: 100%;
}
}
}
/*
* @Title:
* @Author: hongmye
* @Date: 2023-12-26 18:34:42
*/
import React, { useMemo, useEffect, useState, memo } from 'react';
import { Tooltip } from 'antd';
import { schemeData } from '../configData';
import styles from './index.less';
let timer;
const LeftItem = props => {
const { selectKey, onChangeScheme, handlePage, industries } = props;
const onMouseEnter = (item, index) => {
if (timer) {
timer && clearTimeout(timer);
}
timer = setTimeout(() => {
onChangeScheme && onChangeScheme(item, index);
}, 500);
};
const onMouseLeave = (item, index) => {
timer && clearTimeout(timer);
};
useEffect(() => {}, []);
return (
<div className={styles.left_item}>
<div className={styles.l_title_wrap}>
<div className={styles.l_title_sub}>熊猫智慧水务</div>
<div className={styles.l_title}>全行业软硬件系统解决方案:</div>
</div>
<div className={styles.l_list}>
{schemeData.map((item, index) => (
<Tooltip title={industries.includes(item.type) ? '点击体验' : ''} color="#1685FF">
<div
className={styles.l_list_item}
key={item.title}
type={item.title}
selectType={selectKey === item.title ? 'select' : ''}
onClick={event => handlePage(event, item.type, item)}
onMouseEnter={() => onMouseEnter(item, index)}
onMouseLeave={() => onMouseLeave(item, index)}
>
<div className={styles.l_list_item_title}>- {item.title} -</div>
<div className={styles.l_list_item_tip} />
</div>
</Tooltip>
))}
</div>
</div>
);
};
export default memo(LeftItem);
@imgSrc: '@/assets/images/demonstration';
.left_item {
.l_title_wrap {
width: 100%;
height: 123px;
background: url('@{imgSrc}/全行业软硬件系统解决方案.png') no-repeat center center;
background-size: 100% 100%;
padding: 30px 0 0 25px;
.l_title_sub {
background: url('@{imgSrc}/tip.png') no-repeat left center;
background-size: 35px 36px;
padding-left: 35px;
font-size: 16px;
height: 36px;
line-height: 36px;
}
.l_title {
font-size: 22px;
font-family: Microsoft YaHei;
font-weight: bold;
color: #FFFFFF;
padding-left: 5px;
line-height: 32px;
letter-spacing: 1px;
// text-shadow: 0px 8px 8px rgba(8, 34, 78, 0.75);
background: linear-gradient(0deg, #92D2FF 0%, #FFFFFF 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
}
.l_list {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
}
.l_list_item:hover {
opacity: 1;
top: -8px;
}
.l_list_item:hover .l_list_item_tip {
opacity: 1;
}
.l_list_item[selectType='select'] {
opacity: 1;
top: -8px;
.l_list_item_tip {
opacity: 1;
}
}
.l_list_item {
width: 178px;
height: 162px;
opacity: 0.7;
top: 0;
position: relative;
text-align: center;
margin-bottom: 15px;
cursor: pointer;
transition: all 0.5s;
.l_list_item_title {
padding-top: 115px;
font-size: 18px;
}
}
.l_list_item_tip {
width: 71px;
height: 37px;
background: url('@{imgSrc}/选中产品.png') no-repeat center center;
background-size: 100% 100%;
position: absolute;
transition: all 0.3s;
bottom: -12px;
left: calc(50% - 35.5px);
opacity: 0;
}
.l_list_item[type='供水产品'] {
background: url('@{imgSrc}/供水产品.png') no-repeat center center;
background-size: 100% 100%;
}
.l_list_item[type='水利产品'] {
background: url('@{imgSrc}/水利产品.png') no-repeat center center;
background-size: 100% 100%;
}
.l_list_item[type='排水产品'] {
background: url('@{imgSrc}/排水产品.png') no-repeat center center;
background-size: 100% 100%;
}
.l_list_item[type='节水产品'] {
background: url('@{imgSrc}/节水产品.png') no-repeat center center;
background-size: 100% 100%;
}
}
\ No newline at end of file
/*
* @Title:新产品动态
* @Author: hongmye
* @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, handToPage, handToProduct } = props;
const toPage = row => {
if (row.site) {
handToProduct(row);
} else if (row['产品地址']) {
handToPage(row['产品地址']);
}
};
const renderRow = (row, index) => {
const rIndex = `r_${index % 7}`;
return (
<Tooltip
placement="left"
title={row['产品地址'] || row.site ? '点击体验' : ''}
mouseEnterDelay={0.5}
color="#1685FF"
>
<div
className={styles.r_list_item}
key={row['产品名称']}
rIndex={rIndex}
type={row['产品地址'] || row.site ? 'jump' : 'none'}
onClick={() => toPage(row)}
>
<div className={styles.r_list_item_title}>{row['产品名称']}</div>
<div className={styles.r_list_item_tip} />
</div>
</Tooltip>
);
};
return (
<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>
<div className={styles.r_list}>
<DataCarousel
gap={1}
autoplay={5000}
itemHeight={350}
list={listData}
renderItem={renderRow}
config={{
loop: false,
slidesPerView: 7,
}}
/>
</div>
</div>
);
};
export default memo(RightItem);
@imgSrc: '@/assets/images/demonstration';
.right_item {
.r_title_wrap {
width: 100%;
height: 123px;
background: url('@{imgSrc}/全行业软硬件系统解决方案.png') no-repeat center center;
background-size: 100% 100%;
padding: 30px 0 0 25px;
.r_title_sub {
background: url('@{imgSrc}/tip.png') no-repeat left center;
background-size: 35px 36px;
padding-left: 35px;
font-size: 16px;
height: 36px;
line-height: 36px;
}
.r_title {
font-size: 22px;
font-family: Microsoft YaHei;
font-weight: bold;
color: #FFFFFF;
padding-left: 5px;
line-height: 32px;
letter-spacing: 1px;
background: linear-gradient(0deg, #92D2FF 0%, #FFFFFF 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
}
.r_list {
height: 350px;
overflow: hidden;
.r_list_item[type='jump']:hover {
// bottom: -8px;
filter: brightness(160%)
}
.r_list_item[type='jump']:hover .r_list_item_tip {
opacity: 1;
}
.r_list_item:not(:last-child) {
margin-bottom: 8px;
}
.r_list_item {
width: 369px;
height: 42px;
font-size: 16px;
text-align: center;
font-weight: bold;
line-height: 40px;
position: relative;
left: 0;
transition: all 0.3s;
}
.r_list_item[type='jump'] {
cursor: pointer;
}
.r_list_item[type='jump']:active {
opacity: 0.8;
}
.r_list_item_tip {
width: 37px;
height: 40px;
background: url('@{imgSrc}/新产品动态_选中.png') no-repeat center center;
background-size: 100% 100%;
position: absolute;
transition: all 0.3s;
top: 0;
left: -30px;
opacity: 0;
}
.r_list_item[rIndex='r_0'] {
background: url('@{imgSrc}/bg1.png') no-repeat left center;
background-size: 100% 100%;
}
.r_list_item[rIndex='r_0']:hover {}
.r_list_item[rIndex='r_1'] {
background: url('@{imgSrc}/bg2.png') no-repeat left center;
background-size: 100% 100%;
}
.r_list_item[rIndex='r_2'] {
background: url('@{imgSrc}/bg3.png') no-repeat left center;
background-size: 100% 100%;
}
.r_list_item[rIndex='r_3'] {
background: url('@{imgSrc}/bg4.png') no-repeat left center;
background-size: 100% 100%;
}
.r_list_item[rIndex='r_4'] {
background: url('@{imgSrc}/bg5.png') no-repeat left center;
background-size: 100% 100%;
}
.r_list_item[rIndex='r_5'] {
background: url('@{imgSrc}/bg6.png') no-repeat left center;
background-size: 100% 100%;
}
.r_list_item[rIndex='r_6'] {
background: url('@{imgSrc}/bg7.png') no-repeat left center;
background-size: 100% 100%;
}
}
}
:global {
.right_item {
.swiper-wrapper {
.swiper-slide {
width: 100%;
height: 50px;
}
}
}
}
\ No newline at end of file
/*
* @Title:
* @Author: hongmye
* @Date: 2023-12-26 18:34:42
*/
import { Button } from 'antd';
import React, { useMemo, useEffect, useRef, useState, forwardRef, useImperativeHandle } from 'react';
import classNames from 'classnames';
import SwiperCore, { Autoplay, Mousewheel, Navigation, Pagination, EffectCoverflow } from 'swiper/core';
import { Swiper, SwiperSlide } from 'swiper/react';
import leftIcon from '@/assets/images/demonstration/arrow_left.png';
import rightIcon from '@/assets/images/demonstration/arrow_right.png';
import { schemeData } from '../configData';
import 'swiper/components/navigation/navigation.min.css';
import 'swiper/components/pagination/pagination.min.css';
import 'swiper/components/effect-coverflow/effect-coverflow.min.css';
import 'swiper/swiper.min.css';
import styles from './index.less';
const autoplay = 15000;
SwiperCore.use([Autoplay, Pagination, Navigation, Mousewheel, EffectCoverflow]);
const VideoItem = (props, ref) => {
const { selectKey = '', setSelectKey } = props;
const swiperRef = useRef(null);
const onSlideToLoop = index => {
if (swiperRef.current) {
swiperRef.current.slideToLoop(index);
}
};
useImperativeHandle(ref, () => ({
onSlideToLoop,
}));
const listData = schemeData.filter(i => !!i.video);
const renderItem = (row, index) => (
<div className={styles.video_box} key={row.title}>
<div className={styles.video_tip} type={row.title}>
<span />
{row.title}
</div>
<div className={styles.video_wrap}>
<video autoPlay="autoPlay" muted controls src={row.video} loop />
</div>
</div>
);
const onSwiper = type => {
if (swiperRef.current) {
if (type === 'left') {
swiperRef.current.slidePrev();
}
if (type === 'right') {
swiperRef.current.slideNext();
}
}
};
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();
}
};
useEffect(() => {}, []);
return (
<div className={classNames(styles.video_list, 'dt_video_list')}>
<Swiper
slidesPerView="auto"
autoplay={{
delay: autoplay,
disableOnInteraction: false,
}}
loop
height={450}
direction="horizontal"
onSlideChange={onSlideChange}
effect="coverflow"
coverflowEffect={{
rotate: 50,
stretch: 10,
depth: 60,
modifier: 2,
slideShadows: false,
}}
mousewheel
onSwiper={swiper => {
swiperRef.current = swiper;
// 鼠标悬浮暂停效果
swiper.$el[0].addEventListener('mouseover', () => swiper.autoplay.stop());
// 鼠标移开后继续自动滚屏效果
swiper.$el[0].addEventListener('mouseleave', () => {
listData.length > 1 && autoplay * 1 ? swiper.autoplay.start() : '';
});
}}
>
{listData.map((item, index) => (
<SwiperSlide key={index} virtualIndex={index} onClick={() => {}}>
{renderItem(item, index + 1)}
</SwiperSlide>
))}
</Swiper>
<div className={classNames(styles.swiper_btn, styles.swiper_left)} onClick={() => onSwiper('left')}>
<img src={leftIcon} alt="" />
</div>
<div className={classNames(styles.swiper_btn, styles.swiper_right)} onClick={() => onSwiper('right')}>
<img src={rightIcon} alt="" />
</div>
</div>
);
};
export default forwardRef(VideoItem);
@imgSrc: '@/assets/images/demonstration';
.video_list {
width: 100%;
padding: 0 30px;
height: calc(100% - 25px);
margin-top: 25px;
background: url('@{imgSrc}/视频bg2.png') no-repeat center center;
background-size: calc(100% - 30px) auto;
position: relative;
.swiper_btn {
position: absolute;
width: 36px;
height: 40px;
cursor: pointer;
z-index: 100;
img {
width: 100%;
}
}
.swiper_btn:active {
opacity: 0.8;
}
.swiper_left {
left: 20px;
top: 50%;
transform: translateY(-50%);
}
.swiper_right {
right: 20px;
top: 50%;
transform: translateY(-50%);
}
.video_box {
width: 100%;
height: 450px;
padding: 0 28px 20px;
background: url('@{imgSrc}/视频bg.png') no-repeat center center;
background-size: calc(100% - 56px) 100%;
display: flex;
justify-content: center;
align-items: center;
position: relative;
overflow: hidden;
}
.video_wrap {
position: relative;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
border-radius: 10px;
padding: 10px;
video {
object-fit: fill;
width: 100%;
height: 100%;
border-radius: 10px;
}
}
.video_tip {
width: 123px;
height: 32px;
background: url('@{imgSrc}/供水产品标题.png') no-repeat center center;
background-size: 100% 100%;
padding: 5px 0 0 15px;
font-weight: bold;
position: absolute;
left: 28px;
top: 0;
z-index: 12;
span {
display: inline-block;
width: 10px;
height: 10px;
border: 3px solid #FFFFFF;
box-shadow: 0px 2px 3px 0px rgba(9, 23, 55, 0.3);
border-radius: 50%;
margin-right: 10px;
}
}
.video_tip[type='水利产品'] {
background: url('@{imgSrc}/水利产品标题.png') no-repeat center center;
background-size: 100% 100%;
}
.video_tip[type='排水产品'] {
background: url('@{imgSrc}/排水产品标题.png') no-repeat center center;
background-size: 100% 100%;
}
.video_tip[type='节水产品'] {
background: url('@{imgSrc}/节水产品标题.png') no-repeat center center;
background-size: 100% 100%;
}
}
:global {
.dt_video_list {
.swiper-slide {
width: 100%;
}
.swiper-container {
width: 100%;
height: 100%;
}
}
}
\ No newline at end of file
/* eslint-disable prettier/prettier */
/*
* @Title:
* @Author: hongmye
* @Date: 2024-01-30 15:29:09
*/
import gongshuiVideo from '@/assets/videos/供水.mp4';
import shuiliVideo from '@/assets/videos/水利.mp4';
import paishuiVideo from '@/assets/videos/排水.mp4';
import jieshuiVideo from '@/assets/videos/节水.mp4';
const schemeData = [
{
title: '供水产品',
background: '',
url: '',
video: gongshuiVideo,
type: '供水',
},
{
title: '水利产品',
background: '',
url: '',
video: shuiliVideo,
type: '水利',
},
{
title: '排水产品',
background: '',
url: '',
video: paishuiVideo,
type: '排水',
},
{
title: '节水产品',
background: '',
url: '',
video: jieshuiVideo,
type: '能源',
},
];
const platformData = [
{
title: '水务统一接入平台',
icon: '水务统一接入平台icon.png',
flex: 248,
url: '',
blank: true,
},
{
title: '水务web组态平台',
icon: '水务web组态平台icon.png',
flex: 253,
url: '',
blank: true,
},
{
title: '水务数据中台',
icon: '水务数据中台icon.png',
flex: 216,
url: '',
blank: true,
},
{
title: '熊猫智慧水务系列支撑能力平台',
icon: '',
isCenter: true,
flex: 464,
url: '',
},
{
title: '水务门户网站',
icon: '水务门户网站icon.png',
flex: 226,
url: '',
blank: true,
},
{
title: '水务全场景低代码平台',
icon: '水务全场景低代码平台icon.png',
flex: 283,
url: '',
blank: true,
},
{
title: '水务AI平台',
icon: '水务AI平台icon.png',
flex: 210,
url: '',
blank: true,
},
];
export { schemeData, platformData };
/*
* @Title:
* @Author: hongmye
* @Date: 2023-01-10 11:18:55
*/
import { useCallback, useEffect, useRef, useState } from 'react';
const useFullScreen = needFullscreen => {
const [isFullscreen, setIsFullscreen] = useState(!!document.fullscreenElement);
const ref = useRef();
useEffect(() => {
const handleToggleFullScreen = () => {
setIsFullscreen(!!document.fullscreenElement);
};
document.addEventListener('fullscreenchange', handleToggleFullScreen);
return () => {
document.removeEventListener('fullscreenchange', handleToggleFullScreen);
};
}, []);
const handleFullScreen = useCallback(() => {
ref.current?.requestFullscreen && ref.current?.requestFullscreen();
}, []);
const handleExitFullScreen = useCallback(() => {
document.exitFullscreen();
}, []);
useEffect(() => {
needFullscreen && handleFullScreen();
}, [handleFullScreen, needFullscreen]);
return [ref, isFullscreen, handleFullScreen, handleExitFullScreen];
};
export default useFullScreen;
/* 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 { FullscreenExitOutlined, FullscreenOutlined, RightOutlined } from '@ant-design/icons';
import exitImg from '@/assets/images/demonstration/退出.png';
import { Button, Spin, message, Tooltip } from 'antd';
import React, { useMemo, useState, useEffect, useRef } from 'react';
import { cloneDeep, debounce } from 'lodash';
import Cookies from 'js-cookie';
import { encode } from 'js-base64';
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 { defaultApp } from '@/micro';
import useFullScreen from './components/useFullScreen';
import styles from './index.less';
import LeftItem from './components/Left';
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 = ['供水', '排水', '能源', '水利'];
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 [jumpLoading, setJumpLoading] = useState(false);
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 [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 failCallback = err => {
setJumpLoading(false);
};
// 方案跳转
const handlePage = (event, type, row) => {
const config = props.global;
const industries = config.userInfo?.Industries || [];
if (!industries.includes(type)) {
message.error(`该用户未配置${row.title}`);
return;
}
setJumpLoading(true);
config.uiwidgets = [];
config.widgets = [];
config.allWidgets = [];
props.instance && props.instance.updateConfig(config);
loginAction && loginAction.getUserInfoAndConfig(failCallback, true, type);
};
const updateConfig = (config, data) => {
// props.instance && props.instance.updateConfig(config);
props.updateConfig && props.updateConfig(config);
const newLoginAction = new LoginAction({ ...props, global: config });
newLoginAction && newLoginAction.getUserInfoAndConfig(failCallback, true, data.industry);
};
// 新产品跳转
const handToProduct = data => {
if (!data.site) return message.warning('该用户没有权限!');
setJumpLoading(true);
const userParam = {
token: props.global.token,
subOID: 'subOID',
site: data.site,
ignoreSite: true,
};
const gateWayParam = {
_site: data.site,
};
Promise.all([appService.getUserInfo(userParam), appService.getWateWayConfig(gateWayParam)])
.then(results => {
const res = results[0];
const gatewayRes = results[1];
if (res.code !== 0) {
setJumpLoading(false);
message.error('获取用户信息失败');
}
// 重置一些环境配置
const config = { ...props.global };
config.uiwidgets = [];
config.widgets = [];
config.allWidgets = [];
config.userInfo = window?.globalConfig?.transformUserInfo?.(res.data) ?? res.data;
// 默认有个上次记住的登入企业,存在印象。这里把cookie和localStorage中的都重新设置一下
const date = new Date();
date.setTime(date.getTime() + 24 * 60 * 60 * 1000);
const encodeSite = encode(encodeURIComponent(data.site));
localStorage.setItem('loginSite', JSON.stringify({ [config.token]: data.site }));
Cookies.set('site', encodeSite, {
expires: date,
path: '/',
});
props.updateConfig && props.updateConfig(config);
// 重置网关配置
const hasGateWay =
!gatewayRes || !gatewayRes.data
? false
: _.isString(gatewayRes.data)
? JSON.parse(gatewayRes.data)
: typeof gatewayRes.data === 'boolean'
? gatewayRes.data
: false;
config.hasGateWay = hasGateWay;
config.apiGatewayDomain = `${window.location.origin}${hasGateWay ? '/PandaCore/GateWay' : ''}`;
if (hasGateWay) {
appService
.authorizationToken({
loginName: config.userInfo?.loginName || '',
type: 'WorkNo',
})
.then(tokenRes => {
if (res.code === 0) {
config.access_token = tokenRes.data?.access_token ?? '';
localStorage.setItem('access_token', config.access_token);
}
updateConfig(config, data);
})
.catch(err => {
updateConfig(config, data);
});
} else {
config.access_token = null;
localStorage.setItem('access_token', config.access_token);
updateConfig(config, data);
}
})
.catch(err => {
setJumpLoading(true);
message.error('获取用户信息失败');
});
};
const handToPage = url => {
if (!url) return message.warning('该环境未配置,请联系管理员');
window.open(url, '_blank');
};
const handToPlatform = col => {
if (col['数值'] && col['数值'].includes('http')) {
handToPage(col['数值']);
}
handToProduct(col);
};
const renderCenter = useMemo(() => {
let list = [...platformData];
list = list.map(l => {
const item = configData.find(c => c['名称'] === l.title);
return { ...l, ...item };
});
return list.map(col => {
if (col.isCenter) {
return (
<div className={styles.center_title} style={{ flex: col.flex }} type={col.title}>
<div>{col.title}</div>
</div>
);
}
const isJump = col.site || (col['数值'] && col['数值'].includes('http'));
return (
<Tooltip title={isJump ? '点击体验' : ''} color="#1685FF">
<div
onClick={() => handToPlatform(col)}
className={styles.center_col}
style={{ flex: col.flex }}
type={col.title}
isJump={isJump ? 'yes' : 'no'}
>
<img src={require(`@/assets/images/demonstration/${col.icon}`)} alt="" />
{col.title}
<RightOutlined />
</div>
</Tooltip>
);
});
}, [configData]);
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;
}
n = Number(n.toFixed(4));
setBoxSize({
scale: n,
boxHeight: bHeight,
});
}
};
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: '排序',
direction: 'asc',
queryWheres: [
{
field: '是否显示',
type: '等于',
value: '是',
},
],
});
Promise.all([req1, req2, req3]).then(result => {
const dataStr1 = result[0]?.data?.jsonData || '';
let data1 = dataStr1 ? JSON.parse(dataStr1) : [];
data1 = data1.filter(d => projectType.includes(d['所属行业']));
const dataStr2 = result[1]?.data?.jsonData || '';
let data2 = dataStr2 ? JSON.parse(dataStr2) : [];
const dataStr3 = result[2]?.data?.jsonData || '';
let data3 = dataStr3 ? JSON.parse(dataStr3) : [];
const groups = props.global?.userInfo?.Groups || [];
data3 = data3.map(d => {
const item = groups.find(g => g.site === d.site);
if (item) {
return { ...d, ...item };
}
delete d.site;
return d;
});
data2 = data2.map(d => {
const item = groups.find(g => g.site === d['数值']);
if (item) {
return { ...d, ...item };
}
return d;
});
setProjectData(data1);
setConfigData(data2);
setProductData(data3);
setLoading(false);
});
};
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(() => {
getData();
window.addEventListener('resize', debounce(onResize, 300));
onResize();
return () => {
window.removeEventListener('resize', onResize);
};
}, []);
return (
<div className={classNames(styles.demonstration)} ref={ref}>
{jumpLoading ? (
<div className={styles.demonstrationLoad}>
<Spin />
</div>
) : null}
{showFullScreen ? (
<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}>
<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>
</div>
<div className={styles.top_r}>
<div className={styles.top_r_text}>- 引领中国智慧水务 -</div>
</div>
</div>
{loading ? (
<div className={styles.loadingWrap}>
<div className={styles.loader} />
</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}
industries={props.global?.userInfo?.Industries || []}
/>
</div>
<div className={styles.row_c}>
<VideoItem ref={videoRef} selectKey={selectKey} setSelectKey={setSelectKey} />
</div>
<div className={styles.row_r}>
<RightItem listData={productData} handToPage={handToPage} handToProduct={handToProduct} />
</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}
industries={props.global?.userInfo?.Industries || []}
/>
</div>
</>
) : null}
</div>
</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));
},
});
export default connect(
mapStateToProps,
mapDispatchToProps,
)(Demonstration);
@imgSrc: '@/assets/images/demonstration';
.demonstration {
height: 100%;
width: 100%;
overflow: hidden;
display: flex;
background: url('@{imgSrc}/背景.png') no-repeat center center;
background-size: 100% 100%;
position: relative;
font-size: 14px;
font-family: Microsoft YaHei;
font-weight: 400;
color: #FFFFFF;
align-items: center;
justify-content: center;
.demonstrationLoad {
width: 100%;
height: 100%;
position: absolute;
display: flex;
align-items: center;
justify-content: center;
top: 0;
left: 0;
z-index: 110;
background-color: rgba(255, 255, 255, 0.8);
}
.demonstrationWrap {
height: 100%;
width: 100%;
overflow: hidden;
transform-origin: left top;
position: absolute;
left: 50%;
top: 50%;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.CV_exit {
cursor: pointer;
position: absolute;
right: 0;
top: 0;
z-index: 10;
}
.top {
color: #fff;
display: flex;
justify-content: space-between;
align-items: flex-end;
flex: none;
.top_l {
width: 281px;
padding-left: 33px;
.top_l_btn:active {
opacity: 0.8;
}
.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;
img {
width: 16px;
height: 16px;
margin-right: 5px;
}
}
}
.top_r {
width: 281px;
height: 35px;
.top_r_text {
width: 100%;
height: 35px;
line-height: 35px;
padding-left: 60px;
background: url('@{imgSrc}/引领中国智慧水务.png') no-repeat center center;
background-size: 100% 100%;
font-size: 15px;
letter-spacing: 3px;
}
}
.top_c {
padding-top: 15px;
.top_c_title {
font-size: 34px;
font-weight: bold;
padding-left: 80px;
color: #FFFFFF;
letter-spacing: 1px;
text-shadow: 0 8px 8px rgba(30, 64, 121, 0.35);
background: url('@{imgSrc}/熊猫图标.png') no-repeat left center;
background-size: 65px;
position: relative;
top: 10px;
line-height: 1;
}
}
}
.row {
padding: 0 33px;
display: flex;
overflow: hidden;
z-index: 10;
flex: none;
.row_l {
width: 372px;
flex: none;
}
.row_r {
width: 372px;
flex: none;
}
.row_c {
flex: 1;
}
}
.center_wrap {
position: relative;
flex: none;
}
.center_tip {
position: absolute;
left: 50%;
top: -38px;
transform: translateX(-50%);
width: 130px;
height: 82px;
z-index: 0;
background: url('@{imgSrc}/箭头.png') no-repeat center/100% 100%;
}
.center {
z-index: 10;
display: flex;
padding: 0 28px 5px;
width: 100%;
overflow: hidden;
line-height: 1;
align-items: flex-end;
.center_title {
height: 89px;
padding-top: 43px;
text-align: center;
background: url('@{imgSrc}/熊猫智慧水务系列支撑能力平台.png') no-repeat center/100% 100%;
z-index: 10;
div {
font-size: 22px;
font-weight: bold;
color: #FFFFFF;
background: linear-gradient(0deg, #92D2FF 0%, #FFFFFF 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
}
.center_col {
height: 61px;
font-size: 15px;
font-weight: bold;
display: flex;
align-items: center;
justify-content: center;
position: relative;
top: 0;
transition: all 0.3s;
margin-bottom: 5px;
img {
width: 36px;
height: 36px;
}
}
.center_col[isJump='yes'] {
cursor: pointer;
}
.center_col[isJump='yes']:hover {
top: -8px;
filter: brightness(130%)
}
.center_col[isJump='yes']:active {
opacity: 0.8;
}
.center_col[type='水务统一接入平台'] {
background: url('@{imgSrc}/水务统一接入平台.png') no-repeat center/100% 100%;
}
.center_col[type='水务web组态平台'] {
background: url('@{imgSrc}/水务web组态平台.png') no-repeat center/100% 100%;
}
.center_col[type='水务数据中台'] {
background: url('@{imgSrc}/水务数据中台.png') no-repeat center/100% 100%;
}
.center_col[type='水务门户网站'] {
background: url('@{imgSrc}/水务门户网站.png') no-repeat center/100% 100%;
}
.center_col[type='水务全场景低代码平台'] {
background: url('@{imgSrc}/水务全场景低代码平台.png') no-repeat center/100% 100%;
}
.center_col[type='水务AI平台'] {
background: url('@{imgSrc}/水务AI平台.png') no-repeat center/100% 100%;
}
}
.bottom {
flex: none;
height: 290px;
overflow: hidden;
}
}
.loadingWrap {
position: absolute;
left: 50%;
top: 40%;
transform: translate(-50%, -38px);
}
.loader {
animation: rotate 2s infinite;
height: 50px;
width: 50px;
}
.loader:before,
.loader:after {
border-radius: 50%;
content: "";
display: block;
height: 20px;
width: 20px;
}
.loader:before {
animation: ball1 2s infinite;
background-color: #fff;
box-shadow: 30px 0 0 #1685FF;
margin-bottom: 10px;
}
.loader:after {
animation: ball2 2s infinite;
background-color: #1685FF;
box-shadow: 30px 0 0 #fff;
}
@keyframes rotate {
0% {
transform: rotate(0deg) scale(0.8)
}
50% {
transform: rotate(360deg) scale(1.2)
}
100% {
transform: rotate(720deg) scale(0.8)
}
}
@keyframes ball1 {
0% {
box-shadow: 30px 0 0 #1685FF;
}
50% {
box-shadow: 0 0 0 #1685FF;
margin-bottom: 0;
transform: translate(15px, 15px);
}
100% {
box-shadow: 30px 0 0 #1685FF;
margin-bottom: 10px;
}
}
@keyframes ball2 {
0% {
box-shadow: 30px 0 0 #fff;
}
50% {
box-shadow: 0 0 0 #fff;
margin-top: -20px;
transform: translate(15px, 15px);
}
100% {
box-shadow: 30px 0 0 #fff;
margin-top: 0;
}
}
\ No newline at end of file
......@@ -5,15 +5,14 @@ import { appService } from '@/api';
import { SERVICE_INTERFACE_SUCCESS_CODE } from '@/constants';
import PandaBootPage from './panda';
import IntegrationPage from './integration';
import Demonstration from './demonstration';
const systemItemName = '引导页模板'; // 系统配置项名称
const BootPageTemplate = {
default: PandaBootPage,
integration: IntegrationPage
integration: IntegrationPage,
demonstration: Demonstration,
};
const BootPage = props => {
const [info, setInfo] = useState({
first: true,
......@@ -21,17 +20,18 @@ const BootPage = props => {
error: false,
});
const [template, setTemplate] = useState('default');
const [pattern, setPattern] = useState(true); // 是否进入演示模式
const RenderComponent = useMemo(() => {
if (window?.globalConfig?.isIntegration >= 1) {
//集成登录
return BootPageTemplate.integration
} else {
//云平台
return BootPageTemplate[template] || BootPageTemplate.default
// 集成登录
return BootPageTemplate.integration;
}
if (pattern && template !== 'integration') {
return BootPageTemplate.demonstration;
}
}, [template]);
// 云平台
return BootPageTemplate[template] || BootPageTemplate.default;
}, [template, pattern]);
useEffect(() => {
if (window?.globalConfig?.isIntegration >= 1) {
......@@ -61,7 +61,9 @@ const BootPage = props => {
}, []);
return (
<SecurityLayout>{info.loading ? <Spin /> : info.error ? <Empty /> : <RenderComponent {...props} />}</SecurityLayout>
<SecurityLayout>
{info.loading ? <Spin /> : info.error ? <Empty /> : <RenderComponent setPattern={setPattern} {...props} />}
</SecurityLayout>
);
};
......
/* eslint-disable global-require */
// 云平台引导页
import React, { useCallback, useEffect, useMemo, useState, useRef } from 'react';
import enterImg from '@/assets/images/demonstration/进入.png';
import { RightOutlined } from '@ant-design/icons';
import { Space, Spin, Progress } from 'antd';
import classNames from 'classnames';
......@@ -15,7 +17,6 @@ import { defaultApp } from '@/micro';
import usingIcon from '@/assets/bootPage/using-icon.png';
import { appService } from '@/api';
import styles from './index.less';
const industries = [
{ name: '供水', type: '供水', subTitle: 'WATER SUPPLY', color: 'rgb(16,104,239)' },
{ name: '农饮水', type: '农饮水', subTitle: 'RURAL POTABLE WATER', color: 'rgb(4,142,101)' },
......@@ -34,6 +35,7 @@ const industries = [
const BootPage = props => {
const dataRef = useRef();
const process = useRef();
const { setPattern } = props;
const [Industries] = useState(props.global.userInfo.Industries);
const [percentBottom, setPercentBottom] = useState(-40);
const [percentNum, setPercentNum] = useState(0);
......@@ -80,7 +82,6 @@ const BootPage = props => {
setTimeout(() => {
setPercentBottom(40);
setPercentNum(100);
setLoadding(false);
clearInterval(process.current);
setTimeout(() => {
props.history.push('/cloud/introduction/newproducts');
......@@ -180,6 +181,11 @@ const BootPage = props => {
return (
<div className={styles.bootPage}>
<div className={styles.b_top_l}>
<div className={styles.b_top_l_btn} onClick={() => setPattern(true)}>
<img src={enterImg} alt="" /> 进入演示模式 <RightOutlined />
</div>
</div>
<div className={styles.bootPageMain}>
<header className={styles.bootPageHead}>
{/* eslint-disable-next-line jsx-a11y/alt-text */}
......
......@@ -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,6 +307,7 @@
.bootPageZh {
font-size: 30px;
}
.bootPageEn {
font-size: 14px;
}
......
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