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

feat: 集成登录配置优化,添加通用模板

parent 215c0491
Pipeline #93597 waiting for manual action with stages
......@@ -62,6 +62,8 @@ export const API = {
REFRESH_SECRET: '/PandaCore/GCK/IntegrationAuth/RefreshSecret', // 根据APPKey生成APPSecret
CM_EVENT_LOAD_DEPARTMENT_ROLES: '/PandaOMS/OMS/WorkOrderCenter/CM_Event_LoadDepartmentAndRoles',
GET_CONFIG_FILE_JSON: '/PandaCore/GCK/FileCenter/ConfigJSON', // 获取配置文件
GET_CONFIG_FILE_LIST: '/PandaOMS/OMS/FileCenter/GetFileUrls', // 获取用户上传
EnableIntegrationConfig: '/PandaCore/GCK/IntegrationAuth/EnableIntegrationConfig', // 开启或关闭集成登录
};
const services = {
......@@ -319,6 +321,16 @@ const services = {
method: constants.REQUEST_METHOD_GET,
type: constants.REQUEST_HTTP,
},
GetFileUrls: {
url: API.GET_CONFIG_FILE_LIST,
method: constants.REQUEST_METHOD_GET,
type: constants.REQUEST_HTTP,
},
EnableIntegrationConfig: {
url: API.EnableIntegrationConfig,
method: constants.REQUEST_METHOD_GET,
type: constants.REQUEST_HTTP,
},
};
export const searchAutoCity = keywords => {
......
......@@ -7,28 +7,80 @@ import { actionCreators } from '@/containers/App/store';
import { store } from '@wisdom-utils/utils';
import LoginAction from '@/pages/user/login/login';
import Cookies from 'js-cookie';
import { notification, Tooltip } from 'antd';
import { notification, Tooltip, message } from 'antd';
import homeIcon from '@/assets/bootPage/集成登录.png';
import { appService } from '@/api';
import axios from 'axios';
import { defaultApp } from '@/micro';
import { useHistory } from '@wisdom-utils/runtime';
import LoadPage from '@/components/LoadPage';
import styles from './index.less';
const IntegratedSwitch = props => {
const timer = useRef(null);
const timer3 = useRef(null);
const progressRef = useRef(0);
const history = useHistory();
const [loginAction, setAction] = useState(() => new LoginAction(props));
const [dataList, setDataList] = useState([]);
const [client, setClient] = useState('');
const clientRef = useRef(props.global.client);
const [jumpLoading, setJumpLoading] = useState(false);
const [progressValue, setProgressValue] = useState(0);
const jumpProgressEnd = () => {
setProgressValue(100);
timer.current && clearInterval(timer.current);
timer.current = null;
};
const jumpProgressStart = () => {
if (timer.current) {
clearInterval(timer.current);
timer.current = null;
}
progressRef.current = 0;
setProgressValue(0);
timer.current = setInterval(() => {
if (progressRef.current < 97.5) {
progressRef.current += 2.5;
setProgressValue(progressRef.current);
} else {
setProgressValue(99);
timer.current && clearInterval(timer.current);
timer.current = null;
}
}, 100);
};
// 定时消除 loading
const startTiming = (time = 2) => {
if (timer3.current) {
clearInterval(timer3.current);
timer3.current = null;
}
timer3.current = setTimeout(() => {
setJumpLoading(false);
timer.current && clearInterval(timer.current);
timer.current = null;
}, time * 1000);
};
const handError = err => {
if (err) {
message.error(err);
}
setJumpLoading(false);
jumpProgressEnd();
};
useEffect(() => {
// if (!window?.globalConfig?.userInfo?.OID || (!(window?.globalConfig?.isIntegration > 1) && window?.globalConfig?.Industry !== '集成登录')) return setDataList([]);
if (!window?.globalConfig?.userInfo?.OID || !(window?.globalConfig?.isIntegration > 1)) return setDataList([]);
appService.GetIntegrationConfig({
if (!window?.globalConfig?.userInfo?.OID || !(window?.globalConfig?.isIntegration >= 1)) return setDataList([]);
appService
.GetIntegrationConfig({
type: '集成登录',
userId: window?.globalConfig?.userInfo?.OID ?? null,
isEnable: true,
// client: `${client || props.global.client || ''}`,
client:
localStorage.getItem('integrationClient') || sessionStorage.getItem('client') || props?.global?.client || '',
})
.then(res => {
setDataList(res?.data || []);
......@@ -41,18 +93,24 @@ const IntegratedSwitch = props => {
// 子站跳转
// eslint-disable-next-line no-shadow
const handlePage = useCallback((item, loginAction) => {
setJumpLoading(true);
jumpProgressStart();
startTiming(5);
if (item.subType === '外链') {
// 营收
if (item.paramValue === 'ticket') {
// 获取临时token
appService.getTicketByToken({ token: window.globalConfig?.token }).then(res => {
if (res.code === 0) {
const url = `${item.url + (item.url.indexOf('?') > 0 ? '&' : '?') + item.paramName}=${res.data}`;
const url = `${item.url + (item.url.indexOf('?') > 0 ? '&' : '?') + item.paramValue}=${res.data}`;
if (item?.openOpt === '当前页打开') {
history.push('/thirdParty', { linkUrl: url });
} else {
window.open(url, '_blank');
}
} else {
setJumpLoading(false);
jumpProgressEnd();
notification.error({
message: '提示',
duration: 3,
......@@ -61,7 +119,9 @@ const IntegratedSwitch = props => {
}
});
} else {
const url = `${item.url + (item.url.indexOf('?') > 0 ? '&' : '?') + item.paramName}=${window.globalConfig?.token}`;
const url = `${item.url + (item.url.indexOf('?') > 0 ? '&' : '?') + item.paramName}=${
window.globalConfig?.token
}`;
if (item?.openOpt === '当前页打开') {
history.push('/thirdParty', { linkUrl: url });
} else {
......@@ -72,9 +132,7 @@ const IntegratedSwitch = props => {
if (window.qiankunIsCache) {
store.set('event:dropCache');
}
const cli = item.url?.indexOf('client=') >= 0 ? item.url.split('client=')[1] : '';
const cli = item.appKey;
Cookies.set('client', cli, {
expires: 86400000 / (24 * 60 * 60 * 1000),
path: '/',
......@@ -87,7 +145,7 @@ const IntegratedSwitch = props => {
sessionStorage.setItem(currentProductNew, 0);
setClient(cli);
clientRef.current = cli;
const config = props.global;
config.uiwidgets = [];
config.widgets = [];
......@@ -98,7 +156,7 @@ const IntegratedSwitch = props => {
}
// props.instance && props.instance.updateConfig(config);
loginAction && loginAction.getUserInfoAndConfig('', true, item.type);
loginAction && loginAction.getUserInfoAndConfig('', true);
} else {
let { url } = item;
if (url?.indexOf('{userId}') >= 0) {
......@@ -122,26 +180,43 @@ const IntegratedSwitch = props => {
useEffect(() => {
const handleToggleIndustry = event => {
history.push(`/?client=${client || props.global.client || ''}`);
setJumpLoading(false);
jumpProgressEnd();
history.push(`/?client=${clientRef.current || props.global.client || ''}`);
props.updateCurrentIndex(0);
defaultApp();
};
const handleError = () => {
setJumpLoading(false);
jumpProgressEnd();
};
loginAction.events.on('toggleIndustry', handleToggleIndustry);
loginAction.events.on('loginError', handleError);
return () => {
loginAction.events.removeListener('toggleIndustry', handleToggleIndustry);
loginAction && loginAction.events && loginAction.events.removeListener('loginError', handleError);
};
}, [loginAction.events, props]);
return (
dataList.length > 1 ? <div className={styles.switchPage}>
return dataList.length > 1 ? (
<div className={styles.switchPage}>
{jumpLoading ? (
<div className={styles.integrationJumpLoad} key="jumpLoading">
<div style={{ width: '285px' }}>
<LoadPage percent={progressValue / 100} text="页面加载中~" />
</div>
</div>
) : null}
<ul className={classNames(styles.switchPageCase, styles.switchPageSmall)}>
<li className={styles.switchPageLi} onClick={() => { history.push('/industry'); }}>
<li
className={styles.switchPageLi}
onClick={() => {
history.push('/industry');
}}
>
<div className={styles.switchPageList}>
<Tooltip placement="top" title="主页">
<img
src={homeIcon}
alt=""
/>
<img src={homeIcon} alt="" />
</Tooltip>
</div>
</li>
......@@ -158,8 +233,8 @@ const IntegratedSwitch = props => {
</li>
))}
</ul>
</div > : null
);
</div>
) : null;
};
const mapStateToProps = state => ({
......
......@@ -9,6 +9,20 @@
width: 100%;
height: 0px;
.integrationJumpLoad {
width: 100vw;
height: 100vh;
position: fixed;
display: flex;
align-items: center;
justify-content: center;
top: 0;
left: 0;
z-index: 1080;
padding-bottom: 50px;
background-color: rgba(0, 0, 0, 0.5);
}
.switchPageCase {
position: absolute;
bottom: 0;
......
......@@ -394,7 +394,7 @@ const Layout = props => {
type: '集成登录',
userId: window.globalConfig.userInfo?.OID ?? null,
isEnable: true,
client: integrationClient || '' // 只有指定client才能获取集成登录信息
client: integrationClient || props.global.client // 只有指定client才能获取集成登录信息
})
.then(res => {
setFirst(false);
......
......@@ -3,7 +3,7 @@
* @Author: hongmye
* @Date: 2023-01-10 11:18:55
*/
import React, { useEffect, useMemo, useState } from 'react';
import React, { useEffect, useMemo, useState, useRef } from 'react';
import { Empty, Spin, notification } from 'antd';
import SecurityLayout from '@/layouts/SecurityLayout';
import { appService } from '@/api';
......@@ -22,6 +22,7 @@ const BootPage = props => {
loading: true,
error: false,
});
const integratedConfig = useRef({});
const { clear } = useAliveController();
const history = useHistory();
const [template, setTemplate] = useState(window?.globalConfig?.displayMode || 'default');
......@@ -56,6 +57,7 @@ const BootPage = props => {
setInfo({ first: false, loading: false, error: true });
return;
}
integratedConfig.current = data;
let displayMode = data?.displayMode || 'default';
if (displayMode === '卡片' || displayMode === '地图') {
displayMode = 'default';
......@@ -69,7 +71,15 @@ const BootPage = props => {
}, []);
return (
<SecurityLayout>{info.loading ? <Spin /> : info.error ? <Empty /> : <RenderComponent {...props} />}</SecurityLayout>
<SecurityLayout>
{info.loading ? (
<Spin />
) : info.error ? (
<Empty />
) : (
<RenderComponent {...{ ...props, ...{ integratedConfig: integratedConfig.current } }} />
)}
</SecurityLayout>
);
};
const mapStateToProps = state => ({
......
......@@ -15,12 +15,17 @@ import DanlingPage from './project/danling';
import MilePage from './project/mile';
import DongyingPage from './project/dongying';
import QinzhouPage from './project/qinzhou';
import IntegrationNewPage from './integrationNew';
export const guidePage = [
// type 为true 则需要 功能配置 isPanda 为true
{
label: '集成登录(默认)',
value: 'default',
},
{
label: '集成登录(新)',
value: 'integrationNew',
},
{
label: '集成登录演示',
value: 'integration2',
......@@ -66,6 +71,7 @@ export const guidePage = [
];
export const BootPageTemplate = {
default: IntegrationPage,
integrationNew: IntegrationNewPage,
panda: PandaBootPage,
integration2: IntegrationPage2,
demonstration: Demonstration,
......
......@@ -5,6 +5,7 @@
overflow: hidden;
z-index: 100;
transition: all 0.2s;
background-color: #fff;
iframe {
border: none;
......
/* eslint-disable indent */
/*
* @Title: 集成登录通用模板
* @Author: hongmye
* @Date: 2024-10-30 18:34:42
*/
import { appService } from '@/api';
import { connect } from 'react-redux';
import { actionCreators } from '@/containers/App/store';
import axios from 'axios';
import { getImageUrl } from '@/utils/utils';
import { FullscreenExitOutlined, FullscreenOutlined } from '@ant-design/icons';
import { message, Button } from 'antd';
import classNames from 'classnames';
import { debounce } from 'lodash';
import React, { useRef, useEffect, useState, useMemo, useCallback } from 'react';
import backImg from '@/assets/images/demonstration/返回.png';
import arrowLeftImg from '@/assets/images/demonstration/左箭头.png';
import LoadPage from '@/components/LoadPage';
import $ from 'jquery';
import { useHistory, useAliveController } from '@wisdom-utils/runtime';
import { store } from '@wisdom-utils/utils';
import Cookies from 'js-cookie';
import LoginAction from '@/pages/user/login/login';
import { defaultApp } from '@/micro';
import useFullScreen from '../demonstration/components/useFullScreen';
import styles from './index.less';
const boxWidth = 1920;
const boxHeight = 930;
const IntegrationNew = props => {
const { integratedConfig } = props;
const [ref, isFullscreen, handleFullScreen, handleExitFullScreen] = useFullScreen(false);
const history = useHistory();
const integrationClient = integratedConfig?.client || window?.globalConfig?.client || 'city'; // 集成登录client
const timer2 = useRef(null);
const timer3 = useRef(null);
const timer4 = useRef(null);
const clientRef = useRef(props.global.client);
const progressRef2 = useRef(0);
const loadingTime = integratedConfig?.loadingTime || 5;
const [loginAction, setAction] = useState(() => new LoginAction(props));
const [mClient, setMClient] = useState('');
const { clear } = useAliveController();
// 退出
const exit = () => {
if (isFullscreen) {
handleExitFullScreen && handleExitFullScreen();
} else {
handleFullScreen && handleFullScreen();
}
};
const [boxSize, setBoxSize] = useState({
scale: 1,
boxHeight: 930,
});
const [integrationData, setIntegrationData] = useState([]); // 所有子站
const [linkUrl, setLinkUrl] = useState('');
// 解决 切换 client 时,updateConfig时,页会刷新,loading会重置
const [jumpLoading, setJumpLoading] = useState(!!window.jumpLoadingProgress);
const [progressValue2, setProgressValue2] = useState(window.jumpLoadingProgress || 0);
const [showBackBtn, setShowBackBtn] = useState(true); // 是否显示iframe 返回按钮,三维平台用
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 getData = async () => {
const token = props.global?.token || Cookies.get('token');
const client = integratedConfig?.client || sessionStorage.getItem('client') || props?.global?.client || '';
localStorage.setItem('integrationClient', client);
appService
.GetIntegrationConfig({
type: '集成登录',
userId: window.globalConfig.userInfo?.OID ?? null,
isEnable: true,
client,
})
.then(res1 => {
const list = res1.data || [];
setIntegrationData(list);
});
};
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 handError = err => {
if (err) {
message.error(err);
}
setLinkUrl('');
setJumpLoading(false);
jumpProgressEnd();
};
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 toRevenue = async item => {
setJumpLoading(true);
jumpProgressStart();
startTiming(6);
try {
const res = await appService.getTicketByToken({ token: window.globalConfig?.token });
if (res.code === 0) {
// 营收是api-bcs,直饮水是api-ddw
// /api-ddw/sysUser/ssoGCK
const apiPath = `${item.url + (item.url.indexOf('?') > 0 ? '&' : '?') + item.paramValue}=${res.data}`;
if (item?.openOpt === '当前页打开') {
props.history.push('/thirdParty', { linkUrl: apiPath });
} else {
window.open(apiPath, '_blank');
}
} else {
res.msg && message.error(res.msg);
setJumpLoading(false);
jumpProgressEnd();
}
} catch (error) {
message.error('跳转错误,请联系管理员');
setJumpLoading(false);
jumpProgressEnd();
}
};
const toClient = (item, loginA) => {
if (window.qiankunIsCache) {
store.set('event:dropCache');
}
const cli = item.appKey;
Cookies.set('client', cli, {
expires: 86400000 / (24 * 60 * 60 * 1000),
path: '/',
});
sessionStorage.setItem('client', cli);
const currentProduct = `__global__recent_productIndex__micro_${window.location.hostname}_${window.globalConfig
?.client ?? 'city'}`;
sessionStorage.removeItem(currentProduct);
const currentProductNew = `__global__recent_productIndex__micro_${window.location.hostname}_${cli || 'city'}`;
sessionStorage.setItem(currentProductNew, 0);
setMClient(cli);
clientRef.current = cli;
const config = props.global;
config.uiwidgets = [];
config.widgets = [];
config.allWidgets = [];
window.qiankunStarted = false;
if (cli) {
config.client = cli;
}
setJumpLoading(true);
jumpProgressStart();
startTiming(loadingTime);
window.jumpLoadingProgress = 99;
loginA && loginA.getUserInfoAndConfig('', true);
};
const onLink = (item, loginA) => {
const token = props.global?.token || Cookies.get('token');
if (!token) {
history.push(`/user/login?client=${integrationClient}`, { reload: true });
clear();
props.logout();
return;
}
const { url, appKey } = item;
if (item.subType === '内链' && appKey) {
toClient(item, loginA);
} else {
if (!url) return;
if (item.subType === '外链') {
if (item.paramValue === 'ticket') {
toRevenue(item); // 去营收
return;
}
}
const link = `${item.url + (item.url.indexOf('?') > 0 ? '&' : '?') + item.paramName}=${
window.globalConfig?.token
}`;
if (item?.openOpt === '当前页打开') {
props.history.push('/thirdParty', { linkUrl: link });
} else {
window.open(link, '_blank');
}
}
};
const renderItem = item => (
<div
onClick={() => onLink(item, loginAction)}
className={styles.IY_item}
key={item.name}
type={item.name}
style={{
zIndex: linkUrl ? 0 : 10,
background: item.backgroundImage ? `url(${getImageUrl(item.backgroundImage)}) center/100% 100% no-repeat` : '',
}}
>
<div className={styles.IY_item_name}>{item.name}</div>
<div className={styles.IY_item_name_sub}>{item.subTitle || ''}</div>
</div>
);
const renderList = useMemo(() => {
const rowMap = {
1: [1],
2: [2],
3: [3],
4: [4],
5: [3, 2],
6: [3, 3],
7: [4, 3],
8: [4, 8],
9: [5, 4],
10: [5, 5],
};
const arr = rowMap[integrationData.length];
const temp = [];
integrationData.forEach((i, index) => {
if (index < arr[0]) {
if (!temp[0]) temp[0] = [];
temp[0].push(i);
} else {
if (!temp[1]) temp[1] = [];
temp[1].push(i);
}
});
return temp.map(row => {
if (row && row.length) {
return <div className={styles.IY_row}>{row.map(item => renderItem(item))}</div>;
}
return null;
});
}, [integrationData]);
useEffect(() => {
getData();
window.addEventListener('resize', debounce(onResize, 300));
onResize();
return () => {
window.removeEventListener('resize', onResize);
timer2.current && clearInterval(timer2.current);
timer2.current = null;
timer3.current && clearInterval(timer3.current);
timer3.current = null;
};
}, []);
useEffect(() => {
if (!linkUrl) {
if (timer4.current) {
clearTimeout(timer4.current);
timer4.current = null;
}
timer4.current = setTimeout(() => {
if ($('.CarouselRipples')?.ripples) {
$('.CarouselRipples').ripples({
resolution: 800,
dropRadius: 20, // px
perturbance: 2,
});
}
}, 1000);
}
return () => {
if (timer4.current) {
clearTimeout(timer4.current);
timer4.current = null;
}
};
}, [linkUrl]);
useEffect(() => {
const handleToggleIndustry = event => {
setJumpLoading(false);
jumpProgressEnd();
window.jumpLoadingProgress = 0;
props.history.push(`/?client=${clientRef.current || props.global.client}`);
props.updateCurrentIndex && props.updateCurrentIndex(0);
defaultApp();
};
const handleError = () => {
setJumpLoading(false);
jumpProgressEnd();
};
loginAction.events.on('loginSuccess', handleToggleIndustry);
loginAction.events.on('loginError', handleError);
return () => {
loginAction && loginAction.events && loginAction.events.removeListener('loginSuccess', handleToggleIndustry);
loginAction && loginAction.events && loginAction.events.removeListener('loginError', handleError);
};
}, [loginAction.events, props]);
return (
<div className={classNames(styles.integrationNew, 'integrationNew')} ref={ref}>
{jumpLoading ? (
<div className={styles.integrationJumpLoad} key="jumpLoading">
<div style={{ width: '285px' }}>
<LoadPage percent={progressValue2 / 100} text="页面加载中~" />
</div>
</div>
) : null}
{!linkUrl ? (
<div className={styles.integrationNew_exit} onClick={exit}>
<Button type="text" style={{ color: '#fff', fontSize: '24px' }}>
{isFullscreen ? <FullscreenExitOutlined /> : <FullscreenOutlined />}
</Button>
</div>
) : null}
<div
className={styles.integration_content}
style={{
width: boxWidth,
height: boxSize.boxHeight,
transform: `scale(${boxSize.scale}) translate(-50%,-50%)`,
zIndex: linkUrl ? 0 : 10,
}}
>
<div className={styles.integrationNew_title}>
<div className={styles.integrationNew_icon}>
<img
src={
props.global &&
props.global.transformDevAssetsBaseURL &&
props.global.transformDevAssetsBaseURL(integratedConfig?.logo || props.global.logo)
}
alt="logo"
/>
</div>
<div className={styles.integrationNew_title_text}>
<span>{integratedConfig?.title || props.global.title || '智慧水务综合监控平台'}</span>
</div>
</div>
{integratedConfig?.subtitle ? (
<div className={styles.integrationNew_title_sub}>{integratedConfig.subtitle}</div>
) : null}
<div className={styles.IY_list}>{renderList}</div>
</div>
{!linkUrl ? (
<div
className={classNames(styles.iframeBack, 'animate__animated', 'animate__fadeIn')}
onClick={() => props.logout()}
>
<div className={styles.iframeBackLeft}>
<img src={arrowLeftImg} alt="返回" />
</div>
<div className={styles.iframeBackIcon}>
<img src={backImg} alt="返回" />
退出
</div>
</div>
) : null}
{linkUrl && showBackBtn ? (
<div
className={classNames(styles.iframeExit, 'animate__animated', 'animate__fadeIn')}
onClick={() => setLinkUrl('')}
>
<div className={styles.iframeExitLeft}>
<img src={arrowLeftImg} alt="返回" />
</div>
<div className={styles.iframeExitIcon}>
<img src={backImg} alt="返回" />
返回
</div>
</div>
) : null}
{!linkUrl ? <div className={classNames(styles.CarouselRipples, 'CarouselRipples')} data-ripple="ripple" /> : null}
</div>
);
};
const mapStateToProps = state => ({
global: state.getIn(['global', 'globalConfig']),
});
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,
)(IntegrationNew);
.integrationNew {
width: 100%;
position: relative;
height: 100%;
overflow: hidden;
background: url('@/assets/images/integration/danling/背景.png') center/100% 100% no-repeat;
.iframeBackIcon {
position: absolute;
top: 0;
right: -45px;
display: flex;
height: 44px;
width: 44px;
background: rgba(28, 94, 180, 0.95);
border-radius: 7px 0px 0px 7px;
flex-direction: column;
justify-content: space-around;
align-items: center;
font-size: 12px;
transition: all 0.2s;
padding: 3px 0;
img {
width: 17px;
height: 12px;
}
}
.iframeBack:hover {
.iframeBackIcon {
right: 0;
}
.iframeBackLeft {
right: -15px;
}
}
.iframeBackLeft {
position: absolute;
top: 0;
right: 0;
width: 14px;
height: 44px;
background: rgba(28, 94, 180, 0.95);
border-radius: 7px 0 0 7px;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.3s;
img {
width: 6px;
height: 11px;
}
}
.iframeBack {
width: 44px;
height: 44px;
position: absolute;
top: 50px;
right: 0;
color: #FFF;
cursor: pointer;
user-select: none;
position: absolute;
z-index: 110;
}
.iframeExitIcon {
position: absolute;
top: 0;
left: -45px;
display: flex;
height: 44px;
width: 44px;
background: rgba(28, 94, 180, 0.95);
border-radius: 0 7px 7px 0;
flex-direction: column;
justify-content: space-around;
align-items: center;
font-size: 12px;
transition: all 0.2s;
padding: 3px 0;
img {
width: 17px;
height: 12px;
}
}
.iframeExit:hover {
.iframeExitIcon {
left: 0;
}
.iframeExitLeft {
left: -15px;
}
}
.iframeExitLeft {
position: absolute;
top: 0;
left: 0;
width: 14px;
height: 44px;
background: rgba(28, 94, 180, 0.95);
border-radius: 0 7px 7px 0;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.3s;
img {
width: 6px;
height: 11px;
}
}
.iframeExit {
width: 44px;
height: 44px;
position: absolute;
top: 4px;
left: 0;
color: #FFF;
cursor: pointer;
user-select: none;
position: absolute;
z-index: 110;
}
.integrationNew_exit {
position: absolute;
right: 10px;
top: 10px;
z-index: 100;
}
.integration_content {
display: flex;
flex-direction: column;
align-items: center;
transform-origin: left top;
position: absolute;
left: 50%;
top: 50%;
padding: 0px 20px 10px;
z-index: 10;
pointer-events: none;
}
//基础平台end
.integrationNew_title {
display: flex;
align-items: center;
justify-content: center;
padding-top: 15px;
padding-bottom: 5px;
.integrationNew_icon {
margin-right: 20px;
img {
max-height: 60px;
}
}
&_text {
flex: none;
color: #fff;
span {
line-height: 64px;
font-weight: bold;
font-size: 36px;
color: #FFFFFF;
letter-spacing: 4px;
// background: linear-gradient(0deg, #56A1EF 0%, #FFFFFF 59%);
// -webkit-background-clip: text;
// -webkit-text-fill-color: transparent;
position: relative;
// top: -8px;
font-family: Microsoft YaHei;
}
}
}
.integrationNew_title_sub {
font-family: Microsoft YaHei;
font-weight: 400;
font-size: 14px;
color: rgba(255, 255, 255, 0.75);
line-height: 22px;
padding: 0 125px;
background: url(@/assets/images/integration/danling/title_left.png) no-repeat left center, url(@/assets/images/integration/danling/title_right.png) no-repeat right center;
background-size: 115px 1px, 115px 1px;
}
.IY_list .IY_row:not(:last-child) {
margin-bottom: 68px;
}
.IY_list {
padding-top: 60px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
margin: auto;
// grid-template-columns: 270px 270px 270px 270px 270px;
// grid-template-rows: 280px;
// gap: 56px 68px;
z-index: 1000;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
.IY_row {
display: flex;
justify-content: center;
}
.IY_row .IY_item:not(:last-child) {
margin-right: 56px;
}
.IY_item {
width: 270px;
height: 280px;
border-radius: 50px;
text-align: center;
padding-top: 198px;
transition: all 0.3s;
position: relative;
top: 0;
cursor: pointer;
z-index: 10;
pointer-events: all;
background: url('@/assets/images/integration/mile/领导驾驶舱.png') center/100% 100% no-repeat;
.IY_item_name {
font-weight: bold;
font-size: 24px;
line-height: 42px;
color: #FFFFFF;
}
.IY_item_name_sub {
font-weight: 400;
font-size: 14px;
color: rgba(255, 255, 255, 0.7);
}
}
.IY_item:hover {
top: -15px;
}
}
.integrationJumpLoad {
width: 100%;
height: 100%;
position: absolute;
display: flex;
align-items: center;
justify-content: center;
top: 0;
left: 0;
z-index: 1080;
padding-bottom: 50px;
background-color: rgba(0, 0, 0, 0.6);
}
.hide {
visibility: hidden;
}
@-webkit-keyframes scale-in-center {
0% {
-webkit-transform: scaleY(0);
transform: scaleY(0);
opacity: 1;
}
100% {
-webkit-transform: scaleY(1);
transform: scaleY(1);
opacity: 1;
}
}
@keyframes scale-in-center {
0% {
-webkit-transform: scaleY(0);
transform: scaleY(0);
opacity: 1;
}
100% {
-webkit-transform: scaleY(1);
transform: scaleY(1);
opacity: 1;
}
}
.scaleInCenter {
visibility: visible;
-webkit-animation: scale-in-center .3s cubic-bezier(0.250, 0.460, 0.450, 0.940) both;
animation: scale-in-center .3s cubic-bezier(0.250, 0.460, 0.450, 0.940) both;
}
.CarouselRipples {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
z-index: 1;
}
& :global {
.CarouselRipples:before {
content: '';
display: inline-block;
vertical-align: middle;
height: 100%;
}
.integrationNew {
.anticon {
vertical-align: 0.125em;
}
}
}
\ No newline at end of file
import React, { useState, useEffect } from 'react';
// import 'react-quill/dist/quill.snow.css';
import { appService } from '@/api';
import {
Form,
......@@ -17,8 +16,9 @@ import {
Switch,
Tooltip,
} from 'antd';
import { PlusOutlined, LoadingOutlined, RedoOutlined } from '@ant-design/icons';
import { PlusOutlined, LoadingOutlined, RedoOutlined, InfoCircleOutlined } from '@ant-design/icons';
import CryptoJS from 'crypto-js';
import { getImageUrl } from '@/utils/utils';
import RMSComponents from './RolePmSite';
import PreviewModal from './PreviewModal';
import styles from '../index.less';
......@@ -30,12 +30,11 @@ const { TextArea } = Input;
const AddModal = props => {
const { callBackSubmit = () => {}, type, pickItem, visible, onCancel, keepSystemName, groupList, targetType } = props;
const [loading, setLoading] = useState(false);
const [radio, setRadio] = useState();
const [identity, setIdentity] = useState(0);
const [form] = Form.useForm();
const subTypes = Form.useWatch('subType', form);
const [imageUrl, setImageUrl] = useState();
const [im, setIm] = useState();
const [imageBgUrl, setImageBgUrl] = useState('');
const [imageType, setImageType] = useState('');
const [previewModal, setPreviewModal] = useState(false);
const [keepImgeUrl, setKeepImgeUrl] = useState('');
const [fileList, setFileList] = useState([]);
......@@ -46,121 +45,11 @@ const AddModal = props => {
const [keepFiled, setKeepFiled] = useState([]);
const [pick, setPick] = useState(''); // 复选框数据填入项
const [keepIds, setKeepIds] = useState(null);
const [account, setAccount] = useState(0);
const [isFromLocal, setIsFromLocal] = useState('');
const key = CryptoJS.enc.Utf8.parse('1p2a3n4d5a6o7m8s9a10n1e2t3c4o5re'); // 十六位十六进制数作为密钥
const iv = CryptoJS.enc.Utf8.parse('1234567890000000');
const { Option } = Select;
useEffect(() => {
if (visible) {
setIsFromLocal('');
getRole();
if (type === 'edit') {
setRadio(pickItem.target != 0);
setIdentity(pickItem.siteType);
setAccount(pickItem.accountType);
const {
paramName,
paramValue,
url,
name,
icon,
roles,
appKey,
appSecret,
whiteList,
subType,
openOpt = '',
} = pickItem;
form.setFieldsValue({
paramName,
paramValue,
url,
subType,
name,
icon,
roles: roles ? roles.split(',') : null,
appKey,
appSecret,
whiteList,
openOpt: openOpt || '',
});
if (pickItem.images && pickItem.images.length > 0) {
const arr = [];
pickItem.images.map((i, j) => {
const aa = {};
aa.uid = j;
aa.name = 'image.png';
aa.status = 'done';
aa.url = `${window.location.origin}/${i}`;
aa.submitUrl = i;
arr.push(aa);
});
setFileList(arr);
}
if (pickItem.icon) {
if (!pickItem.icon.includes('images')) {
setImageUrl(getImg(pickItem.icon));
setIm(pickItem.icon);
} else {
if (pickItem.icon.startsWith('CityTemp') || pickItem.icon.startsWith('civ_integratedlogin')) {
setImageUrl(`http://192.168.12.116:8017/${pickItem.icon}`);
} else {
setImageUrl(`${window.location.origin}/${pickItem.icon}`);
}
setIm(pickItem.icon);
}
// }
} else {
form.setFieldsValue({
icon: '',
});
setImageUrl('');
setIm('');
}
} else {
setRadio(0);
setIdentity(0);
setAccount(0);
form.setFieldsValue({
paramValue: 'ticket',
target: 0,
mapSetting: '',
coordinate: '',
siteType: 0,
accountType: 0,
});
}
} else {
setRadio('');
setFileList([]);
setImageUrl('');
setIm('');
setKeepImgeUrl('');
form.resetFields();
}
}, [visible]);
const getRole = () => {
appService.LoadDepartmentAndRole().then(res => {
if (res.code === 0) {
setKeepFiled(groupArr(res.data, 'groupType'));
const aa = groupArr(res.data, 'groupType');
if (type === 'edit' && pickItem.roles) {
const data = pickItem.roles.split(',');
const newData = [];
data.forEach(item => {
const list = aa.角色.find(i => i.value === item);
if (list) newData.push(list.label);
});
form.setFieldsValue({ roles: newData.toString() });
}
}
});
};
const pickFiled1 = fileds => {
if (form.getFieldValue(fileds)) {
setCheckedList1(form.getFieldValue(fileds).split(','));
......@@ -182,7 +71,6 @@ const AddModal = props => {
ss.label = j.Name;
ss.value = j.ID.toString();
ar.push(ss);
// console.log(ss);
});
list[i.groupType] = ar;
});
......@@ -194,22 +82,7 @@ const AddModal = props => {
if (validate) {
setLoading(true);
const obj = form.getFieldsValue();
if (identity === 0) {
if (!obj.url) {
notification.warning({
message: '提示',
duration: 3,
description: '请填写地址',
});
return;
}
}
const aa = { key: obj.paramName, value: obj.paramValue };
const bb = [];
bb.push(aa);
if (obj.icon.file) {
obj.icon = obj.icon.file.response.data;
}
let data = [];
if (obj.coordinate) {
data = obj.coordinate.split(',');
......@@ -224,18 +97,11 @@ const AddModal = props => {
}
});
}
if (!obj.icon) {
if (!imageUrl) {
message.error('请选择图标!');
return;
}
// 从本地选取
if (!isFromLocal && isFromLocal !== '') {
if (obj.icon.includes('CityTemp') && obj.icon.includes('图库')) {
obj.icon = obj.icon;
} else {
obj.icon = `CityTemp\\图库\\${obj.icon}`;
}
}
if (type === 'add') {
appService
.SaveIntegrationConfig({
......@@ -243,7 +109,7 @@ const AddModal = props => {
type: targetType,
url: obj.url,
roles: keepIds?.join(',') || '',
icon: obj.icon,
icon: imageUrl,
userId: window.globalConfig.userInfo.OID,
paramValue: obj.paramValue,
paramName: obj.paramName,
......@@ -252,6 +118,8 @@ const AddModal = props => {
whiteList: obj.whiteList,
subType: obj.subType,
openOpt: obj.openOpt || '',
backgroundImage: imageBgUrl,
subTitle: obj.subTitle || '',
})
.then(res => {
if (res.code === 0) {
......@@ -283,7 +151,7 @@ const AddModal = props => {
type: pickItem.type,
url: obj.url,
roles: keepIds === null ? pickItem.roles : keepIds.join(','),
icon: obj.icon,
icon: imageUrl,
userId: window.globalConfig.userInfo.OID,
paramValue: obj.paramValue,
paramName: obj.paramName,
......@@ -292,6 +160,8 @@ const AddModal = props => {
appSecret: obj.appSecret,
subType: obj.subType,
openOpt: obj.openOpt || '',
backgroundImage: imageBgUrl,
subTitle: obj.subTitle || '',
})
.then(res => {
if (res.code === 0) {
......@@ -339,11 +209,8 @@ const AddModal = props => {
return isJpgOrPng && isLt2M;
};
const getImg = img => `/PandaOMS/OMS/FileCenter/DownLoadFiles?module=图库&filePath=${img}`;
const getImg = img => `${window.location.origin}/${img}`;
const handleChange = info => {
setKeepImgeUrl('');
setIm('');
if (info.file.status === 'uploading') {
setLoading(true);
return;
......@@ -351,12 +218,11 @@ const AddModal = props => {
if (info.file.status === 'done') {
if (info.file.response.code === 0) {
setIsFromLocal(false);
if (info.file.response.data.includes('CityTemp') && info.file.response.data.includes('图库')) {
setImageUrl(getImg(info.file.response.data));
} else {
setImageUrl(getImg(info.file.response.data));
let icon = info.file.response.data;
if (!icon.includes('CityTemp') || !icon.includes('图库')) {
icon = `CityTemp\\图库\\${icon}`;
}
setImageUrl(icon);
setLoading(false);
} else {
message.error(info.file.response.msg);
......@@ -365,10 +231,30 @@ const AddModal = props => {
}
}
};
const handleChangeBg = info => {
if (info.file.status === 'uploading') {
setLoading(true);
return;
}
if (info.file.status === 'done') {
if (info.file.response.code === 0) {
let icon = info.file.response.data;
if (!icon.includes('CityTemp') || !icon.includes('图库')) {
icon = `CityTemp\\图库\\${icon}`;
}
setImageBgUrl(icon);
setLoading(false);
} else {
message.error(info.file.response.msg);
setImageBgUrl('');
setLoading(false);
}
}
};
const uploadButton = (
<div>
{/* {loading ? <LoadingOutlined/> : <PlusOutlined/>} */}
{/* {loading ? <LoadingOutlined /> : <PlusOutlined />} */}
<div
style={{
marginTop: 8,
......@@ -379,43 +265,25 @@ const AddModal = props => {
</div>
);
const pictruePreview = () => {
const pictruePreview = (iType, img) => {
setImageType(iType);
setKeepImgeUrl(img);
setPreviewModal(true);
};
const onOk = props => {
if (props) {
if (!props.path.includes('images')) {
setImageUrl(getImg(props.path));
setIm(props.path);
setKeepImgeUrl(props.path);
const onOkImg = val => {
if (val) {
if (imageType === 'backgroundImage') {
setImageBgUrl(val.path);
form.setFieldsValue({ backgroundImage: `${val.path}` });
} else {
setImageUrl(`${window.location.origin}/${props.path}`);
setIm(props.path);
setKeepImgeUrl(props.path);
setImageUrl(val.path);
form.setFieldsValue({ icon: `${val.path}` });
}
setIsFromLocal(true);
form.setFieldsValue({ icon: `${props.path}` });
}
};
const options = [
{
value: 'http://{IP:端口}/civbase/user/noscret/?client={client}',
},
{
value: 'http://{IP:端口}/web4/?client={client}',
},
];
const onChangeIdentity = e => {
setIdentity(e.target.value);
};
const onChangeAccount = e => {
setAccount(e.target.value);
};
const onOK = prop => {
setIsVisibleRoles(false);
const inputText = {};
......@@ -444,6 +312,77 @@ const AddModal = props => {
}
});
};
const getRole = () => {
appService.LoadDepartmentAndRole().then(res => {
if (res.code === 0) {
setKeepFiled(groupArr(res.data, 'groupType'));
const aa = groupArr(res.data, 'groupType');
if (type === 'edit' && pickItem.roles) {
const data = pickItem.roles.split(',');
const newData = [];
data.forEach(item => {
const list = aa.角色.find(i => i.value === item);
if (list) newData.push(list.label);
});
form.setFieldsValue({ roles: newData.toString() });
}
}
});
};
useEffect(() => {
if (visible) {
getRole();
if (type === 'edit') {
const {
paramName,
paramValue,
url,
name,
icon,
roles,
appKey,
appSecret,
whiteList,
subType,
openOpt = '',
backgroundImage,
subTitle,
} = pickItem;
form.setFieldsValue({
paramName,
paramValue,
url,
subType,
name,
icon,
roles: roles ? roles.split(',') : null,
appKey,
appSecret,
whiteList,
openOpt: openOpt || '',
backgroundImage,
subTitle,
});
setImageUrl(icon || '');
setImageBgUrl(backgroundImage || '');
} else {
form.setFieldsValue({
paramValue: 'ticket',
target: 0,
mapSetting: '',
coordinate: '',
siteType: 0,
accountType: 0,
});
}
} else {
setFileList([]);
setImageUrl('');
setKeepImgeUrl('');
form.resetFields();
}
}, [visible]);
return (
<Modal
title={type === 'add' ? `新增-${targetType}` : `编辑-${targetType}`}
......@@ -456,24 +395,30 @@ const AddModal = props => {
{...props}
onOk={() => onSubmit()}
forceRender
confirmLoading={loading}
getContainer={false}
>
<Form form={form} {...layout}>
{type === 'edit' ? (
<Row>
<Col span={12}>
<Item
label="名称"
labelCol={{ span: 8 }}
name="name"
rules={[
{ required: true, message: '请输入名称' },
{
validator: (rule, value) => {
const aa = form.getFieldValue().name;
const regEn = /[`~!@#$%^&*()_+<>?:"{},.\/;'[\]]/im;
const regEn = /[`~!@#$%^&*()_+<>?:"{},.\\/;'[\]]/im;
const regCn = /[·!#¥(——):;“”‘、,|《。》?、【】[\]]/im;
if (keepSystemName.indexOf(aa) != -1 && pickItem.name != aa) {
if (keepSystemName.indexOf(aa) !== -1 && (type === 'edit' && pickItem.name !== aa)) {
// eslint-disable-next-line prefer-promise-reject-errors
return Promise.reject('名称已存在');
}
if (regEn.test(aa) || regCn.test(aa)) {
// eslint-disable-next-line prefer-promise-reject-errors
return Promise.reject('名称不能包含特殊字符');
}
return Promise.resolve();
......@@ -483,31 +428,19 @@ const AddModal = props => {
>
<Input allowClear style={{ width: '100%' }} placeholder="请输入名称" />
</Item>
) : (
</Col>
<Col span={10}>
<Item
label="名称"
name="name"
rules={[
{ required: true, message: '请输入名称' },
{
validator: (rule, value) => {
const aa = form.getFieldValue().name;
const regEn = /[`~!@#$%^&*()_+<>?:"{},.\/;'[\]]/im;
const regCn = /[·!#¥(——):;“”‘、,|《。》?、【】[\]]/im;
if (keepSystemName.indexOf(aa) != -1) {
return Promise.reject('名称已存在');
}
if (regEn.test(aa) || regCn.test(aa)) {
return Promise.reject('名称不能包含特殊字符');
}
return Promise.resolve();
},
},
]}
name="subTitle"
tooltip={{
title: '部分集成登录页显示',
icon: <InfoCircleOutlined />,
}}
>
<Input allowClear style={{ width: '100%' }} placeholder="请输入名称" />
<Input placeholder="副标题" autoComplete="off" style={{ marginLeft: '20px', width: '100%' }} />
</Item>
)}
</Col>
</Row>
<Item label="角色选择" name="roles">
<div style={{ display: 'flex' }}>
<Item name="roles" style={{ marginBottom: 0, width: '100%' }}>
......@@ -536,17 +469,16 @@ const AddModal = props => {
]}
>
<Upload
disabled
name="singleFile"
listType="picture-card"
showUploadList={false}
beforeUpload={beforeUpload}
action={`${window.location.origin}${PUBLISH_SERVICE}/UploadSingleFile`}
// onChange={handleChange}
onChange={handleChange}
>
{imageUrl ? (
<img
src={imageUrl}
src={getImageUrl(imageUrl)}
alt="singleFile"
style={{
width: '90%',
......@@ -561,7 +493,53 @@ const AddModal = props => {
</Col>
<Col span={12}>
<Item>
<Button type="primary" onClick={pictruePreview} style={{ marginTop: '33px' }}>
<Button type="primary" onClick={() => pictruePreview('icon', imageUrl)} style={{ marginTop: '33px' }}>
从图片库中选择
</Button>
</Item>
</Col>
</Row>
<Row>
<Col span={10}>
<Item
label="背景图"
name="backgroundImage"
style={{ height: '112px' }}
labelCol={{ span: 10 }}
tooltip={{
title: '部分集成登录页显示',
icon: <InfoCircleOutlined />,
}}
>
<Upload
name="singleFile"
listType="picture-card"
showUploadList={false}
beforeUpload={beforeUpload}
action={`${window.location.origin}${PUBLISH_SERVICE}/UploadSingleFile`}
onChange={handleChangeBg}
>
{imageBgUrl ? (
<img
src={getImageUrl(imageBgUrl)}
alt="singleFile"
style={{
width: '90%',
}}
/>
) : (
uploadButton
)}
</Upload>
</Item>
</Col>
<Col span={12}>
<Item>
<Button
type="primary"
onClick={() => pictruePreview('backgroundImage', imageBgUrl)}
style={{ marginTop: '33px' }}
>
从图片库中选择
</Button>
</Item>
......@@ -575,13 +553,14 @@ const AddModal = props => {
</Radio.Group>
</Item>
{subTypes !== '内链' ? (
<>
{' '}
<Item label="跳转方式" name="openOpt" initialValue="打开新链接">
<Radio.Group>
<Radio value="新窗口打开">新窗口打开</Radio>
<Radio value="当前页打开">当前页打开</Radio>
</Radio.Group>
</Item>
) : null}
<Item label="地址" name="url" rules={[{ required: true, message: '请输入站点路径' }]}>
<AutoComplete placeholder="请输入可以访问的链接,需要与下方的链接类型对应" allowClear />
</Item>
......@@ -591,7 +570,11 @@ const AddModal = props => {
labelCol={{ span: 8 }}
label="参数名"
name="paramName"
rules={[{ required: true, message: '请输入参数' }]}
tooltip={{
title: '直接跳转,不需要填该参数,若与每三方对接,需要该参数',
icon: <InfoCircleOutlined />,
}}
// rules={[{ required: true, message: '请输入参数' }]}
>
<Input allowClear placeholder="请填写站点参数" />
</Item>
......@@ -611,7 +594,7 @@ const AddModal = props => {
label="AppKey"
name="appKey"
className={styles.disabledInput}
rules={[{ required: true, message: '请输入参数' }]}
// rules={[{ required: true, message: '请输入参数' }]}
>
<Input disabled={type === 'edit'} placeholder="请输入自定义的AppKey,提交后不可变更" />
</Item>
......@@ -619,7 +602,7 @@ const AddModal = props => {
label="AppSecret"
name="appSecret"
className={styles.disabledInput}
rules={[{ required: true, message: '请输入AppKey,或点击刷新按钮重新获取AppSecret' }]}
// rules={[{ required: true, message: '请输入AppKey,或点击刷新按钮重新获取AppSecret' }]}
>
<Input
disabled
......@@ -639,16 +622,26 @@ const AddModal = props => {
<Item label="白名单" name="whiteList">
<TextArea rows={3} />
</Item>
</>
) : (
<Item
label="AppKey"
name="appKey"
className={styles.disabledInput}
rules={[{ required: true, message: '请输入参数' }]}
>
<Input disabled={type === 'edit'} placeholder="请输入网站client,提交后不可变更" />
</Item>
)}
</Form>
<PreviewModal
visible={previewModal}
onCancel={() => {
setPreviewModal(false);
}}
imageUrl={im}
keepImgeUrl={keepImgeUrl}
type={type}
callBackSubmit={onOk}
callBackSubmit={onOkImg}
/>
<RMSComponents
visible={isVisibleRoles}
......
/* eslint-disable prefer-template */
/* eslint-disable react/jsx-boolean-value */
import React, { useState, useEffect, useMemo } from 'react';
import {
Form,
Modal,
Input,
notification,
Button,
message,
Upload,
Select,
Col,
Row,
AutoComplete,
InputNumber,
} from 'antd';
import React, { useState, useEffect, useMemo, useRef } from 'react';
import { Button, Form, Modal, Input, message, Upload, Select, Col, Row, Switch, InputNumber, Radio } from 'antd';
import { appService } from '@/api';
import { PlusOutlined, LoadingOutlined } from '@ant-design/icons';
import { PlusOutlined, LoadingOutlined, InfoCircleOutlined } from '@ant-design/icons';
import { guidePage } from '@/pages/bootpage/template/constants';
import { getImageUrl } from '@/utils/utils';
import PreviewModal from './PreviewModal';
const PUBLISH_SERVICE = '/PandaOMS/OMS';
const { Item } = Form;
const { Option } = Select;
const colorList = [
const showTipOptions = [
{
label: '直排',
value: '直排',
},
{
key: '科技蓝',
color: '#2262B2',
// headerColor: 'linear-gradient(0deg, #0066D6 0%, #39A9FF 100%)',
label: '转盘',
value: '转盘',
},
{
key: '环保绿',
color: '#00A295',
// headerColor: 'linear-gradient(0deg, #00845D 0%, #02BF87 100%)',
label: '不显示',
value: 'none',
},
];
const tipAlignOptions = ['左下', '中下', '右下'];
const Master = props => {
const { callBackSubmit = () => {}, visible, onCancel, type, isPanda } = props;
const { callBackSubmit = () => {}, visible, onCancel, type, isPanda, configSetting } = props;
const settingRef = useRef({});
const [loading, setLoading] = useState(false);
const [form] = Form.useForm();
const isShowTip = Form.useWatch('isShowTip', form);
const [imageUrl, setImageUrl] = useState();
const [im, setIm] = useState();
const [previewModal, setPreviewModal] = useState(false);
const [keepImgeUrl, setKeepImgeUrl] = useState('');
const [radio, setRadio] = useState();
const [flag, setFlag] = useState(0);
const [keepSettings, setKeepSettings] = useState([]);
const [isFromLocal, setIsFromLocal] = useState(false);
const optionsTemp = useMemo(() => {
const oType = guidePage.filter(item => {
......@@ -58,116 +43,64 @@ const Master = props => {
});
return oType;
}, [isPanda]);
useEffect(() => {
if (visible) {
appService.GetIntegratedloginSetting().then(res => {
if (res.code === 0) {
const aa = res.data.title.split('<br/>');
const bb = res.data.qrCodeConfig.split('|');
const displayMode = res.data.displayMode || 'default';
const init = async () => {
if (visible || !configSetting) {
console.log('🚀 ~ configSetting:', configSetting);
form.setFieldsValue({
logo: res.data.logo,
primaryColor: res.data.primaryColor,
displayMode,
// subtitle: res.data.subtitle,
title: aa[0],
titlebr: aa[1],
loginTemplate: res.data.loginTemplate,
loadingTime: res.data.loadingTime,
mapSettings: res.data.mapSettings,
qrCodename: bb[0],
qrCodeurl: bb[1],
client: res.data.client,
logo: configSetting.logo,
displayMode: configSetting.displayMode || 'default',
subtitle: configSetting.subtitle,
title: configSetting.title,
loginTemplate: configSetting.loginTemplate,
loadingTime: configSetting.loadingTime,
mapSettings: configSetting.mapSettings,
client: configSetting.client,
isShowTip: configSetting.isShowTip,
isShowPanel: configSetting.isShowPanel,
tipAlign: configSetting.tipAlign,
});
setKeepSettings(res.data.mapSettings);
if (res.data.displayMode === '卡片') {
setFlag(0);
} else {
setFlag(1);
}
const data = res.data.displayMode || 'default';
setRadio(data);
setImageUrl(window.location.origin + `/${res.data.logo}`);
setIm(res.data.logo);
settingRef.current = configSetting || {};
setImageUrl(configSetting.logo || '');
} else {
form.setFieldsValue({
primaryColor: '#1890FF',
});
}
});
} else {
setImageUrl('');
setIm('');
setKeepImgeUrl('');
form.resetFields();
setFlag(0);
}
}, [form, visible]);
};
useEffect(() => {
init();
}, [visible]);
// 提交
const onSubmit = () => {
const obj = form.getFieldsValue();
if (obj.qrCodename && !obj.qrCodeurl) {
notification.error({
message: '提示',
duration: 3,
description: '输入二维码名称,则二维码Url必填',
});
} else if (!obj.qrCodename && obj.qrCodeurl) {
notification.error({
message: '提示',
duration: 3,
description: '输入二维码Url,则输入二维码名称必填',
});
} else {
form.validateFields().then(validate => {
if (obj.logo.file) {
obj.logo = obj.logo.file.response.data;
}
if (obj.titlebr) {
obj.title = `${obj.title}<br/>${obj.titlebr}`;
}
if (validate) {
if (!obj.logo) {
message.error('请选择登录Logo!');
return;
}
if (!isFromLocal) {
if (obj.logo.includes('CityTemp') && obj.logo.includes('图库')) {
obj.logo = obj.logo;
} else {
obj.logo = 'CityTemp\\图库\\' + obj.logo;
}
}
appService
.AddIntegratedloginSetting({
logo: obj.logo,
primaryColor: obj.primaryColor,
const params = {
...settingRef.current,
...{
logo: imageUrl,
subtitle: obj.subtitle,
loginTemplate: obj.loginTemplate || 'Default',
title: obj.title,
displayMode: obj.displayMode,
loadingTime: obj.loadingTime,
mapSettings: obj.displayMode === '卡片' ? keepSettings : obj.mapSettings,
qrCodeConfig: obj.qrCodename && obj.qrCodeurl && `${obj.qrCodename}|${obj.qrCodeurl}`,
client: obj.client || 'city',
})
isShowTip: obj.isShowTip,
isShowPanel: obj.isShowPanel,
tipAlign: obj.tipAlign,
},
};
if (isShowTip !== '直排' || isShowTip !== '转盘') {
params.tipAlign = settingRef.current.tipAlign || '中下';
}
appService
.AddIntegratedloginSetting(params)
.then(res => {
if (res.code === 0) {
onCancel();
callBackSubmit(obj);
notification.success({
message: '提示',
duration: 3,
description: res.msg || '操作成功',
});
callBackSubmit(params);
message.success(res.msg || '保存成功');
} else {
notification.error({
message: '提示',
duration: 3,
description: res.msg || '操作失败',
});
message.error(res.msg || '保存失败');
}
})
.catch(err => {
......@@ -175,15 +108,7 @@ const Master = props => {
});
}
});
}
};
const layout = {
layout: 'horizontal',
labelCol: { span: 4 },
wrapperCol: { span: 18 },
};
const beforeUpload = file => {
const isJpgOrPng =
file.type === 'image/jpeg' || file.type === 'image/png' || file.type === 'image/jpg' || file.type === 'image/gif';
......@@ -196,20 +121,14 @@ const Master = props => {
}
return isJpgOrPng && isLt2M;
};
const getImg = img => `/PandaOMS/OMS/FileCenter/DownLoadFiles?module=图库&filePath=${img}`;
const handleChange = info => {
setKeepImgeUrl('');
setIm('');
if (info.file.status === 'uploading') {
setLoading(true);
return;
}
if (info.file.response.code === 0) {
setIsFromLocal(false);
setImageUrl(getImg(info.file.response.data));
setImageUrl(info.file.response.data);
setLoading(false);
} else {
message.error(info.file.response.msg);
......@@ -217,13 +136,6 @@ const Master = props => {
setLoading(false);
}
};
const getBase64 = (img, callback) => {
const reader = new FileReader();
reader.addEventListener('load', () => callback(reader.result));
reader.readAsDataURL(img);
};
const uploadButton = (
<div>
{loading ? <LoadingOutlined /> : <PlusOutlined />}
......@@ -236,28 +148,20 @@ const Master = props => {
</div>
</div>
);
const pictruePreview = () => {
setPreviewModal(true);
};
const onOk = props => {
if (props) {
setImageUrl(window.location.origin + `/${props.path}`);
setIm(props.path);
setKeepImgeUrl(props.path);
form.setFieldsValue({ logo: `${props.path}` });
setIsFromLocal(true);
const onOk = val => {
if (val) {
setImageUrl(val.path);
form.setFieldsValue({ logo: `${val.path}` });
}
};
const onChange = e => {
setRadio(e.target.value);
if (e.target.value == '地图') {
setFlag(1);
} else {
setFlag(0);
}
const layout = {
layout: 'horizontal',
labelCol: { span: 6 },
wrapperCol: { span: 16 },
};
const renderTitle = title => <span>{title}</span>;
......@@ -302,14 +206,12 @@ const Master = props => {
okText="确认"
{...props}
onOk={() => onSubmit()}
forceRender={true}
forceRender
getContainer={false}
confirmLoading={loading}
>
<Form form={form} {...layout}>
<Row>
<Col span={14}>
<Item
labelCol={{ span: 7 }}
label="标题"
name="title"
rules={[
......@@ -319,22 +221,18 @@ const Master = props => {
},
]}
>
<Input placeholder="请输入标题" autoComplete="off" style={{ marginleft: '3px' }} />
<Input placeholder="请输入标题" autoComplete="off" />
</Item>
</Col>
<Col span={8}>
<Item name="titlebr">
<Input placeholder="换行文案" autoComplete="off" style={{ marginLeft: '20px', width: '123%' }} />
<Item name="subtitle" label="副标题">
<Input placeholder="副标题" autoComplete="off" />
</Item>
</Col>
</Row>
<Row>
<Col span={10}>
<Col span={12}>
<Item
label="登录Logo"
label="logo"
name="logo"
style={{ height: '112px' }}
labelCol={{ span: 10 }}
labelCol={{ span: 12 }}
rules={[
{
required: true,
......@@ -353,11 +251,11 @@ const Master = props => {
>
{imageUrl ? (
<img
src={imageUrl}
src={getImageUrl(imageUrl)}
alt="singleFile"
style={{
width: '90%',
backgroundColor: '#2881a1',
// backgroundColor: '#2881a1',
}}
/>
) : (
......@@ -366,7 +264,7 @@ const Master = props => {
</Upload>
</Item>
</Col>
<Col span={12}>
<Col span={10}>
<Item>
<Button type="primary" onClick={pictruePreview} style={{ marginTop: '33px' }}>
从图片库中选择
......@@ -374,30 +272,28 @@ const Master = props => {
</Item>
</Col>
</Row>
<Item name="primaryColor" label="主题">
<Select placeholder="请选择颜色" style={{ marginLeft: '3px' }}>
{colorList.map(item => (
<Option value={item.color} key={item.color}>
<div style={{ display: 'flex', alignItems: 'center' }}>{`${item.key}`}</div>
</Option>
))}
</Select>
</Item>
<Item label="登录模板" name="loginTemplate">
<AutoComplete placeholder="请选择登录模板" options={options1} allowClear />
</Item>
<Item label="引导页模板" name="displayMode">
<Select placeholder="请选择引导页模板" options={optionsTemp} />
</Item>
<Item label="集成站点" name="client" tooltip="该站点可进入集成登录页,默认为city">
<Input />
</Item>
<Row>
<Col span={8}>
<Item label="切换栏" name="isShowTip" tooltip="以气泡形式,悬浮在页面,可切换子站">
<Radio.Group options={showTipOptions} />
</Item>
{isShowTip === '直排' || isShowTip === '转盘' ? (
<Item label="切换栏位置" name="tipAlign">
<Radio.Group options={tipAlignOptions} />
</Item>
) : null}
<Item label="切换页板" valuePropName="checked" name="isShowPanel" tooltip="子站内,鼠标悬浮页面左上角,可显示">
<Switch checkedChildren="显示" unCheckedChildren="不显示" />
</Item>
<Item
label="加载时间"
name="loadingTime"
labelCol={{ span: 12 }}
rules={[
{
required: true,
......@@ -405,56 +301,19 @@ const Master = props => {
},
]}
>
<InputNumber min={0} max={5} />
</Item>
</Col>
<Col span={16}>
<Item>
<span>秒</span>
</Item>
</Col>
</Row>
<Row>
<Col span={8}>
<Item name="qrCodename" label="二维码" labelCol={{ span: 12 }}>
<Input placeholder="请输入名称" />
</Item>
</Col>
<Col span={16}>
<Item
labelCol={{ span: 4 }}
name="qrCodeurl"
label="url"
rules={[
{
validator: (rule, value) => {
const aa = form.getFieldValue().qrCodeurl;
const regEn = /^((ht|f)tps?):\/\/([\w-]+(\.[\w-]+)*\/?)+(\?([\w\-\.,@?^=%&:\/~\+#]*)+)?$/;
if (aa) {
if (regEn.test(aa) === false) {
return Promise.reject('url必须以http(s)://开头');
}
}
return Promise.resolve();
},
},
]}
>
<Input placeholder="请输入二维码url" style={{ width: '95%' }} />
<InputNumber min={0} max={10} addonAfter="秒" />
</Item>
</Col>
</Row>
</Form>
<PreviewModal
visible={previewModal}
onCancel={() => {
setPreviewModal(false);
}}
imageUrl={im}
keepImgeUrl={keepImgeUrl}
keepImgeUrl={imageUrl}
callBackSubmit={onOk}
type={type}
moduleName="logo"
groupName="logo"
/>
</Modal>
);
......
/* eslint-disable no-lonely-if */
/* eslint-disable no-unused-expressions */
/* eslint-disable prefer-template */
/* eslint-disable react/jsx-boolean-value */
/* eslint-disable no-inner-declarations */
import React, { useState, useEffect } from 'react';
import { Modal, Collapse, notification } from 'antd';
import { appService } from '@/api';
import classnames from 'classnames';
import { getImageUrl } from '@/utils/utils';
import styles from '../index.less';
const { Panel } = Collapse;
const PreviewModal = props => {
const { callBackSubmit = () => {}, visible, onCancel, imageUrl, keepImgeUrl, type } = props;
const { callBackSubmit = () => {}, visible, onCancel, keepImgeUrl, type, moduleName, groupName } = props;
const [imgData, setImgData] = useState([]);
const [pickItem, setPickItem] = useState('');
const [keepItem, setKeepItem] = useState('');
const [keepGroupName, setKeepGroupName] = useState([]);
const update = () => {
appService
.GetIntegrationConfigIcon()
const req1 = appService.GetIntegrationConfigIcon();
const req2 = appService.GetFileUrls({
// moduleName: 'icon,androidMenu,menuNew,logo,CityTemp,bootAnimation,loginPageImage,homePageImage,userPageImage',
moduleName: moduleName || 'CityTemp',
});
Promise.all([req1, req2])
.then(res => {
if (res.code === 0) {
const bb = [];
const aa = [];
res.data.map((i, a) => {
if (res[0]?.code === 0) {
res[0].data.map((i, a) => {
if (i.files.length > 0 && type !== '' && i.groupName !== '网站图标') {
bb.push(i);
aa.push(i.groupName);
......@@ -34,21 +36,12 @@ const PreviewModal = props => {
aa.push(i.groupName);
}
});
setKeepGroupName(aa);
setImgData(bb);
res.data.map(i => {
res[0].data.map(i => {
i.files.map((j, index) => {
if (keepImgeUrl) {
if (j.path == keepImgeUrl) {
setKeepItem(i.groupName);
setPickItem(index);
}
} else {
if (j.path == imageUrl) {
if (j.path === keepImgeUrl) {
setKeepItem(i.groupName);
setPickItem(index);
}
}
});
});
} else {
......@@ -57,6 +50,37 @@ const PreviewModal = props => {
description: res.msg,
});
}
if (res[1]?.code === 0) {
const urlList = [];
function getUrl(arr) {
if (Array.isArray(arr) && arr.length) {
arr.forEach(a => {
if (Array.isArray(a.fileUrls) && a.fileUrls.length) {
a.fileUrls.forEach(f => {
// if (f && f.includes('CityTemp\\图库')) {
urlList.push({
path: f,
name: '',
type: 'custom',
});
// }
});
}
getUrl(a.child);
});
}
}
getUrl(res[1].data || []);
if (urlList.length) {
aa.push(groupName || '用户上传');
bb.push({
groupName: groupName || '用户上传',
files: urlList,
});
}
}
setKeepGroupName(aa);
setImgData(bb);
})
.catch(err => {
console.error(err);
......@@ -79,6 +103,7 @@ const PreviewModal = props => {
}
onCancel();
};
const getImg = img => `${window.location.origin}/${encodeURIComponent(img)}`;
const handleCollapseChange = key => {
setKeepGroupName(key);
......@@ -95,7 +120,7 @@ const PreviewModal = props => {
okText="确认"
{...props}
onOk={() => onSubmit()}
forceRender={true}
forceRender
getContainer={false}
>
<Collapse
......@@ -117,22 +142,14 @@ const PreviewModal = props => {
}}
>
{i.files.map((k, index) => (
// <Image
// src={`${isDev ? process.env.PROXY : window.location.origin}${k}`}
// height="100px"
// />
<div className={styles.divItem} key={index}>
{/* <CheckCircleTwoTone
className={classnames({
[styles.iconHidden]: index !== pickItem || i.groupName !== keepItem,
[styles.iconItem]: index === pickItem && i.groupName === keepItem,
})}
/> */}
<img
src={window.location.origin + `/${k.path}`}
src={getImageUrl(k.path)}
className={classnames({
[styles.imgCommon]: true,
[styles.imgHidden]: index !== pickItem || i.groupName !== keepItem,
[styles.imgItem]: index === pickItem && i.groupName === keepItem,
[styles.imgCustom]: k.type === 'custom',
})}
height="80px"
width="80px"
......
/* eslint-disable no-use-before-define */
/* eslint-disable no-underscore-dangle */
import React, { useState, useEffect, useRef } from 'react';
import { Tooltip, Spin, Modal, Input, Space, Button, Popconfirm, Table, Image, Tag, message, Popover } from 'antd';
import {
Tooltip,
Spin,
Modal,
Input,
Space,
Button,
Popconfirm,
Table,
Image,
Tag,
message,
Popover,
Switch,
} from 'antd';
import { appService } from '@/api';
import { connect } from 'react-redux';
import { actionCreators } from '@/containers/App/store';
import { getImageUrl } from '@/utils/utils';
import { SaveIntegrationIndex } from '@/api/service/base';
import {
EditTwoTone,
DeleteOutlined,
PlusOutlined,
LockOutlined,
UnlockOutlined,
DownOutlined,
SortAscendingOutlined,
SortDescendingOutlined,
} from '@ant-design/icons';
// import pdf from '@/assets/pdf/熊猫智慧水务第三方系统接入说明文档.pdf';
import styles from './index.less';
import AddModal from './components/AddModal';
import Master from './components/Master';
const path = require('path');
const subTypeMap = {
内链: '站内跳转',
外链: '站外跳转',
自定义: '自定义',
};
const IntegratedLogin = props => {
let isPanda = props.params?.isPanda || 'false';
let isPanda = props.params?.isPanda || 'false'; // 云平台判断
isPanda = isPanda === 'true';
const configSetting = useRef({});
const [loading, setLoading] = useState(false);
const [integratedType, setIntegratedType] = useState(props.global.isIntegration >= 1);
const [tableData, setTableData] = useState([]);
const [showSearchStyle, setShowSearchStyle] = useState(false); // 是否显示模糊查询样式
const [searchWord, setSearchWord] = useState(''); // 关键字
......@@ -33,19 +55,6 @@ const IntegratedLogin = props => {
const [keepSystemName, setKeepSystemName] = useState([]);
const [groupList, setGroupList] = useState([]); // 分组列表
const [targetType, setTargetType] = useState('');
const [migrationLoading, setMigrationLoading] = useState(false);
const menuItems = [
{
label: '集成登录',
key: '集成登录',
icon: <PlusOutlined />,
},
{
label: '单点登录',
key: '单点登录',
icon: <PlusOutlined />,
},
];
const { Search } = Input;
......@@ -67,12 +76,12 @@ const IntegratedLogin = props => {
dataIndex: 'icon',
key: 'icon',
align: 'center',
width: 200,
width: 120,
render: (text, record) => {
if (text) {
return (
<Image
src={`${window.location.origin}/${text}`}
src={getImageUrl(text)}
// src={text}
height="50px"
style={{ backgroundColor: '#2881a1' }}
......@@ -98,30 +107,29 @@ const IntegratedLogin = props => {
),
},
{
title: '集成方式',
dataIndex: 'type',
title: '链接类型',
dataIndex: 'subType',
width: 120,
key: 'type',
align: 'center',
render: (text, record) => subTypeMap[text] || '',
},
{
title: 'APPKey',
dataIndex: 'appKey',
width: 120,
key: 'appKey',
align: 'center',
},
{
title: 'APPSecret',
dataIndex: 'appSecret',
key: 'appSecret',
align: 'left',
title: '地址',
dataIndex: 'url',
width: 200,
align: 'center',
},
{
title: '操作',
key: 'action',
width: 200,
width: 150,
align: 'center',
render: (record, text, index) => (
<Space size="middle">
......@@ -137,9 +145,10 @@ const IntegratedLogin = props => {
</Tooltip>
) : null}
<Tooltip title="编辑">
<EditTwoTone onClick={() => edit(record)} style={{ fontSize: '16px' }} />
</Tooltip>
<Button type="text" onClick={() => edit(record)} style={{ color: '#1685ff' }}>
编辑
</Button>
{!record.isEnable ? (
<Tooltip title="点击启用">
<Popconfirm
......@@ -154,7 +163,9 @@ const IntegratedLogin = props => {
cancelText="取消"
onConfirm={() => freezeUser(record)}
>
<LockOutlined style={{ fontSize: '16px', color: '#e86060' }} />
<Button type="text" style={{ color: '#1685ff' }}>
启用
</Button>
</Popconfirm>
</Tooltip>
) : (
......@@ -171,7 +182,9 @@ const IntegratedLogin = props => {
cancelText="取消"
onConfirm={() => freezeUser(record)}
>
<UnlockOutlined style={{ fontSize: '16px', color: '#1890ff' }} />
<Button type="text" style={{ color: '#e86060' }}>
停用
</Button>
</Popconfirm>
</Tooltip>
)}
......@@ -189,7 +202,9 @@ const IntegratedLogin = props => {
cancelText="取消"
onConfirm={() => dele(record)}
>
<DeleteOutlined style={{ fontSize: '16px', color: '#e86060' }} />
<Button type="text" style={{ color: '#e86060' }}>
删除
</Button>
</Popconfirm>
</Tooltip>
</Space>
......@@ -230,7 +245,7 @@ const IntegratedLogin = props => {
setLoading(true);
appService
.GetIntegrationConfig({
client: configSetting.current?.client || 'city',
client: configSetting.current?.client || props.global?.client || 'city',
})
.then(res => {
setLoading(false);
......@@ -342,16 +357,33 @@ const IntegratedLogin = props => {
}
});
};
const migration = () => {
// 调用迁移接口
message.success('迁移成功,重载配置中,请稍后~');
setMigrationLoading(true);
setTimeout(async () => {
await getData();
setMigrationLoading(false);
}, 300);
const onChangeType = e => {
setIntegratedType(e);
appService
.EnableIntegrationConfig({})
.then(res => {
if (res.code === 0) {
if (e) {
message.success('已关打开集成站点');
} else {
message.success('已关闭集成站点');
}
const config = { ...props.global };
if (e) {
config.isIntegration = '1';
} else {
config.isIntegration = '';
}
props.updateConfig && props.updateConfig(config);
} else {
setIntegratedType(!e);
res.msg && message.error(res.msg);
}
})
.catch(err => {
setIntegratedType(!e);
});
};
const handleMenuClick = e => {
add(e.key);
};
......@@ -386,49 +418,35 @@ const IntegratedLogin = props => {
value={searchWord}
/>
<Popover
content={
<Space direction="vertical">
{menuItems.map(item => (
<Button
style={{ marginLeft: 20 }}
type="primary"
onClick={() => {
handleMenuClick(item);
handleMenuClick({ label: '集成登录', key: '集成登录' });
}}
>
{item.label}
<Space>新增子站</Space>
</Button>
))}
</Space>
}
trigger="hover"
>
<Button style={{ marginLeft: 20 }}>
</div>
<Space size={[20]}>
<Space>
新增配置
<DownOutlined />
<Tooltip title={`点击${integratedType ? '关闭集成站点' : '打开集成站点'}`}>
<Switch
onChange={onChangeType}
checked={integratedType}
checkedChildren="开启"
unCheckedChildren="关闭"
/>
</Tooltip>
</Space>
</Button>
</Popover>
<Button style={{ marginLeft: 20 }} type="primary" loading={migrationLoading} onClick={migration}>
一键迁移
</Button>
</div>
<div>
<a target="_blank" style={{ marginRight: '20px' }} href={path.join(__dirname, '/center')}>
快速访问平台
</a>
{/* <Tooltip title="点击查看对接文档">
<a
style={{ display: 'inline-block', marginTop: '5px', marginRight: '20px' }}
target="_blank"
href={path.join(__dirname, pdf)}
rel="noopener noreferer"
href={path.join(__dirname, `/civbase/user/login?client=${configSetting.current?.client || 'city'}`)}
>
<FilePdfOutlined style={{ fontSize: '24px' }} />
快速访问平台
</a>
</Tooltip> */}
<Button onClick={masterStation}>配置集成网站</Button>
</div>
</Space>
</div>
<div className={styles.table}>
<Table
......@@ -442,6 +460,7 @@ const IntegratedLogin = props => {
pagination={false}
/>
</div>
{/* 新增集成登录 */}
{addVisible ? (
<AddModal
visible={addVisible}
......@@ -454,22 +473,31 @@ const IntegratedLogin = props => {
destroyOnClose
keepSystemName={keepSystemName}
/>
) : (
''
)}
) : null}
{/* 集成网站 */}
{masterVisible ? (
<Master
visible={masterVisible}
onCancel={() => setMasterVisible(false)}
type={type}
isPanda={isPanda}
configSetting={configSetting.current}
callBackSubmit={onMasterBack}
/>
) : (
''
)}
) : null}
</div>
);
};
export default IntegratedLogin;
const mapStateToProps = state => ({
global: state.getIn(['global', 'globalConfig']),
instance: state.getIn(['global', 'instance']),
});
const mapDispatchToProps = dispatch => ({
updateConfig(config) {
dispatch(actionCreators.getConfig(config));
},
});
export default connect(
mapStateToProps,
mapDispatchToProps,
)(IntegratedLogin);
......@@ -32,14 +32,17 @@
}
.doctorTable {
margin-bottom: 16px;
margin-bottom: 10px;
}
.divItem {
display: inline-block;
margin-left: 30px;
margin-bottom: 30px;
// width: 80px;
}
.imgCommon {
border: 3px solid transparent;
}
.imgItem {
......@@ -56,6 +59,10 @@
background-color: #2881a1;
}
.imgCustom {
background-color: #fafafa !important;
}
.imgHidden:hover {
border: 3px solid #00ff37;
box-sizing: border-box;
......@@ -64,10 +71,7 @@
}
.iconItem {
// position: relative;
// left: 70px;
// top: 10px;
// font-size: 17px;
margin-top: -3px;
font-size: 17px;
float: right;
......@@ -79,10 +83,7 @@
}
.iconHidden:hover {
// position: relative;
// left: 70px;
// top: 10px;
// font-size: 17px;
margin-top: -3px;
font-size: 17px;
float: right;
......@@ -92,8 +93,7 @@
.table {
flex: 1;
background-color: white;
//height: calc(100vh - 130px);
//margin-top: 10px;
overflow-y: scroll;
padding: 8px;
}
......
/* eslint-disable prettier/prettier */
import React, { useEffect } from 'react';
import React, { useRef, useEffect, useState } from 'react';
import Iframe from 'react-iframe';
import { connect } from 'react-redux';
import Cookies from 'js-cookie';
......@@ -8,6 +8,7 @@ import { actionCreators } from '@/containers/App/store';
import _ from 'lodash';
import { useHistory, useAliveController } from '@wisdom-utils/runtime';
import IntegratedSwitch from '@/components/IntegratedSwitch';
import { message } from 'antd';
import styles from './index.less';
const ThirdParty = props => {
......@@ -16,8 +17,38 @@ const ThirdParty = props => {
if (!state.linkUrl) {
return props.history.push(`/industry`);
}
const onMessageBack = e => {
const { data } = e?.data || {};
if (!data?.type) return;
switch (data?.type) {
// 页面加载完成
// 登录成功
case 'runAfterFirstMounted':
case 'loginSuccess':
break;
case 'loginError':
message.warning('登录失败,请联系管理人员');
break;
case '无法连接':
message.warning('该站点无法连接,请联系管理人员');
break;
case 'showBack':
break;
case 'hideBack':
break;
default:
break;
}
};
useEffect(() => {
window.addEventListener('message', onMessageBack);
return () => {
window.removeEventListener('message', onMessageBack);
};
}, []);
// eslint-disable-next-line react-hooks/rules-of-hooks
useEffect(() => {
const tk = Cookies.get('token') || props.global.token;
......@@ -58,4 +89,7 @@ const mapDispatchToProps = dispatch => ({
dispatch(actionCreators.logout());
},
});
export default connect(mapStateToProps, mapDispatchToProps)(ThirdParty);
export default connect(
mapStateToProps,
mapDispatchToProps,
)(ThirdParty);
......@@ -4,3 +4,17 @@
position: relative;
overflow: hidden;
}
.integrationJumpLoad {
width: 100%;
height: 100%;
position: absolute;
display: flex;
align-items: center;
justify-content: center;
top: 0;
left: 0;
z-index: 1080;
padding-bottom: 50px;
background-color: rgba(0, 0, 0, 0.5);
}
\ No newline at end of file
......@@ -83,3 +83,27 @@ export function getVideoUrl() {
: window.location.origin.replace(protocol, 'ws:');
return `${address}/`;
}
export const getImageUrl = path => {
if (!path || typeof path !== 'string') return '';
if (path.indexOf('http') === 0) {
return path;
}
if (path.indexOf('data:') === 0) {
return path;
}
if (path.startsWith('assets')) {
return `${window.location.origin}/civweb4/${path}`.replace(/\\/g, '/');
}
if (path.startsWith('center/images')) {
return `${window.location.origin}/${path}`.replace(/\\/g, '/');
}
if (path.includes('/个人信息/')) {
path = `/cityinterface/rest/services/filedownload.svc/download${path}`;
return path;
}
if (!path.includes('CityTemp') && !path.includes('图库')) {
path = `CityTemp\\图库\\${path}`;
}
return `/PandaOMS/OMS/FileCenter/DownLoadFiles?module=图库&filePath=${encodeURIComponent(path)}`;
};
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