Commit 6f7cb50e authored by 程恺文's avatar 程恺文
parents 0dac1009 74c00cba
Pipeline #67124 passed with stages
# Don't check auto-generated stuff into git
coverage
build
node_modules
stats.json
.umi
.umi-production
......@@ -12,5 +12,10 @@ npm-debug.log
src/umi
.vscode
civbase
# dependencies
node_modules
npm-debug.log*
yarn-error.log
package-lock.json
yarn.lock
\ No newline at end of file
......@@ -53,6 +53,23 @@ module.exports = {
cssLoader: {
modules: {
getLocalIdent: (context, _, localName) => {
if (/@wisdom-cesium/.test(context.resourcePath)) {
const matchRule = slash(context.resourcePath).match(/@wisdom-cesium\/(krpano)(.*).less$/)
if (matchRule && matchRule[2]) {
if (/rc-slider/.test(matchRule[0])) {
return localName
}
const className = matchRule[2].
split('/')
.map(a => a.replace(/([A-Z])/g, '-$1'))
.map(a => a.toLowerCase()).join('-')
return `panda-krpano-${className}-${localName}`.replace(/--/g, '-')
}
return localName
}
if (
context.resourcePath.includes('node_modules') ||
context.resourcePath.includes('ant.design.pro.less') ||
......
......@@ -106,16 +106,17 @@
"@babel/polyfill": "7.4.3",
"@babel/runtime": "^7.10.5",
"@esri/calcite-colors": "6.0.3",
"@wisdom-cesium/cesium": "^1.1.4",
"@wisdom-cesium/cesium": "^1.1.6",
"@wisdom-cesium/krpano": "1.0.29-20",
"@wisdom-components/basictable": "^1.5.16",
"@wisdom-components/empty": "^1.4.1",
"@wisdom-map/amap": "1.1.0-beta.42",
"@wisdom-map/arcgismap": "1.4.0-84",
"@wisdom-map/basemap": "1.1.0-17",
"@wisdom-map/amap": "1.1.0-beta.47",
"@wisdom-map/arcgismap": "1.4.0-120",
"@wisdom-map/basemap": "1.1.0-21",
"@wisdom-map/util": "^1.0.28-0",
"@wisdom-utils/components": "0.1.279",
"@wisdom-utils/runtime": "0.0.32",
"@wisdom-utils/utils": "0.1.319",
"@wisdom-utils/components": "0.1.287",
"@wisdom-utils/runtime": "0.0.38",
"@wisdom-utils/utils": "0.1.327",
"animate.css": "^4.1.1",
"antd": "4.21.2",
"compression": "1.7.4",
......@@ -142,6 +143,7 @@
"qiankun": "^2.4.6",
"qrcode.react": "^1.0.0",
"rc-cascader": "^2.3.2",
"rc-queue-anim": "^2.0.0",
"react": "17.0.2",
"react-activation": "^0.9.9",
"react-dom": "17.0.2",
......
......@@ -14,6 +14,9 @@
},
{
"title": "节水主题一"
},
{
"title": "新春"
}
]
}
\ No newline at end of file
......@@ -14,6 +14,7 @@ instanceRequest.transformRequestURL = function(url) {
'/CityInterface/rest/services.svc/GetConfig',
'/PandaOMS/OMS/HostManager/GetGateWay',
'/PandaCore/Identity/AuthorizationToken',
'/PandaEnergy/WaterSaving/download',
'/PandaOMS/OMS/WebSite/GetConfig',
];
if (excludeURL.includes(url)) {
......
import { request } from '@wisdom-utils/utils';
import * as constants from '../../constants';
const API = {
GET_INFORMATION:
'/PandaCore/GCK/Message/GetInformationInfo',
GET_MQTT_SITE_CODE:
'/PandaOMS/OMS/HostManager/GetEmqtConfig',
GET_ALL_INFORMATION_INFO:
'/PandaCore/GCK/Message/GetAllInformationInfo',
POST_INFORMATION_STATUS:
'/PandaCore/GCK/Message/PostInformationStatus',
POST_ADD_OPTIONS:
'/CityInterface/rest/services/WisdomUnion.svc/CustomerManage/AddOption',
GET_CURRENT_INFO_TYPE:
'/PandaCore/GCK/Message/GetCurrentInfoType',
GET_INFORMATION: '/PandaCore/GCK/Message/GetInformationInfo',
GET_INFORMATION_THREE: '/PandaOMS/OMS/MessageConfig/GetInformationInfo',
GET_MQTT_SITE_CODE: '/PandaOMS/OMS/HostManager/GetHostConfig',
GET_ALL_INFORMATION_INFO: '/PandaCore/GCK/Message/GetAllInformationInfo',
GET_ALL_INFORMATION_INFO_THREE: '/PandaOMS/OMS/MessageConfig/GetAllInformationInfo',
POST_INFORMATION_STATUS: '/PandaCore/GCK/Message/PostInformationStatus',
POST_ADD_OPTIONS: '/CityInterface/rest/services/WisdomUnion.svc/CustomerManage/AddOption',
GET_CURRENT_INFO_TYPE: '/PandaCore/GCK/Message/GetCurrentInfoType',
};
const notificationService = {
......@@ -23,7 +19,8 @@ const notificationService = {
type: constants.REQUEST_HTTP,
},
getInformationInfo: {
url: API.GET_INFORMATION,
url: () =>
window?.globalConfig?.mqtt_mess?.MessageLevel === '3.0' ? API.GET_INFORMATION_THREE : API.GET_INFORMATION,
method: constants.REQUEST_METHOD_GET,
type: constants.REQUEST_HTTP,
},
......@@ -33,7 +30,10 @@ const notificationService = {
type: constants.REQUEST_HTTP,
},
getAllInformationInfo: {
url: API.GET_ALL_INFORMATION_INFO,
url: () =>
window?.globalConfig?.mqtt_mess?.MessageLevel === '3.0'
? API.GET_ALL_INFORMATION_INFO_THREE
: API.GET_ALL_INFORMATION_INFO,
method: constants.REQUEST_METHOD_GET,
type: constants.REQUEST_HTTP,
},
......@@ -49,5 +49,4 @@ const notificationService = {
},
};
export default notificationService;
This diff was suppressed by a .gitattributes entry.
......@@ -23,6 +23,7 @@ const ValidContainer = props => {
let rules = localStorage.getItem('password_pwdRegex') ? localStorage.getItem('password_pwdRegex') : '';
const check = localStorage.getItem('password_token');
const rulesTip = localStorage.getItem('password_pwdRegexTip') ? localStorage.getItem('password_pwdRegexTip') : '';
const accessToken = localStorage.getItem('access_token') ? localStorage.getItem('access_token') : '';
let reg;
try {
reg = new RegExp(rules);
......@@ -36,7 +37,7 @@ const ValidContainer = props => {
const tk = global.token;
// eslint-disable-next-line no-eval
if (tk) {
if (check && check === true) {
if (rules !== '' && check && check === accessToken) {
setNeedChangePassword(true);
}
}
......
......@@ -314,7 +314,7 @@ class NoticeIconView extends Component {
this.renderSysPlatform(message);
};
handlerUnknowDetail = message => {
handlerUnknowDetail = (message, type) => {
// 需要有跳转路径
if (!message.webPath)
return notification.info({ message: '提示', duration: 3, description: '未配置跳转路径' });
......@@ -343,8 +343,11 @@ class NoticeIconView extends Component {
}
params._source = '消息通知';
params._target = message.webPath;
if (type) {
if (/civweb4/.test(targetMenuPath)) return true;
}
sessionStorage.setItem('routerParams', JSON.stringify(params));
window.history.pushState(params, '', `/civbase/${targetMenuPath}`);
window.history.pushState(params, '', `/civbase/${targetMenuPath}?v=${Date.now()}`);
}
render() {
......
import React, {
useRef,
useState,
} from 'react';
import React, { useRef, useState } from 'react';
import {
message,
Popover,
} from 'antd';
import { message, Popover } from 'antd';
import _ from 'lodash';
import { connect } from 'react-redux';
import Icon from '@ant-design/icons';
import {
AvatarDropdown as Avatar,
useIntl,
} from '@wisdom-utils/components';
import { AvatarDropdown as Avatar, useIntl } from '@wisdom-utils/components';
import HeaderSearch from '@wisdom-utils/components/lib/layout/components/HeaderSearch';
import { useHistory } from '@wisdom-utils/runtime';
......@@ -112,7 +103,7 @@ const GlobalHeaderRight = props => {
const handleFeedback = event => {
event.stopPropagation();
window.open(`https://mis.panda-water.cn/feedback/?site_code="${props.global.get('userInfo.site')}`);
window.open(`https://work.panda-water.cn/feedback/?site_code=${props.global.get('userInfo.site')}`);
}
const handlerFavitor = event => {
......
......@@ -18,7 +18,6 @@ const App = props => {
useEffect(() => {
event.emit('loading', props.loading);
}, [props.loading]);
const metaSecurity = /https/.test(window.location.protocol) ? (
<meta httpEquiv="Content-Security-Policy" content="upgrade-insecure-requests" />
) : null;
......
import { fromJS } from 'immutable';
import Cookies from 'js-cookie';
import { AppConfig, store, event, Storage, helpers } from '@wisdom-utils/utils';
import { Storeage as Store } from '@wisdom-utils/utils/lib/helpers';
import { params, Storeage as Store } from '@wisdom-utils/utils/lib/helpers';
import defaultSetting from '@wisdom-utils/components/lib/AppLayout/layouts/defaultSettings';
import _ from 'lodash';
import memoized from 'nano-memoize';
......@@ -42,7 +42,11 @@ const proxy = require('../../../../config/proxy');
const keywordStorage = new Storage(`__global_search_keywords__micro_${window.location.hostname}`);
const recentVisitedStorage = new Storage(`__global_recent_visited__micro_${window.location.hostname}`);
const recentProductStorage = new Storage(`__global__recent_product__micro_${window.location.hostname}`);
const currentProduct = new Store(`__global__recent_productIndex__micro_${window.location.hostname}`);
const currentProduct = new Store(
`__global__recent_productIndex__micro_${window.location.hostname}_${params.getParams('client') ||
sessionStorage.getItem('client') ||
'city'}`,
);
Cookies.set('loginMode', Cookies.get('loginMode') || 'pdw');
export const initialState = fromJS({
globalConfig: {},
......
......@@ -7,7 +7,9 @@ body,
height: 100%;
overflow: hidden;
}
#app {
background: transparent!important;
}
* {
margin: 0;
padding: 0;
......
......@@ -2,14 +2,16 @@ import { request } from '@wisdom-utils/utils';
import * as constants from '@wisdom-utils/components/lib/AppLayout/helpers/constants';
const API = {
GET_INFORMATION: '/PandaCore/GCK/Message/GetInformationInfo',
GET_MQTT_SITE_CODE: '/PandaOMS/OMS/HostManager/GetEmqtConfig',
GET_INFORMATION_THREE: '/PandaOMS/OMS/MessageConfig/GetInformationInfo',
GET_MQTT_SITE_CODE: '/PandaOMS/OMS/HostManager/GetHostConfig',
POST_INFORMATION_STATUS: '/PandaCore/GCK/Message/PostInformationStatus',
POST_ADD_OPTIONS: '/CityInterface/rest/services/WisdomUnion.svc/CustomerManage/AddOption',
};
const services = {
getInformationInfo: {
url: API.GET_INFORMATION,
url: () =>
window?.globalConfig?.mqtt_mess?.MessageLevel === '3.0' ? API.GET_INFORMATION_THREE : API.GET_INFORMATION,
method: constants.REQUEST_METHOD_GET,
type: constants.REQUEST_HTTP,
},
......@@ -30,7 +32,7 @@ const services = {
},
};
export const postInformationStatus = (param) =>
export const postInformationStatus = param =>
request({
url: API.POST_INFORMATION_STATUS,
method: constants.REQUEST_METHOD_GET,
......
......@@ -4,8 +4,7 @@ export const API = {
IOT_CHANGE_PASSWORD: 'CityInterface/rest/services/OMS.svc/U_UpdatePasswordQuickGCK',
FILE_DOWNLOAD: '/cityinterface/rest/services/filedownload.svc/download',
UPDATE_AVATAR: '/CityInterface/rest/services/OMs.svc/U_EditUser',
UPLOAD_FILE_URL:
'/cityinterface/rest/services/filedownload.svc/uploadfile/个人信息/{path}/{filename}',
UPLOAD_FILE_URL: '/cityinterface/rest/services/filedownload.svc/uploadfile/个人信息/{path}/{filename}',
AVATAR_FILE_URL: '/cityinterface/rest/services/filedownload.svc/download',
GET_VERSION: '/CityInterface/rest/services/OMs.svc/U_GetVersion',
};
......
......@@ -17,7 +17,6 @@ export const MESSAGE_TYPE = {
export const NEW_MESSAGE = 'NEW_MESSAGE';
export const USERNAME = 'mao2080';
export const PASSWORD = '123';
export const PLATFORM_LEVEL = '4';
......
import React from 'react';
import { Badge, Button, ConfigProvider } from 'antd';
// eslint-disable-next-line import/no-unresolved
import classNames from 'classnames';
import useMergeValue from 'use-merge-value';
......@@ -40,8 +41,8 @@ const messageSvg = () => (
/>
</svg>
);
const BellOutlined = (props) => <Icon component={messageSvg} {...props} />;
const NoticeIcon = (props) => {
const BellOutlined = props => <Icon component={messageSvg} {...props} />;
const NoticeIcon = props => {
const { getPrefixCls } = React.useContext(ConfigProvider.ConfigContext);
const prefixCls = props.prefixCls || getPrefixCls();
const btnPrefixCls = `${prefixCls}-head-notifier-button`;
......@@ -54,14 +55,12 @@ const NoticeIcon = (props) => {
}
const panes = [];
React.Children.forEach(children, (child) => {
React.Children.forEach(children, child => {
if (!child) {
return;
}
const { list, title } = child.props;
panes.push(
<NoticeList {...child.props} data={list} key={child} title={title} config={props.config} />,
);
panes.push(<NoticeList {...child.props} data={list} key={child} title={title} config={props.config} />);
});
const childProps = panes.length === 1 ? panes[0].props : { list: [] };
return (
......@@ -72,7 +71,9 @@ const NoticeIcon = (props) => {
type="link"
onClick={() => (childProps.list.length > 0 ? confirmRead(true) : null)}
disabled={childProps.list.length === 0}
>全部标记已读</Button>
>
全部标记已读
</Button>
</div>
{panes}
{renderFooter && renderFooter()}
......
import React from 'react';
import { List, Spin, ConfigProvider } from 'antd';
// eslint-disable-next-line import/no-unresolved
import classNames from 'classnames';
import './style/list.less';
import { Alarm, Case, Notice, Unknown } from './templates';
......@@ -11,10 +12,7 @@ const Empty = ({ emptyText, ...props }) => {
const prefixCls = props.prefixCls || getPrefixCls();
return (
<div className={`${prefixCls}-notFound`}>
<img
src="https://gw.alipayobjects.com/zos/rmsportal/sAuJeJzSKbUmHfBQRzmZ.svg"
alt="not found"
/>
<img src="https://gw.alipayobjects.com/zos/rmsportal/sAuJeJzSKbUmHfBQRzmZ.svg" alt="not found" />
<div>{emptyText}</div>
</div>
);
......@@ -113,11 +111,11 @@ class NoticeList extends React.Component {
switch (item.infoClasses) {
case MESSAGE_TYPE.ALARM_TYPE:
messageTemplate = (
<Alarm message={item} confirmRead={this.confirmRead} config={this.props.config} />
<Alarm message={item} confirmRead={this.confirmRead} config={this.props.config} handlerUnknowDetail={this.handlerUnknowDetail} />
);
break;
case MESSAGE_TYPE.CASE_TYPE:
messageTemplate = <Case message={item} confirmRead={this.confirmRead} />;
messageTemplate = <Case message={item} confirmRead={this.confirmRead} handlerUnknowDetail={this.handlerUnknowDetail} />;
break;
case MESSAGE_TYPE.SYS_TYPE:
messageTemplate = (
......
......@@ -12,6 +12,9 @@ class Message {
webConfig,
webPath,
messType,
defaultContent,
webIcon,
title,
infoClasses
} = message) {
this.id = id;
......@@ -23,6 +26,9 @@ class Message {
this.webConfig = webConfig;
this.webPath = webPath;
this.messType = messType; // 方案名称 - 大类型下细类型
this.webIcon = webIcon; // 消息图标
this.title = title; // 消息标题
this.defaultContent = defaultContent;
this.infoClasses = infoClasses;
}
}
......@@ -64,6 +70,9 @@ export const createMessageFromHis = (hisMessage, options = {}) => {
webConfig: hisMessage.web_config,
webPath: hisMessage.web_path,
messType: hisMessage.messType,
defaultContent: (_.isString(hisMessage.defaultContent) && hisMessage.defaultContent.replace(new RegExp(/ /g), "").length > 0) ? hisMessage.defaultContent : null,
webIcon: (_.isString(hisMessage.webIcon) && hisMessage.webIcon.replace(new RegExp(/ /g), "").length > 0) ? hisMessage.webIcon : null,
title: (_.isString(hisMessage.title) && hisMessage.title.replace(new RegExp(/ /g), "").length > 0) ? hisMessage.title : null,
infoClasses,
};
return createMessage(template);
......@@ -90,9 +99,9 @@ export const createMessageFromReal = (realMesssage, options = {}) => {
// 2.0 消息
infoContent = JSON.parse(realMesssage.content || '{}');
}
const template = {
id: realMesssage.infoId,
id: realMesssage.infoId || realMesssage.ID,
infoContent,
time,
infoType: realMesssage.infoType,
......@@ -100,7 +109,10 @@ export const createMessageFromReal = (realMesssage, options = {}) => {
dateTime: realMesssage.createTime,
webConfig: realMesssage.web_config,
webPath: realMesssage.web_path,
messType: realMesssage.messType,
messType: realMesssage.messType || realMesssage.MessType,
defaultContent: (_.isString(realMesssage.defaultContent) && realMesssage.defaultContent.replace(new RegExp(/ /g), "").length > 0) ? realMesssage.defaultContent : null,
webIcon: (_.isString(realMesssage.webIcon) && realMesssage.webIcon.replace(new RegExp(/ /g), "").length > 0) ? realMesssage.webIcon : null,
title: (_.isString(realMesssage.title) && realMesssage.title.replace(new RegExp(/ /g), "").length > 0) ? realMesssage.title : null,
infoClasses,
}
......
......@@ -351,6 +351,8 @@ class Notifier {
}
} catch (e) {
Logger.error(`收到消息处理异常:${e.message}`);
} finally {
window?.share?.event?.emit?.('event:messageArrived', buffer);
}
}
......@@ -449,8 +451,8 @@ class Notifier {
const alarmType = message?.infoContent?.alarmType; // 报警类型:“状态报警”
const content = message?.infoContent?.alarmContent; // 报警内容:“出水超压报警”
const alarmValue = message?.infoContent?.alarmValue ?? ''; // 报警值
let msg = `紧急报警:${device},${alarmType},${content},报警值:${isString(alarmValue) ? replaceSpeak(alarmValue) :'' },请注意!!!`;
const level = message?.infoLevel !== '1' ? '紧急报警,紧急报警,紧急报警:' : ''
let msg = `${level}${device},${alarmType},${content},报警值:${isString(alarmValue) ? replaceSpeak(alarmValue) :'' },请注意!!!`;
this.speak(msg);
};
speakCase = message => {
......@@ -473,12 +475,13 @@ class Notifier {
};
speakOther = message => {
// 类型区分‘全员公告’ 还是 ‘个人消息’
const type = isEmpty(message.tousers) || parseMessage.tousers === '' ? '公告' : '消息';
const type = message.title ?? (isEmpty(message.tousers) || parseMessage.tousers === '' ? '公告' : '消息');
// 构建语音消息内容
const { infoContent, time } = message;
let content = replaceSpeak((infoContent?.content ?? '').replace(/\\n/g, ','));
let msg = `您有新的${type}${content.substring(0, content.lastIndexOf(',')).replace(':', ',')} 时间:${time}`;
let content = replaceSpeak((infoContent?.content ?? message.defaultContent ?? '').replace(/\\n/g, ','));
const text = content.substring(0, content.lastIndexOf(',')).replace(':', ',');
let msg = `您有新的${type}${text !== '' ? text : content} 时间:${time}`;
this.speak(msg);
};
......
import React from 'react';
import _ from 'lodash';
// eslint-disable-next-line import/no-unresolved
import classNames from 'classnames';
import { findPathByWidget, isJSON } from '@wisdom-utils/components/lib/AppLayout/helpers';
import '../styles/common.less';
import './index.less';
import { ConfigProvider } from 'antd';
import { getMessageTypeIcon } from '../../utils';
/* eslint-disable */
export class AlarmContent {
constructor({
......@@ -26,7 +28,7 @@ export class AlarmContent {
}
}
const Alarm = ({ message, confirmRead, config }) => {
const Alarm = ({ message, confirmRead, config, handlerUnknowDetail }) => {
const { getPrefixCls } = React.useContext(ConfigProvider.ConfigContext);
const prefixCls = getPrefixCls();
......@@ -39,20 +41,22 @@ const Alarm = ({ message, confirmRead, config }) => {
const alarmThreshold = message?.infoContent?.alarmThreshold;
const goPath = (item) => {
if(handlerUnknowDetail && handlerUnknowDetail(message, 'alarm')) {
const widgetID = 'widget_city_综合运营_管网监控_实时监控_报警监控';
const webPath = 'product/scada/AlertMonitoring/AlertMonitoring';
const widget = findPathByWidget(
'productex/water/IOTMonitor/RealTimeAlarm/RealTimeAlarm',
config.widgets,
'',
'url',
);
window.share.event.emit('listenerMointer', {
widgetId: widgetID,
label: '实时报警',
url: widget.url || webPath,
});
}
confirmRead(false, [message.id]);
const widgetID = 'widget_city_综合运营_管网监控_实时监控_报警监控';
const webPath = 'product/scada/AlertMonitoring/AlertMonitoring';
const widget = findPathByWidget(
'productex/water/IOTMonitor/RealTimeAlarm/RealTimeAlarm',
config.widgets,
'',
'url',
);
window.share.event.emit('listenerMointer', {
widgetId: widgetID,
label: '实时报警',
url: widget.url || webPath,
});
};
......@@ -62,6 +66,7 @@ const Alarm = ({ message, confirmRead, config }) => {
className={classNames(`${prefixCls}-notifier-message_scada`, `${prefixCls}-notifier-message-container`)}
title="点击查看详情"
onClick={() => goPath(message)}
style={{ backgroundImage: `url(${getMessageTypeIcon(message)})` }}
>
<div className={`${prefixCls}-notifier-message-title`}>
<span>{alarmType}</span>
......
import React from 'react';
import { ConfigProvider } from 'antd';
// eslint-disable-next-line import/no-unresolved
import classNames from 'classnames';
import '../styles/common.less';
import './index.less';
import { getMessageTypeIcon } from '../../utils';
// "caseType":"待办工单","flowName":"维修处理流程","nodeName":"审核关单","content":"请迅速到现场处理","time":"2020-11-03 09:11:12"
export class CaseContent {
......@@ -17,7 +19,7 @@ export class CaseContent {
}
}
const Case = ({ message, confirmRead }) => {
const Case = ({ message, confirmRead, handlerUnknowDetail }) => {
const { getPrefixCls } = React.useContext(ConfigProvider.ConfigContext);
const prefixCls = getPrefixCls();
const caseType = message?.infoContent?.caseType;
......@@ -27,34 +29,36 @@ const Case = ({ message, confirmRead }) => {
const content = message?.infoContent?.content;
const goPath = item => {
confirmRead(false, [message.id]);
const messageType = item.messType;
let label = '';
let widgetID = '';
switch (messageType) {
case '任务派发':
label = '任务派发';
widgetID = 'widget_city_综合运营_二供管理_维修管理_工单办理';
break;
case '任务驳回':
label = '任务驳回';
widgetID = 'widget_city_综合运营_二供管理_维修管理_工单办理';
// eslint-disable-next-line no-underscore-dangle,no-case-declarations
let _tab;
// eslint-disable-next-line prefer-const
_tab = '任务驳回';
break;
default:
label = '工单办理';
widgetID = 'widget_city_综合运营_二供管理_维修管理_工单办理';
break;
if (handlerUnknowDetail && handlerUnknowDetail(message, 'case')) {
const messageType = item.messType;
let label = '';
let widgetID = '';
switch (messageType) {
case '任务派发':
label = '任务派发';
widgetID = 'widget_city_综合运营_二供管理_维修管理_工单办理';
break;
case '任务驳回':
label = '任务驳回';
widgetID = 'widget_city_综合运营_二供管理_维修管理_工单办理';
// eslint-disable-next-line no-underscore-dangle,no-case-declarations
let _tab;
// eslint-disable-next-line prefer-const
_tab = '任务驳回';
break;
default:
label = '工单办理';
widgetID = 'widget_city_综合运营_二供管理_维修管理_工单办理';
break;
}
const webPath = item.webPath || 'product/maintenance/CaseManage/CaseDoingBox/StardCaseDoingBoxView|isDelay=1';
window.share.event.emit('listenerMointer', {
widgetId: widgetID,
label,
url: webPath,
});
}
const webPath = item.webPath || 'product/maintenance/CaseManage/CaseDoingBox/StardCaseDoingBoxView|isDelay=1';
window.share.event.emit('listenerMointer', {
widgetId: widgetID,
label,
url: webPath,
});
confirmRead(false, [message.id]);
};
return (
......@@ -62,6 +66,7 @@ const Case = ({ message, confirmRead }) => {
className={classNames(`${prefixCls}-notifier-message_case`, `${prefixCls}-notifier-message-container`)}
title="点击查看详情"
onClick={() => goPath(message)}
style={{ backgroundImage: `url(${getMessageTypeIcon(message)})` }}
>
<div className={`${prefixCls}-notifier-message-title`}>
<span>{caseType}</span>
......@@ -72,7 +77,9 @@ const Case = ({ message, confirmRead }) => {
e.stopPropagation();
confirmRead(false, [message.id]);
}}
// eslint-disable-next-line global-require
src={require('../../images/oper/ok_line.png')}
alt=""
/>
</div>
<div className={`${prefixCls}-notifier-message-content`}>
......
import React from 'react';
import { ConfigProvider } from 'antd';
// eslint-disable-next-line import/no-unresolved
import classNames from 'classnames';
import '../styles/common.less';
import './index.less';
import './index.less';
import { getMessageTypeIcon } from '../../utils';
export class NoticeContent {
// eslint-disable-next-line no-undef
......@@ -15,7 +16,6 @@ export class NoticeContent {
}
}
const Notice = ({ message, confirmRead, config, handlerSysDetail }) => {
const { getPrefixCls } = React.useContext(ConfigProvider.ConfigContext);
const prefixCls = getPrefixCls();
......@@ -25,26 +25,31 @@ const Notice = ({ message, confirmRead, config, handlerSysDetail }) => {
const noticeContent = message?.infoContent?.noticeContent ?? '';
// const remark = message?.infoContent?.remark;
const goPath = (item) => {
const goPath = item => {
confirmRead(false, [message.id]);
handlerSysDetail && handlerSysDetail(message);
};
return (
<div
className={classNames(`${prefixCls}-notifier-message_notice`, `${prefixCls}-notifier-message-container`)}
title="点击查看详情"
onClick={() => goPath(message)}
style={{ backgroundImage: `url(${getMessageTypeIcon(message)})` }}
>
<div className={`${prefixCls}-notifier-message-title`}>
<span>{noticeType}{noticeTitle ? `:${noticeTitle}` : ''}</span>
<span>
{noticeType}
{noticeTitle ? `:${noticeTitle}` : ''}
</span>
<img
className={`${prefixCls}-notifier-message-confirm`}
title="点击标为已读"
onClick={(e) => {
onClick={e => {
e.stopPropagation();
confirmRead(false, [message.id]);
}}
// eslint-disable-next-line global-require
src={require('../../images/oper/ok_line.png')}
alt=""
/>
......@@ -52,7 +57,7 @@ const Notice = ({ message, confirmRead, config, handlerSysDetail }) => {
<div className={`${prefixCls}-notifier-message-content`}>
<p>{noticeContent}</p>
</div>
<p className={`${prefixCls}-notifier-message-time`}>{message.time}</p>
<p className={`${prefixCls}-notifier-message-time`}>{message.time}</p>
</div>
);
};
......
import React from 'react';
import { ConfigProvider } from 'antd';
// eslint-disable-next-line import/no-unresolved
import classNames from 'classnames';
import '../styles/common.less';
......@@ -11,24 +12,23 @@ const Unknown = ({ message, confirmRead, handlerUnknowDetail }) => {
const prefixCls = getPrefixCls();
let content = '';
let noticeTitle = '';
const { infoContent } = message;
try {
const type = typeof message.infoContent;
switch (type) {
case 'object':
let { infoContent } = message;
noticeTitle = infoContent.title || '';
content = infoContent.content || JSON.stringify(message.infoContent);
break;
case 'string':
content = message.infoContent;
noticeTitle = message.title || infoContent.title || '';
content = infoContent.content || message.defaultContent || JSON.stringify(message.infoContent);
break;
default:
noticeTitle = message.title || '';
content = message.defaultContent || message.infoContent;
break;
}
} catch (e) {
// i
}
const goPath = (item) => {
const goPath = item => {
handlerUnknowDetail && handlerUnknowDetail(message);
confirmRead(false, [message.id]);
};
......@@ -37,17 +37,18 @@ const Unknown = ({ message, confirmRead, handlerUnknowDetail }) => {
className={classNames(`${prefixCls}-notifier-message_unknown`, `${prefixCls}-notifier-message-container`)}
title="点击查看详情"
onClick={() => goPath(message)}
style={{backgroundImage: `url(${getMessageTypeIcon(message.messType)})`}}
style={{ backgroundImage: `url(${getMessageTypeIcon(message)})` }}
>
<div className={`${prefixCls}-notifier-message-title`}>
<span>{noticeTitle}</span>
<img
className={`${prefixCls}-notifier-message-confirm`}
title="点击标为已读"
onClick={(e) => {
onClick={e => {
e.stopPropagation();
confirmRead(false, [message.id]);
}}
// eslint-disable-next-line global-require
src={require('../../images/oper/ok_line.png')}
alt=""
/>
......
import { MESSAGE_TYPE } from '../constants';
import parseMessageToJSON from './parse';
import alarm_icon from '../images/types/alarm.png';
import approve_icon from '../images/types/approve.png';
import meeting_icon from '../images/types/meeting.png';
import notice_icon from '../images/types/notice.png';
import task_icon from '../images/types/task.png';
import work_icon from '../images/types/work.png';
import write_icon from '../images/types/write.png';
import other_icon from '../images/types/other.png';
import alarmIcon from '../images/types/alarm.png';
import approveIcon from '../images/types/approve.png';
import meetingIcon from '../images/types/meeting.png';
import noticeIcon from '../images/types/notice.png';
import taskIcon from '../images/types/task.png';
import workIcon from '../images/types/work.png';
import writeIcon from '../images/types/write.png';
import otherIcon from '../images/types/other.png';
export const getMessageTypeIcon = messageType => {
let icon = other_icon;
export const getMessageTypeIcon = message => {
const { webIcon } = message;
if (webIcon) return `${window.location.origin}/${webIcon}`;
const { messageType, infoType } = message;
let icon = otherIcon;
if (infoType === '通用报警') {
icon = alarmIcon;
} else if (infoType === '系统通知') {
icon = noticeIcon;
} else if (infoType === '工单提醒') {
icon = workIcon;
}
if (!messageType) return icon;
if (messageType === '工时填报') {
icon = write_icon;
icon = writeIcon;
} else if (messageType.indexOf('审批') > -1) {
icon = approve_icon;
icon = approveIcon;
} else if (messageType.indexOf('会议') > -1) {
icon = meeting_icon;
icon = meetingIcon;
} else if (messageType.indexOf('任务') > -1) {
icon = task_icon;
icon = taskIcon;
}
return icon;
};
export const getMessageClasses = messageType => {
let infoType = '';
switch (messageType) {
// 报警类
case 'SCADA报警':
case '通用报警':
infoType = MESSAGE_TYPE.ALARM_TYPE;
break;
// 工单类
case '工单流程':
case '工单提醒':
infoType = MESSAGE_TYPE.CASE_TYPE;
break;
// 系统消息类
case '系统通知':
case '系统消息':
infoType = MESSAGE_TYPE.SYS_TYPE;
break;
// 其他类
default:
infoType = MESSAGE_TYPE.UNKNOWN;
break;
}
return infoType;
let infoType = '';
switch (messageType) {
// 报警类
case 'SCADA报警':
case '通用报警':
infoType = MESSAGE_TYPE.ALARM_TYPE;
break;
// 工单类
case '工单流程':
case '工单提醒':
infoType = MESSAGE_TYPE.CASE_TYPE;
break;
// 系统消息类
case '系统通知':
case '系统消息':
infoType = MESSAGE_TYPE.SYS_TYPE;
break;
// 其他类
default:
infoType = MESSAGE_TYPE.UNKNOWN;
break;
}
return infoType;
};
/**
* 消息语音单位转换
* 说明:消息通过语音播放时,需要将一些字母单位转换成文字,不然会当做字母播放。
......@@ -76,16 +82,17 @@ export const replaceSpeak = msg => {
return msg;
};
// eslint-disable-next-line arrow-body-style
export const generatedId = () => {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'
.replace(/[xy]/g, function(c) {
// eslint-disable-next-line no-bitwise
const r = (Math.random() * 16) | 0;
// eslint-disable-next-line no-bitwise
const v = c === 'x' ? r : (r & 0x3) | 0x8;
return v.toString(16);
})
.toUpperCase();
};
export {
parseMessageToJSON,
}
\ No newline at end of file
export { parseMessageToJSON };
This diff is collapsed.
......@@ -338,7 +338,7 @@ class Site {
loginSite[token] = site;
localStorage.setItem('loginSite', JSON.stringify(loginSite));
const self = this;
self.props.updateCurrentIndex && self.props.updateCurrentIndex(-1);
// self.props.updateCurrentIndex && self.props.updateCurrentIndex(-1);
const login = new Login(this.props, () => {
self.setLoading(false);
self.getCityStationsForUser().then(res => {
......@@ -373,6 +373,7 @@ class Site {
}
changeGroup(event, item, onChangeVisible, actionRef) {
debugger
event.persist();
const site = item ? item.site : event.target.dataset.site;
const { loginName } = this.globalConfig.userInfo;
......
import React, { memo } from "react";
import SecurityLayout from "../../../layouts/SecurityLayout";
import React from 'react';
import SecurityLayout from '../../../layouts/SecurityLayout';
const HocContainer = Component => {
return (props) => {
return (
<SecurityLayout>
<Component {...props} />
</SecurityLayout>
)
}
}
const HocContainer = Component => props => (
<SecurityLayout>
<Component {...props} />
</SecurityLayout>
);
export default HocContainer;
\ No newline at end of file
export default HocContainer;
import React, { memo } from 'react';
import React, { memo, useEffect, useRef } from 'react';
import { FullscreenExitOutlined, FullscreenOutlined } from '@ant-design/icons';
import Iframe from 'react-iframe';
import Empty from '@wisdom-components/empty';
import styles from './index.less';
import Hoc from './HocContainer';
import useFullScreen from './useFullScreen';
const TabWidget = ({ params }) => {
const { linkUrl } = params || {};
const TabWidget = props => {
const params = Object.assign({}, props.params, {
fullscreen: !(props.params !== undefined && props.params.fullscreen === 'true'),
});
const { linkUrl, fullscreen } = params;
const [ref, isFullscreen, handleFullScreen, handleExitFullScreen] = useFullScreen(fullscreen);
return (
<div className={styles['tab-iframe']}>
<div className={styles['tab-iframe']} ref={ref}>
<div className={styles['oper-wrap']}>
<div className={styles['oper-btn']}>
{isFullscreen ? (
<FullscreenExitOutlined className={styles['btn-fullscreen_exit']} onClick={handleExitFullScreen} />
) : (
<FullscreenOutlined className={styles['btn-fullscreen']} onClick={handleFullScreen} />
)}
</div>
</div>
{linkUrl ? (
<Iframe
url={linkUrl}
......@@ -19,7 +35,7 @@ const TabWidget = ({ params }) => {
styles={{ border: 'none' }}
/>
) : (
<Empty description="配置url链接才能显示哦!"/>
<Empty description="配置url链接才能显示哦!" />
)}
</div>
);
......
......@@ -3,4 +3,34 @@
height: 100%;
position: relative;
overflow: hidden;
iframe {
border: none;
}
.oper-wrap {
top: 0;
right: 0;
width: 100px;
height: 100px;
position: absolute;
z-index: 2;
.oper-btn {
cursor: pointer;
color: #FFF;
position: absolute;
top: 10px;
right: -100%;
transition: right ease-in-out 0.8s;
}
&:hover {
.oper-btn {
right: 20px;
}
}
}
}
\ No newline at end of file
import { useState, useEffect, useCallback, useRef } 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();
}, []);
const handleExitFullScreen = useCallback(() => {
document.exitFullscreen();
}, []);
useEffect(() => {
needFullscreen && handleFullScreen();
}, [handleFullScreen, needFullscreen]);
return [ref, isFullscreen, handleFullScreen, handleExitFullScreen];
};
export default useFullScreen;
This diff is collapsed.
import {Preview} from '@wisdom-cesium/krpano'
const Krpano = props => {
const {projectName} = props
return (<div
style={{
position : "relative",
width : "100%",
height : "100%"
}}
>
<Preview projectName = {projectName}/>
</div>)
}
export default Krpano
\ No newline at end of file
import 'kit_logger';
import React, {
useCallback,
useEffect,
useState,
} from 'react';
import {
Button,
Form,
Input,
message,
} from 'antd';
import React, { useCallback, useEffect, useState } from 'react';
import { Button, Form, Input, message } from 'antd';
import omit from 'omit.js';
import { useIntl } from '@wisdom-utils/components';
......@@ -26,12 +17,7 @@ import ItemMap from './map';
const FormItem = Form.Item;
// eslint-disable-next-line no-undef
const Logger = logger('loginForm');
const getFormItemOptions = ({
onChange,
defaultValue,
customProps = {},
rules,
}) => {
const getFormItemOptions = ({ onChange, defaultValue, customProps = {}, rules }) => {
const options = {
rules: rules || customProps.rules,
};
......@@ -78,7 +64,7 @@ const LoginItem = props => {
}
})
.catch(error => {
message.error(intl.formatMessage({id: 'pages.login.phoneLogin.errorCodeMessage'}));
message.error(intl.formatMessage({ id: 'pages.login.phoneLogin.errorCodeMessage' }));
});
}, []);
......@@ -98,7 +84,7 @@ const LoginItem = props => {
}, 1000);
}
return () => clearInterval(interval);
}, [timing]);
}, [props, timing]);
if (!name) {
return null;
......@@ -114,7 +100,7 @@ const LoginItem = props => {
return Promise.resolve();
}
// eslint-disable-next-line prefer-promise-reject-errors
return Promise.reject(intl.formatMessage({id: 'pages.login.phoneLogin.errorMessage'}));
return Promise.reject(intl.formatMessage({ id: 'pages.login.phoneLogin.errorMessage' }));
};
// eslint-disable-next-line no-shadow
const rules = [
......@@ -126,7 +112,7 @@ const LoginItem = props => {
delete options.rules;
return (
<FormItem shouldUpdate style={{marginBottom: '14px'}}>
<FormItem shouldUpdate style={{ marginBottom: '14px' }}>
{({ getFieldValue, validateFields }) => (
<>
<FormItem name={name} {...options} rules={rules}>
......@@ -147,8 +133,8 @@ const LoginItem = props => {
}}
>
{timing
? `${intl.formatMessage({id: 'pages.login.phoneLogin.sendCationCode'})}(${count})`
: intl.formatMessage({id: 'pages.login.phoneLogin.getVerificationCode'})}
? `${intl.formatMessage({ id: 'pages.login.phoneLogin.sendCationCode' })}(${count})`
: intl.formatMessage({ id: 'pages.login.phoneLogin.getVerificationCode' })}
</Button>
</>
)}
......@@ -156,6 +142,13 @@ const LoginItem = props => {
);
}
if (type === 'Password') {
return (
<FormItem name={name} {...options}>
<Input.Password {...customProps} {...otherProps} />
</FormItem>
);
}
return (
<FormItem name={name} {...options}>
<Input {...customProps} {...otherProps} />
......@@ -169,15 +162,7 @@ Object.keys(ItemMap).forEach(key => {
const item = ItemMap[key];
LoginItems[key] = props => (
<LoginContext.Consumer>
{context => (
<LoginItem
customProps={item.props}
rules={item.rules}
{...props}
type={key}
{...context}
/>
)}
{context => <LoginItem customProps={item.props} rules={item.rules} {...props} type={key} {...context} />}
</LoginContext.Consumer>
);
});
......
......@@ -5,6 +5,8 @@ import {
MailOutlined,
MobileOutlined,
UserOutlined,
EyeInvisibleOutlined,
EyeTwoTone,
} from '@ant-design/icons';
import styles from './index.less';
......@@ -27,9 +29,7 @@ export default {
NewYearPassword: {
props: {
size: 'large',
prefix: (
<LockOutlined className={styles.prefixIcon} twoToneColor="#ff9600" />
),
prefix: <LockOutlined className={styles.prefixIcon} twoToneColor="#ff9600" />,
type: 'password',
id: 'password',
placeholder: '888888',
......@@ -45,6 +45,7 @@ export default {
props: {
size: 'large',
prefix: <LockOutlined className={styles.prefixIcon} />,
iconRender: visible => (visible ? <EyeTwoTone /> : <EyeInvisibleOutlined />),
type: 'password',
id: 'password',
placeholder: '888888',
......@@ -90,9 +91,7 @@ export default {
NewYearMobile: {
props: {
size: 'large',
prefix: (
<MobileOutlined className={styles.prefixIcon} twoToneColor="#ff9600" />
),
prefix: <MobileOutlined className={styles.prefixIcon} twoToneColor="#ff9600" />,
placeholder: 'mobile number',
id: 'mobile',
},
......@@ -110,9 +109,7 @@ export default {
NewYearCaptcha: {
props: {
size: 'large',
prefix: (
<MailOutlined className={styles.prefixIcon} twoToneColor="#ff9600" />
),
prefix: <MailOutlined className={styles.prefixIcon} twoToneColor="#ff9600" />,
placeholder: '请输入短信验证码',
},
rules: [
......
/*
* @Author: 634665781 634665781@qq.com
* @Date: 2022-07-08 14:28:01
* @LastEditors: 634665781 634665781@qq.com
* @LastEditTime: 2022-09-05 17:38:26
* @LastEditors: Please set LastEditors
* @LastEditTime: 2023-01-13 10:01:40
* @FilePath: \CivWeb\src\pages\user\login\index.js
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
import React, { useEffect } from 'react';
import BaseLogin from './template/baseLogin';
import NewYear from './template/newYear';
import baseLoginNewYear from './template/baseLoginNewYear';
import InfoLogin from './template/infoLogin';
import Yulin from './template/yulin';
// import { useParams } from '@wisdom-utils/runtime';
......@@ -23,8 +24,12 @@ import HuhehaoteLogin from './template/project/huhehaote';
import XinganLogin from './template/project/xingan';
import ErlianhaoteLogin from './template/project/erlianhaote';
import YixianLogin from './template/project/yixian';
import LixianLogin from './template/project/lixian';
import DazuLogin from './template/project/dazu';
import PanoramaLogin from './template/panorama';
import { AppInitState } from '../../../render';
const LoginTemplate = {
'新春.html': baseLoginNewYear,
'新春 - 智联.html': NewYear,
'Dark - IOTMultiLogin.html': BaseLogin,
'Dark.html': BaseLogin,
......@@ -42,6 +47,9 @@ const LoginTemplate = {
'项目 - 新干.html': XinganLogin,
'项目 - 二连浩特.html': ErlianhaoteLogin,
'项目 - 易县.html': YixianLogin,
'项目 - 蠡县.html': LixianLogin,
'项目 - 大足.html': DazuLogin,
'全景图.html': PanoramaLogin,
default: BaseLogin,
};
/* eslint-disable */
......
......@@ -98,25 +98,30 @@ class Login {
site: this.getLocalSiteBytoken(token),
'request.preventCache': Date.now(),
ignoreSite: true,
}).then(response => {
if (response && response.code === 0) {
self.globalConfig.userInfo = window?.globalConfig?.transformUserInfo?.(response.data) ?? {};
self.updateConfig && self.updateConfig(self.globalConfig);
self.getUserInfoAndConfig();
} else {
self.logout && self.logout();
if (params.getParams('token')) {
// token免登录失败,回到登录页,防止reload造成死循环
window.location.href = `${window.location.origin}`;
return false;
}
if (self.globalConfig.style === 'ios' && self.globalConfig.loginTemplate === 'IOSCloud.html') {
window.location.href = `${window.location.origin}`;
return false;
})
.then(response => {
if (response && response.code === 0) {
self.globalConfig.userInfo = window?.globalConfig?.transformUserInfo?.(response.data) ?? {};
self.updateConfig && self.updateConfig(self.globalConfig);
self.getUserInfoAndConfig();
} else {
self.logout && self.logout();
if (params.getParams('token')) {
// token免登录失败,回到登录页,防止reload造成死循环
window.location.href = `${window.location.origin}`;
return false;
}
if (self.globalConfig.style === 'ios' && self.globalConfig.loginTemplate === 'IOSCloud.html') {
window.location.href = `${window.location.origin}`;
return false;
}
window.location.reload();
}
window.location.reload();
}
});
})
.catch(error => {
this.handleLoginError();
Logger.log('获取用户配置失败');
});
}
writeLogs() {
......@@ -182,9 +187,8 @@ class Login {
getWebConfig(token, getIndustry) {
const self = this;
// eslint-disable-next-line no-undef
// 获取网站配置的同时,预先获取到mqtt配置,注册进子应用
Promise.all([
Promise.allSettled([
noticeService.getMqttSiteCode({ 'request.preventCache': Date.now() }),
getWebSiteConfig({
client: self.globalConfig.client,
......@@ -193,17 +197,26 @@ class Login {
}),
])
.then(results => {
const res = results[0] || {};
const promise = results[0];
const mqttConfig = {
mqtt_mess: {},
mqtt_path: DEFAULT_MQTT_PATH,
nginxStart: false,
mqtt_IsSSL: true,
ipConfig: {},
};
if (promise.status === 'rejected') {
self.globalConfig = Object.assign(self.globalConfig, {
...mqttConfig,
});
return results;
}
const res = promise.value || {};
if (res && res.code === 0) {
const mqttConfig = {
mqtt_mess: {},
mqtt_path: DEFAULT_MQTT_PATH,
nginxStart: false,
mqtt_IsSSL: true,
};
if (Array.isArray(res.data) && res.data.length > 0) {
if (res.data[0]) {
const data = res.data[0];
mqttConfig.ipConfig = data;
mqttConfig.mqtt_IsSSL = data.IsSSL ? data.IsSSL : false;
mqttConfig.mqtt_mess.site_code = data.SiteCode || self.globalConfig.userInfo.site;
mqttConfig.mqtt_mess.TcpIP = data.TcpIP;
......@@ -237,7 +250,7 @@ class Login {
return results;
})
.then(results => {
const response = results[1] ?? {};
const response = results[1]?.value ?? {};
const result =
response && response.code === SERVICE_INTERFACE_SUCCESS_CODE
? Array.isArray(response.data)
......@@ -489,7 +502,7 @@ class Login {
id: 'wxlogin_container',
appid: 'wxec56ca668e7f9155',
agentid: '1000083',
redirect_uri: encodeURIComponent(window.location.href.replace('#/', '')),
redirect_uri: encodeURIComponent(window.location.href),
href: 'https://mis.panda-water.cn/web4/styles/wx.css',
});
}
......@@ -511,7 +524,7 @@ class Login {
if (url.indexOf('&code') !== -1) {
// 判断是否存在参数
// eslint-disable-next-line no-useless-escape
url = url.replace(/(\&code|#)[^'"]*/, ''); // 去除参数
url = url.replace(/(\&code|#)[^'"]*/, '&code=success'); // 去除参数
window.history.pushState({}, 0, url);
}
self.isSignIn = true;
......@@ -701,11 +714,16 @@ class Login {
self.updateConfig && self.updateConfig(self.globalConfig);
} catch (error) {
console.log(error);
message.error('登录失败');
if (self.goLogin()) {
return false;
}
// self.handleLoginError(failCallback);
}
})
.catch(error => {
this.handleLoginError();
Logger.log('获取用户配置失败');
});
} else {
self.handleLoginError();
......@@ -852,9 +870,12 @@ class Login {
rules = '';
reg = new RegExp(rules);
}
const check = rules && rules !== '' && !reg.test(pwd)
localStorage.setItem('access_token', response.access_token);
localStorage.setItem('password_token', check);
let check = false;
if(rules !== '') check = !reg.test(pwd)
localStorage.setItem('access_token', response.access_token ? response.access_token : '');
if(check) {
localStorage.setItem('password_token', response.access_token ? response.access_token : '');
}
Cookies.set('client', self.globalConfig.client, {
expires: exp / (24 * 60 * 60 * 1000),
path: '/',
......
/* eslint-disable no-empty */
/* eslint-disable react-hooks/exhaustive-deps */
/* eslint-disable no-undef */
import '@wisdom-utils/utils/lib/helpers/format';
import { params } from '@wisdom-utils/utils/lib/helpers';
import React, { forwardRef, useEffect, useRef, useState } from 'react';
......@@ -8,10 +11,7 @@ import LoginAction from './login';
import { defaultApp } from '../../../micro';
const Login = forwardRef((props, _ref) => {
const history = useHistory();
const [action, setAction] = useState(
() =>
new LoginAction(Object.assign({}, props, { history }), () => {}, false),
);
const [action, setAction] = useState(() => new LoginAction(Object.assign({}, props, { history }), () => {}, false));
const [redirect] = useState(() => {
const param = params.getParams('redirect')?.replaceAll(';', '&');
return param ? decodeURIComponent(escape(param)) : null;
......@@ -21,31 +21,39 @@ const Login = forwardRef((props, _ref) => {
const hasLogin = useRef();
useEffect(() => {
action.globalConfig = props.global;
// eslint-disable-next-line no-prototype-builtins
if (props.global && props.global.hasOwnProperty('products') && hasLogin.current !== true) {
hasLogin.current = true;
action.init();
}
}, [action.globalConfig, props.global]);
}, [action, action.globalConfig, props.global]);
useEffect(() => {
action &&
action.events.on('loginSuccess', event => {
// http://127.0.0.1:8080/civbase/civweb4/
// props.updateConfig(Object.assign({}, props.global, {
// homepage: params.getParams('redirect')
// }));
// props.history.push('/' + params.getParams('redirect'))
props.history.push(
`/?client=${props.global.client}`,
props.updateConfig(
Object.assign({}, window.globalConfig, {
redirect,
}),
);
let url = '';
try {
url =
_.isString(redirect) && redirect.replace(new RegExp(/ /g), '').length > 0
? redirect.replace('&skipHome=true', '')
: '';
} catch (error) {}
// props.history.push('/' + params.getParams('redirect'))
props.history.push(`/?client=${props.global.client}`);
// window.share.event.emit('triggerMicro', props.global);
// initMicroApps();
defaultApp(redirect);
defaultApp(url);
});
return () => {
action && action.events && action.events.removeAllListeners('loginSuccess');
}
}, [action, props.global.client, props.global.generateType, props.history]);
return () => {
action && action.events && action.events.removeAllListeners('loginSuccess');
};
}, [action, props.global.client, props.global.generateType, props.history, redirect]);
return <div>{props.children}</div>;
});
......
......@@ -3,12 +3,14 @@ import 'kit_utils/lib/format';
import React, { forwardRef, useEffect, useRef, useState } from 'react';
import { Modal } from 'antd';
// eslint-disable-next-line import/no-unresolved
import classNames from 'classnames';
import { dom } from '@wisdom-utils/utils/lib/helpers';
import { Helmet, HelmetProvider } from 'react-helmet-async';
import { connect } from 'react-redux';
import { useHistory } from '@wisdom-utils/runtime';
import { actionCreators } from '@/containers/App/store';
import Cookies from 'js-cookie';
import defaultSetting from '../../../../../config/defaultSetting';
import LoginAction from '../login';
import styles from '../style.less';
......@@ -32,11 +34,11 @@ const Login = forwardRef((props, _ref) => {
const [type, setType] = useState('Account');
const [visible, setVisible] = useState(false);
const history = useHistory();
const [action, setAction] = useState(
() =>
new LoginAction(Object.assign({}, props, { history }), setVisible, false),
);
const [action, setAction] = useState(() => new LoginAction(Object.assign({}, props, { history }), setVisible, false));
const [showVideo, setShowVideo] = useState(false);
let { ddCode } = props.global;
const loginMode = Cookies.get('loginMode') || null;
if (loginMode && loginMode === 'iotWechat') ddCode = null;
// useEffect(() => {
// action.globalConfig = props.global;
// }, [props.global]);
......@@ -116,22 +118,27 @@ const Login = forwardRef((props, _ref) => {
}, []);
useEffect(() => {
if (videoRef && videoRef.current) {
videoRef.current.addEventListener('ended', function() {
dom.removeClass(loginRef.current, styles.caseHide);
dom.addClass(loginRef.current, styles.loginTimeShow);
videoTimeout = setTimeout(() => {
dom.removeClass(timeRef.current, styles.caseHide);
dom.addClass(timeRef.current, 'animate__fadeIn');
dom.removeClass(loginFormRef.current, styles.caseHide);
dom.addClass(loginFormRef.current, 'animate__fadeInUp');
dom.removeClass(footerRef.current, styles.caseHide);
dom.addClass(footerRef.current, 'animate__slideInUp');
dom.removeClass(titleRef.current, styles.caseHide);
dom.addClass(titleRef.current, 'animte__fadeInUp');
}, 500);
if(ddCode && loginMode === 'qywx') {
setShowVideo(false);
} else {
setShowVideo(true);
setTimeout(() => {
if (videoRef && videoRef.current) {
videoRef.current.addEventListener('ended', function() {
dom.removeClass(loginRef.current, styles.caseHide);
dom.addClass(loginRef.current, styles.loginTimeShow);
videoTimeout = setTimeout(() => {
dom.removeClass(timeRef.current, styles.caseHide);
dom.addClass(timeRef.current, 'animate__fadeIn');
dom.removeClass(loginFormRef.current, styles.caseHide);
dom.addClass(loginFormRef.current, 'animate__fadeInUp');
dom.removeClass(footerRef.current, styles.caseHide);
dom.addClass(footerRef.current, 'animate__slideInUp');
dom.removeClass(titleRef.current, styles.caseHide);
dom.addClass(titleRef.current, 'animte__fadeInUp');
}, 500);
});
}
});
}
......@@ -178,14 +185,14 @@ const Login = forwardRef((props, _ref) => {
<meta name="description" content={props.global.title || defaultSetting.title} />
</Helmet>
<div className={styles.main}>
<video
{showVideo && <video
src={require("../../../../assets/videos/beforPage.mp4") }
className={styles.videLayer}
autoPlay="autoPlay"
muted
playsInline="playsinline"
ref={videoRef}
/>
/>}
<div className={styles.inner}>
<div
className={classNames(styles.loginTime, styles.caseHide)}
......
This diff is collapsed.
......@@ -10,7 +10,7 @@ const useWeCom = props => {
id: props.container || 'wxlogin_container',
appid: props.appid || WECOM_APPID,
agentid: props.agentid || AGENTID_CLOUD,
redirect_uri: props.redirect_uri.replace('#/', '') || encodeURIComponent(window.location.href.replace('#/', '')),
redirect_uri: props.redirect_uri || encodeURIComponent(window.location.href),
href: props.href || 'https://panda-water.cn/web4/styles/wx.css',
self_redirect: false,
state: props.state || 'STATE',
......@@ -42,7 +42,7 @@ const useIOTQRCode = () => {
container: 'wxlogin_container',
appid: WECOM_APPID,
agentid: AGENTID_CLOUD,
redirect_uri: encodeURIComponent(window.location.href.replace('#/', '')), // window.location.href
redirect_uri: encodeURIComponent(window.location.href), // window.location.href
href: 'https://panda-water.cn/web4/styles/wecom.css',
state: rstate,
},
......
......@@ -16,7 +16,7 @@ import useRenderQcode from '../../js/useRenderQcode';
import Account from '../../js/useAccount';
import IotComponent from '../../js/useIOTComponent';
import CloudForm from './cloudForm';
import { initMicroApps } from '../../../../../micro';
import { defaultApp } from '../../../../../micro';
import useTime from '../../js/useTime';
const isRQcodeFunc = loginFunc => {
......@@ -25,8 +25,10 @@ const isRQcodeFunc = loginFunc => {
};
const loginFuncImg = loginFunc => {
if (isRQcodeFunc(loginFunc)) {
// eslint-disable-next-line global-require
return require('@/assets/images/login/cloud/func_pwd.png');
}
// eslint-disable-next-line global-require
return require('@/assets/images/login/cloud/func_rqcode.png');
};
......@@ -48,7 +50,10 @@ const Login = forwardRef((props, _ref) => {
const [visible, setVisible] = useState(false);
const history = useHistory();
const [action, setAction] = useState(() => new LoginAction(Object.assign({}, props, { history }), setVisible, true));
const [showVideo, setShowVideo] = useState(false);
let { ddCode } = props.global;
const loginMode = Cookies.get('loginMode') || null;
if (loginMode && loginMode === 'iotWechat') ddCode = null;
const handleSubmit = values => {
/* eslint-disable */
action &&
......@@ -70,7 +75,8 @@ const Login = forwardRef((props, _ref) => {
props.updateCurrentIndex && props.updateCurrentIndex(0);
props.history.push(`/?client=${props.global.client}`);
// window.share.event.emit('triggerMicro', props.global);
initMicroApps();
// initMicroApps();
defaultApp();
});
action &&
action.events.on('loginError', event => {
......@@ -92,28 +98,34 @@ const Login = forwardRef((props, _ref) => {
let videoTimeout = null;
useEffect(() => {
if (videoRef && videoRef.current) {
videoRef.current.addEventListener('ended', function() {
dom.removeClass(loginRef.current, styles.caseHide);
dom.addClass(loginRef.current, styles.loginTimeShow);
videoTimeout = setTimeout(() => {
dom.removeClass(timeRef.current, styles.caseHide);
dom.addClass(timeRef.current, 'animate__fadeIn');
dom.removeClass(loginFormRef.current, styles.caseHide);
dom.addClass(loginFormRef.current, 'animate__fadeInUp');
dom.removeClass(footerRef.current, styles.caseHide);
dom.addClass(footerRef.current, 'animate__slideInUp');
dom.removeClass(titleRef.current, styles.caseHide);
dom.addClass(titleRef.current, 'animte__fadeInUp');
}, 500);
if(ddCode && loginMode === 'qywx') {
setShowVideo(false);
} else {
setShowVideo(true);
setTimeout(() => {
if (videoRef && videoRef.current) {
videoRef.current.addEventListener('ended', function() {
dom.removeClass(loginRef.current, styles.caseHide);
dom.addClass(loginRef.current, styles.loginTimeShow);
videoTimeout = setTimeout(() => {
dom.removeClass(timeRef.current, styles.caseHide);
dom.addClass(timeRef.current, 'animate__fadeIn');
dom.removeClass(loginFormRef.current, styles.caseHide);
dom.addClass(loginFormRef.current, 'animate__fadeInUp');
dom.removeClass(footerRef.current, styles.caseHide);
dom.addClass(footerRef.current, 'animate__slideInUp');
dom.removeClass(titleRef.current, styles.caseHide);
dom.addClass(titleRef.current, 'animte__fadeInUp');
}, 500);
});
}
});
}
return () => {
videoTimeout && clearTimeout(videoTimeout);
videoRef.current.removeEventListener('ended', () => {});
videoRef.current && videoRef.current.removeEventListener('ended', () => {});
};
}, [videoRef]);
useEffect(() => {
......@@ -164,14 +176,17 @@ const Login = forwardRef((props, _ref) => {
<meta name="description" content={props.global.title || defaultSetting.title} />
</Helmet>
<div className={styles.main}>
<video
src={require('@/assets/videos/beforPage.mp4')}
className={styles.videLayer}
autoPlay="autoPlay"
muted
playsInline="playsinline"
ref={videoRef}
/>
{
showVideo && <video
src={require('@/assets/videos/beforPage.mp4')}
className={styles.videLayer}
autoPlay="autoPlay"
muted
playsInline="playsinline"
ref={videoRef}
/>
}
{/* main content */}
<div className={styles.inner}>
<div className={classNames(styles.loginTime, styles.caseHide)} ref={loginRef}>
......
import 'kit_utils/lib/format';
import React, { forwardRef, useEffect, useRef, useState } from 'react';
import { Modal } from 'antd';
// eslint-disable-next-line import/no-unresolved
import classNames from 'classnames';
import { dom } from '@wisdom-utils/utils/lib/helpers';
import { Helmet, HelmetProvider } from 'react-helmet-async';
import { connect } from 'react-redux';
import { useHistory } from '@wisdom-utils/runtime';
import { actionCreators } from '@/containers/App/store';
import defaultSetting from '../../../../../../config/defaultSetting';
import LoginAction from '../../login';
import styles from './style.less';
import useRenderQcode from '../../js/useRenderQcode';
import Account from '../../js/useAccount';
import IotComponent from '../../js/useIOTComponent';
import { defaultApp } from '../../../../../micro';
import Krpano from '../../components/Krpano';
const PanoBaseLogin = forwardRef((props, _ref) => {
const videoRef = useRef();
const loginRef = useRef();
const timeRef = useRef();
const titleRef = useRef();
const sliVerify = useRef();
const loginFormRef = useRef();
const formRef = useRef(null);
const footerRef = useRef();
const [status, setStatus] = useState('normal');
const [autoLogin, setAutoLogin] = useState(false);
const [submitting, setSubmitting] = useState(false);
const [currentDate, setCurrentDate] = useState({});
const [type, setType] = useState('Account');
const [visible, setVisible] = useState(false);
const history = useHistory();
const [action, setAction] = useState(() => new LoginAction(Object.assign({}, props, { history }), setVisible, false));
let { ddCode } = props.global;
const loginMode =props.loginMode;
const { projectName } = props.loginParams
if (loginMode && loginMode === 'iotWechat') ddCode = null;
// useEffect(() => {
// action.globalConfig = props.global;
// }, [props.global]);
const handleSubmit = values => {
/* eslint-disable */
action &&
(type === 'Account'
? action.loginHandler(
values.userName,
values.password,
null,
autoLogin,
sliVerify,
)
: type === 'Mobile'
? action.phoneLoginFormHandler(values.mobile, values.captcha)
: null);
setSubmitting(true);
props.updateCurrentIndex && props.updateCurrentIndex(-1);
};
useEffect(() => {
// if (props.loginMode === LOGIN_WAY.WeChart) {
action &&
action.events.on('loginSuccess', event => {
setSubmitting(false);
props.updateCurrentIndex && props.updateCurrentIndex(0);
props.history.push(`/?client=${props.global.client}`);
// window.share.event.emit('triggerMicro', props.global);
// initMicroApps();
defaultApp();
});
action &&
action.events.on('loginError', event => {
setVisible(false);
setSubmitting(false);
});
action &&
action.events.on('loginVisible', status => {
setVisible(status);
});
// }
return () => {
action && action.events && action.events.removeAllListeners('loginSuccess');
action && action.events && action.events.removeAllListeners('loginError');
action && action.events && action.events.removeAllListeners('loginVisible');
}
}, [props.loginMode]);
let loginTimeInterval = null;
useEffect(() => {
if (loginTimeInterval)
clearInterval(loginTimeInterval), (loginTimeInterval = null);
loginTimeInterval = setInterval(() => {
const date = new Date();
const weekday = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
const time = `${date.getHours() < 10 ? `0${date.getHours()}` : date.getHours()
}:${date.getMinutes() < 10 ? `0${date.getMinutes()}` : date.getMinutes()
}:${date.getSeconds() < 10 ? `0${date.getSeconds()}` : date.getSeconds()
}`;
setCurrentDate({
time,
dayofweek: weekday[date.getDay()],
date: date.pattern('yyyy/MM/dd'),
});
}, 1000);
return () => {
loginTimeInterval && clearInterval(loginTimeInterval);
};
}, []);
useEffect(() => {
setSubmitting(false);
}, [visible]);
const renderAddons = useRenderQcode(props.global);
const renderPlatform = () => {
const template = props.global.loginTemplate;
const params = {
fromRef: formRef,
type,
setType,
status,
submitting,
autoLogin,
setAutoLogin,
action,
onSubmit: handleSubmit,
loginMode: props.loginMode,
updateLoginMode: props.updateLoginMode,
};
switch (template) {
case 'DarkCloud.html':
case 'Dark.html':
return <Account {...params} />;
case 'Dark - IOTMultiLogin.html':
return <IotComponent {...params} />;
default:
return <Account {...params} />;
}
};
/* eslint-disable */
return (
<HelmetProvider>
<Helmet>
<title>{props.global.title || defaultSetting.title}</title>
<meta name="description" content={props.global.title || defaultSetting.title} />
</Helmet>
<div className={styles.main}>
<div className={styles.inner}>
<div
className={classNames(styles.loginTime)}
ref={loginRef}
>
<img
role="logo"
src={props.global && props.global.transformDevAssetsBaseURL && props.global.transformDevAssetsBaseURL(props.global.logo)}
/>
<div
className={classNames(
styles.titleCase
)}
ref={titleRef}
>
<span className={styles.title}>{props.global.title}</span>
<span className={styles.subtitle}>
{window.globalConfig && window.globalConfig.subtitle}
</span>
</div>
</div>
<div
className={classNames(
styles.timeCase
)}
ref={timeRef}
>
<span className={styles.time}>{currentDate.time}</span>
<span className={styles.dayofweek}>{currentDate.dayofweek}</span>
<span className={styles.date}>{currentDate.date}</span>
</div>
<div
className={classNames(
styles['login-block']
)}
ref={loginFormRef}
>
<div>
<img src="https://panda-water.cn/web4/assets/images/login/dark/login.png" />
</div>
<div className={styles['login-form']}>{renderPlatform()}</div>
</div>
</div>
{projectName ? <div className={styles.krpano}>
<Krpano projectName={projectName} />
</div> : null}
<Modal
centered
visible={visible}
width={340}
footer={null}
closable={false}
bodyStyle={{ padding: '15px' }}
>
<div ref={sliVerify} />
</Modal>
</div>
</HelmetProvider>
);
});
const mapStateToProps = state => ({
global: state.getIn(['global', 'globalConfig']),
loginMode: state.getIn(['global', 'loginMode']),
});
const mapDispatchToProps = dispatch => ({
updateConfig(config) {
dispatch(actionCreators.getConfig(config));
},
createContext(data) {
dispatch(actionCreators.createContext(data));
},
updateLoginMode(mode) {
dispatch(actionCreators.changeLoginMode(mode));
},
updateCurrentIndex(index) {
dispatch(actionCreators.updateCurrentIndex(index));
},
});
export default connect(
mapStateToProps,
mapDispatchToProps,
)((PanoBaseLogin));
import PanoBaseLogin from "./PanoBaseLogin"
import TieShanLogin from "../project/tieshan"
import { useState , useEffect } from "react"
const LoginTemplate = {
"铁山" : TieShanLogin,
default : PanoBaseLogin
}
const Panorama = props => {
const {loginParams , ...reset} = props
const [params, setParams] = useState({})
useEffect(() => {
if(!loginParams) {
setParams({})
} else {
const params = {}
loginParams.map(data => {
const [key , value] = data.split("=")
params[key] = value
})
setParams(params)
}
}, [loginParams]);
const LoginCompontnt = params['projectName'] && LoginTemplate[params['项目']] ? LoginTemplate[params['项目']] :
params['projectName'] ? LoginTemplate["default"] : LoginTemplate['default']
return (<LoginCompontnt {...reset} loginParams = {params}/>)
}
export default Panorama
\ No newline at end of file
@import '~antd/es/style/themes/variable.less';
@userPageLogin-prefix-cls: ~'@{ant-prefix}-pro-pages-user-login';
@keyframes loginTimeShow {
0% {
opacity: 1;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
zoom: 2;
}
50% {
opacity: 1;
top: 28px;
left: 45px;
transform: translate(0, 0);
zoom: 1;
}
60% {
opacity: 1;
left: 45px;
top: 28px;
transform: translate(0, 0);
}
70% {
opacity: 1;
left: 45px;
top: 28px;
transform: translate(0, 0);
}
75% {
opacity: 1;
left: 45px;
top: 28px;
transform: translate(0, 0);
}
100% {
opacity: 1;
left: 45px;
top: 28px;
transform: translate(0, 0);
}
}
.main {
// width: 368px;
margin: 0 auto;
height: 100%;
width: 100%;
@media screen and (max-width: @screen-sm) {
width: 95%;
}
.icon {
margin-left: 16px;
color: rgba(0, 0, 0, 0.2);
font-size: 24px;
vertical-align: middle;
cursor: pointer;
transition: color 0.3s;
&:hover {
color: @primary-color;
}
}
.other {
margin-top: 24px;
line-height: 22px;
text-align: left;
.register {
float: right;
}
}
.videLayer {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
object-fit: fill;
}
.inner {
position: absolute;
width: 100%;
height: 100%;
&.newYearInner {
height: 100%!important;
}
.loginTime {
position: absolute;
top: 25px;
left: 50px;
display: flex;
align-items: center;
justify-content: center;
opacity: 1;
z-index: 100;
&.newYearLoginTime {
position: absolute!important;
top: 28px!important;
left: 45px!important;
display: flex;
align-items: center;
justify-content: center;
z-index: 100;
transform: inherit!important;
}
img[role='logo'] {
height: 40px;
vertical-align: middle;
}
&.loginTimeShow {
animation-name: loginTimeShow;
animation-duration: 1s;
animation-iteration-count: 1;
animation-fill-mode: forwards;
}
.titleCase {
display: flex;
flex-direction: column;
margin: -5px 0 0 20px;
max-width: 570px;
.title,
.subtitle {
font-family: 'Microsoft YaHei';
text-align: left;
overflow-wrap: break-word;
color: #ffffff;
}
.title {
font-size: 28px;
}
.subtitle {
font-size: 12px;
line-height: 1;
}
}
}
.timeCase{
position: absolute;
width: 100%;
z-index: 200;
}
.timeCase {
.time,
.dayofweek,
.date {
position: absolute;
font-family: 'MicrosoftYaHeiUI';
color: rgba(255, 255, 255, 1);
}
.time {
top: 26px;
right: 170px;
font-size: 40px;
margin-right: 10px;
}
.dayofweek {
top: 32px;
right: 125px;
font-size: 16px;
}
.date {
top: 57px;
right: 95px;
font-size: 14px;
}
}
.loginBlockWrapper {
width: 100%;
height: 100%;
background-image: url(https://panda-water.com/web4/assets/images/login/workflow/智联新春背景.png);
background-size: 100% 100%;
background-repeat: no-repeat;
}
.login-block {
width: 800px;
position: absolute;
left: 50%;
top: 50%;
display: flex;
background:rgba(255,255,255,0.5);
transform: translate(-50%,-50%);
z-index: 100;
&.login-newYear-block {
width: 994px!important;
height: 424px!important;
margin-left: -497px!important;
margin-top: -212px!important;
background: url(https://panda-water.com/web4/assets/images/login/workflow/%E6%99%BA%E8%81%94%E6%96%B0%E6%98%A5%E8%83%8C%E6%99%AF%E6%A1%86.png)!important;
//width: 994px;
//height: 424px;
//position: absolute;
//left: 50%;
//top: 50%;
//margin-left: -497px;
//margin-top: -212px;
//display: flex;
background-size: 100% 100%;
background-repeat: no-repeat;
img {
margin-top: 90px;
margin-left: 168px;
}
.login-form {
display: flex;
align-items: center;
margin-left: 32px;
padding: 0;
background: transparent;
margin-top: -36px;
// :global {
// .ant-btn-primary {
// background: #ff9600 !important;
// border-color: #ff9600 !important;
// }
// }
}
}
img {
margin-top: 50px;
margin-bottom: 50px;
margin-left: 30px;
}
.login-form {
padding: 50px 50px 50px;
// background-color: #ffffff;
}
}
}
.footerCase {
width: 100%;
height: 16%;
background: #fff;
position: absolute;
bottom: 0;
left: 0;
.quickMark {
position: absolute;
bottom: 48px;
text-align: center;
width: 100%;
font-size: 12px;
min-height: 71px;
&-single {
text-align: center;
width: 120px;
display: inline-block;
span {
&.Android {
display: block;
background-image: url(https://panda-water.cn/web4/assets/images/login/dark/Android1.png);
width: 26px;
height: 32px;
margin: auto;
margin-bottom: 6px;
}
&.Wechat {
display: block;
background-image: url(https://panda-water.cn/web4/assets/images/login/dark/Wechat1.png);
width: 34px;
height: 32px;
margin: auto;
margin-bottom: 6px;
}
&.iphone {
display: block;
background-image: url(https://panda-water.cn/web4/assets/images/login/dark/iphone1.png);
width: 28px;
height: 32px;
margin: auto;
margin-bottom: 6px;
}
}
}
.Android-single .Android-code,
.iphone-single .iphone-code {
margin: 0px 0px 10px 0px;
width: 150px;
height: 150px;
background: #fff;
padding: 5px;
display: none;
transform: translateX(-15px);
}
.icon-Container {
height: 50px;
cursor: pointer;
}
}
.copyright {
position: absolute;
z-index: 2;
text-align: center;
width: 100%;
bottom: 10px;
font-size: 13pz;
color: #000000;
.frontIcon {
margin-top: -5px;
}
a {
color: #000000;
}
.addons {
display: none;
}
.split {
border-left: 1px solid #000000;
margin: 0 8px;
}
.glyphicon-qrcode {
vertical-align: text-top;
}
}
}
:global {
.antd-pro-login-submit {
width: 100%;
margin-top: 24px;
}
}
.wechatQRcode {
width: 250px;
height: 220px;
margin: 0 15px;
}
.loginDisplay {
width: 100%;
display: flex;
justify-content: space-between;
font-size: 12px;
a {
&:hover {
color: @primary-color;
transition: all 0.3s ease-in-out;
}
}
}
.captcha {
color: @primary-6;
font-weight: 400;
cursor: pointer;
font-size: 12px;
}
}
.krpano {
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
}
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.
/*
* 功能名称: 大足登录页
* 功能路径:
* 功能参数:
*/
import React, { forwardRef, useEffect, useRef, useState } from 'react';
import { Modal, Popover } from 'antd';
import { Helmet, HelmetProvider } from 'react-helmet-async';
import { connect } from 'react-redux';
import { useHistory, withRouter } from '@wisdom-utils/runtime';
import { actionCreators } from '@/containers/App/store';
import classnames from 'classnames';
import moment from 'moment';
import QueueAnim from 'rc-queue-anim';
import defaultSetting from '../../../../../../../config/defaultSetting';
import LoginAction from '../../../login';
import styles from './index.less';
import Account from '../../../js/useAccount';
import { defaultApp } from '../../../../../../micro';
import logo from './images/logo.png';
import loginTitlePng from './images/text.png';
const Login = forwardRef((props, _ref) => {
const sliVerify = useRef();
const videoRef = useRef();
const loginFormRef = useRef();
const formRef = useRef(null);
const [status, setStatus] = useState('normal');
const [show, setShow] = useState(false);
const [autoLogin, setAutoLogin] = useState(false);
const [submitting, setSubmitting] = useState(false);
const [type, setType] = useState('Account');
const [visible, setVisible] = useState(false);
const [videoShow, setVideoShow] = useState(true);
const history = useHistory();
const [action, setAction] = useState(() => new LoginAction(Object.assign({}, props, { history }), setVisible, false));
const [dateObj, setDateObj] = useState({});
const handleSubmit = values => {
/* eslint-disable */
action &&
(type === 'Account'
? action.loginHandler(values.userName, values.password, null, autoLogin, sliVerify)
: type === 'Mobile'
? action.phoneLoginFormHandler(values.mobile, values.captcha)
: null);
setSubmitting(true);
props.updateCurrentIndex && props.updateCurrentIndex(-1);
};
useEffect(() => {
action &&
action.events.on('loginSuccess', event => {
setSubmitting(false);
props.updateCurrentIndex && props.updateCurrentIndex(0);
props.history.push(`/?client=${props.global.client}`);
// window.share.event.emit('triggerMicro', props.global);
// initMicroApps();
defaultApp();
});
action &&
action.events.on('loginError', event => {
setVisible(false);
setSubmitting(false);
});
action &&
action.events.on('loginVisible', status => {
setVisible(status);
});
return () => {
action && action.events && action.events.removeAllListeners('loginSuccess');
action && action.events && action.events.removeAllListeners('loginError');
action && action.events && action.events.removeAllListeners('loginVisible');
};
}, [props.loginMode]);
useEffect(() => {
setSubmitting(false);
}, [visible]);
const renderPlatform = () => {
const template = props.global.loginTemplate;
const params = {
fromRef: formRef,
type,
setType,
status,
submitting,
autoLogin,
setAutoLogin,
action,
onSubmit: handleSubmit,
loginMode: props.loginMode,
updateLoginMode: props.updateLoginMode,
welcome: null,
};
return <Account {...params} />;
};
/* eslint-disable */
const handleWeek = () => {
const weekOfDay = Number(moment().format('E'));
let weekDayName = '';
switch (weekOfDay) {
case 1:
weekDayName = '周一';
break;
case 2:
weekDayName = '周二';
break;
case 3:
weekDayName = '周三';
break;
case 4:
weekDayName = '周四';
break;
case 5:
weekDayName = '周五';
break;
case 6:
weekDayName = '周六';
break;
case 7:
weekDayName = '周日';
break;
default:
weekDayName = '';
}
return weekDayName;
};
const onShow = () => {
if (!show) {
setShow(true);
}
};
const onended = () => {
if (videoShow) {
setVideoShow(false);
}
if (!show) {
setShow(true);
}
};
useEffect(() => {
setTimeout(() => {
if (videoRef && videoRef.current) {
videoRef.current.addEventListener('ended', () => {
onended();
});
}
});
return () => {
videoRef.current && videoRef.current.removeEventListener('ended', () => {});
};
}, [videoRef]);
useEffect(() => {
return () => {};
}, [show]);
useEffect(() => {
const timer = setInterval(() => {
setDateObj({
curTime: moment().format('HH:mm:ss'),
week: handleWeek(),
date: moment().format('YYYY/MM/DD'),
});
}, 1000);
return () => {
clearInterval(timer);
};
}, []);
return (
<HelmetProvider>
<Helmet>
<title>{props.global.title || defaultSetting.title}</title>
<meta name="description" content={props.global.title || defaultSetting.title} />
</Helmet>
<div className={classnames(styles.dazulogin)} onClick={onShow}>
{show ? (
<>
<QueueAnim type="top">
<div key="outwrapper" className={styles.dazu_out_wrapper}>
<div className={styles.dazu_out_logo}>
<img src={logo} alt="logo" />
</div>
<div className={styles.dazu_out_title}>泽足水务</div>
</div>
</QueueAnim>
<QueueAnim type="scale" duration={1000}>
<div key={'innerwrapper'} className={classnames(styles['inner-wrapper'])}>
<div className={styles['inner-center']}>
<div className={styles['welcome-title']}>
<img src={loginTitlePng} alt="login-title" />
</div>
<div className={classnames(styles['inner-bg'], styles['login-part'])} ref={loginFormRef}>
{renderPlatform()}
</div>
</div>
</div>
</QueueAnim>
<div key="loginheader" className={classnames(styles['login-header'])}>
<QueueAnim type="left">
<div key="logintitle" className={styles['left-title']}>
<div>
<img src={logo} alt="logo" />
</div>
<div className={styles['cn-title']}>重庆泽足水务投资建设有限公司综合管理平台</div>
</div>
</QueueAnim>
<QueueAnim type="right">
<div key="logintime" className={styles['right-timebox']}>
<div className={styles['curr-time']}>{dateObj.curTime}</div>
<div className={styles['curr-week-date']}>
<div className={styles['curr-week']}>{dateObj.week}</div>
<div className={styles['curr-date']}>{dateObj.date}</div>
</div>
</div>
</QueueAnim>
</div>
</>
) : null}
{videoShow ? (
<video
src={require('@/assets/videos/dazu.mp4')}
className={styles.videLayer}
autoPlay="autoPlay"
muted
playsInline="playsinline"
ref={videoRef}
/>
) : null}
<Modal centered visible={visible} width={340} footer={null} closable={false} bodyStyle={{ padding: '15px' }}>
<div ref={sliVerify} />
</Modal>
</div>
</HelmetProvider>
);
});
const mapStateToProps = state => ({
global: state.getIn(['global', 'globalConfig']),
loginMode: state.getIn(['global', 'loginMode']),
});
const mapDispatchToProps = dispatch => ({
updateConfig(config) {
dispatch(actionCreators.getConfig(config));
},
createContext(data) {
dispatch(actionCreators.createContext(data));
},
updateLoginMode(mode) {
dispatch(actionCreators.changeLoginMode(mode));
},
updateCurrentIndex(index) {
dispatch(actionCreators.updateCurrentIndex(index));
},
});
export default connect(
mapStateToProps,
mapDispatchToProps,
)(withRouter(Login));
@font-face {
font-family: PingFang SC;
src: url('@/assets/fonts/PingFang.ttf');
}
.dazulogin {
width: 100%;
height: 100%;
background: radial-gradient(#fff 5%, rgba(162, 215, 245, 1) 100%);
position: relative;
min-height: 7.0rem;
overflow: hidden;
display: flex;
justify-content: center;
align-items: center;
.caseHide {
display: none !important;
}
.videLayer {
width: 100vw;
height: 100vh;
position: absolute;
top: 0;
left: 0;
object-fit: fill;
}
.dazu_out_wrapper {
box-sizing: border-box;
width: 500px;
position: absolute;
top: 120px;
left: calc(50% - 250px);
display: flex;
justify-content: center;
align-items: center;
padding: 10px 0;
z-index: 50;
.dazu_out_title {
font-size: 72px;
font-family: PingFang SC;
font-weight: 800;
color: #265499;
line-height: 1;
margin-left: 20px;
}
}
.inner-bg {
width: 100%;
height: 100%;
&>div {
width: 80%;
margin: 10%;
}
}
.inner-wrapper {
position: absolute;
display: flex;
justify-content: center;
align-items: center;
top: 250px;
left: calc(50% - 240px);
z-index: 50;
}
.inner-bg .title {
font-size: 27px;
font-weight: bold;
color: rgba(255, 255, 255, 1);
letter-spacing: 2px;
}
.form-control:focus {
border-color: #66afe9;
outline: 0;
-webkit-box-shadow: none;
box-shadow: none;
}
.inner-center {
position: relative;
width: 480px;
height: 380px;
background: rgba(255, 255, 255, 0.9);
border: 1px solid #FFFFFF;
box-shadow: 1px 1px 12px -3px #22222277;
border-radius: 8px 10px 10px 10px;
}
.welcome-title {
background: linear-gradient(0deg, rgba(9, 128, 238, 1) 0%, rgba(0, 182, 251, 1) 100%);
height: 100px;
border-radius: 8px 8px 0px 0px;
text-align: center;
line-height: 70px;
padding: 16px;
img {
width: 434px;
}
}
.formgroup2 {
display: flex;
align-items: center;
display: flex;
margin: 0px 5.5%;
margin-bottom: 10%;
align-items: center;
margin-bottom: 40px;
}
.APPcodeBox {
width: 100%;
display: flex;
flex-flow: column;
align-items: center;
cursor: pointer;
position: relative;
}
.APPCtext {
font-size: 14px;
font-family: Microsoft YaHei;
font-weight: 400;
color: #000000;
line-height: 30px;
opacity: 0.75;
}
.login-header {
box-sizing: border-box;
width: 100%;
position: absolute;
top: 0;
left: 0;
height: 82px;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 22px;
z-index: 50;
// border-bottom: 1px solid rgba(255, 255, 255, 0.12);
.left-title {
display: flex;
justify-content: flex-start;
align-items: center;
img {
width: 40px;
}
.cn-title {
font-size: 30px;
font-family: PingFang SC;
line-height: 1;
font-weight: 800;
color: #265499;
margin-left: 10px;
}
}
.right-timebox {
display: flex;
justify-content: center;
align-items: center;
height: 60px;
.curr-time {
width: 140px;
font-size: 36px;
font-family: Microsoft YaHei;
font-weight: 300;
color: #265499;
}
.curr-week-date {
margin-left: 10px;
.curr-week {
font-size: 16px;
font-family: Microsoft YaHei;
font-weight: 400;
color: #265499;
}
.curr-date {
font-size: 14px;
font-family: Microsoft YaHei;
font-weight: 400;
color: #265499;
}
}
}
}
.copyright {
position: absolute;
bottom: 7%;
width: 100%;
margin: 0 auto;
font-size: 12px;
font-family: Microsoft YaHei;
font-weight: 400;
color: #F1F6FD;
text-align: center;
}
.qrcode-box {
position: absolute;
bottom: 0;
right: -35px;
width: 35px;
height: 35px;
background: #FFFFFF;
opacity: 0.8;
cursor: pointer;
}
}
& :global {}
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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