Commit 3f5979a2 authored by 邓晓峰's avatar 邓晓峰

chore: publish @wisdom-utils/components

parent 84d46bf1
Pipeline #47275 skipped with stages
......@@ -110,7 +110,7 @@
"@wisdom-map/Map": "^1.0.12-17",
"@wisdom-map/arcgismap": "^1.0.79-17",
"@wisdom-map/util": "^1.0.27-0",
"@wisdom-utils/components": "0.0.31",
"@wisdom-utils/components": "0.0.34",
"@wisdom-utils/runtime": "0.0.15",
"@wisdom-utils/utils": "0.0.77",
"animate.css": "^4.1.1",
......
......@@ -12,12 +12,12 @@ import {
} from 'antd';
import { withRouter } from 'react-router';
import { request } from '@wisdom-utils/utils';
import { FormattedMessage, useIntl } from '@/locales/localeExports';
import { FormattedMessage, useIntl } from '@wisdom-utils/components';
import { appService } from '../../api';
// eslint-disable-next-line import/named
import { API } from '../../api/service/base';
import globalHeader from '../../locales/zh-CN/globalHeader';
import globalHeader from '@wisdom-utils/components/lib/AppLayout/locales/zh-CN/globalHeader';
import styles from './index.less';
// import i18n from '../../utils/share';
......
......@@ -5,8 +5,7 @@ import { connect } from 'react-redux';
import Icon from '@ant-design/icons';
import classNames from 'classnames';
import { useHistory } from '@wisdom-utils/runtime';
import { HeaderSearch } from '@wisdom-utils/components';
import { useIntl } from '@/locales/localeExports';
import { HeaderSearch, useIntl } from '@wisdom-utils/components';
import { actionCreators } from '../../containers/App/store';
import Avatar from './AvatarDropdown';
import styles from './index.less';
......
......@@ -4,8 +4,7 @@ import { message } from 'antd';
import _ from 'lodash';
import { connect } from 'react-redux';
import Icon from '@ant-design/icons';
import { HeaderSearch } from '@wisdom-utils/components';
import { useIntl } from '@/locales/localeExports';
import { HeaderSearch, useIntl } from '@wisdom-utils/components';
import { actionCreators } from '../../containers/App/store';
import Avatar from './AvatarDropdown';
......
import React, { useState, useEffect } from 'react';
import { Tooltip } from 'antd';
import { CheckOutlined } from '@ant-design/icons';
import classNames from 'classnames';
const BlockCheckbox = ({
value,
configType,
onChange,
list = [],
prefixCls,
}) => {
const baseClassName = `${prefixCls}-drawer-block-checkbox`;
const [dom, setDom] = useState([]);
useEffect(() => {
const domList = (list || []).map(item => (
<Tooltip title={item.title} key={item.key}>
<div
className={classNames(
`${baseClassName}-item`,
`${baseClassName}-item-${item.key}`,
`${baseClassName}-${configType}-item`,
)}
onClick={() => onChange(item.key)}
>
<CheckOutlined
className={`${baseClassName}-selectIcon`}
style={{
display: value === item.key ? 'block' : 'none',
}}
/>
</div>
</Tooltip>
));
setDom(domList);
}, [value, list.length, list, baseClassName, configType, onChange]);
return (
<div
className={baseClassName}
style={{
minHeight: 42,
}}
>
{dom}
</div>
);
};
export default BlockCheckbox;
import React from 'react';
import { List, Tooltip, Select, Switch } from 'antd';
import defaultSettings from '../../../config/defaultSetting';
import { getFormatMessage } from './index';
export const renderLayoutSettingItem = item => {
const action = React.cloneElement(item.action, {
disabled: item.disabled,
});
return (
<Tooltip title={item.disabled ? item.disabledReason : ''} placement="left">
<List.Item actions={[action]}>
<span style={{ opacity: item.disabled ? 0.5 : 1 }}>{item.title}</span>
</List.Item>
</Tooltip>
);
};
const LayoutSetting = ({ settings = {}, changeSetting }) => {
const formatMessage = getFormatMessage();
const { contentWidth, splitMenus, fixedHeader, layout, fixSiderbar } =
settings || defaultSettings;
return (
<List
split={false}
dataSource={[
{
title: formatMessage({
id: 'app.setting.content-width',
defaultMessage: 'Content Width',
}),
action: (
<Select
value={contentWidth || 'Fixed'}
size="small"
className="content-width"
onSelect={value => {
changeSetting('contentWidth', value);
}}
style={{ width: 80 }}
>
{layout === 'side' ? null : (
<Select.Option value="Fixed">
{formatMessage({
id: 'app.setting.content-width.fixed',
defaultMessage: 'Fixed',
})}
</Select.Option>
)}
<Select.Option value="Fluid">
{formatMessage({
id: 'app.setting.content-width.fluid',
defaultMessage: 'Fluid',
})}
</Select.Option>
</Select>
),
},
{
title: formatMessage({
id: 'app.setting.fixedheader',
defaultMessage: 'Fixed Header',
}),
action: (
<Switch
size="small"
disabled
className="fixed-header"
checked={!!fixedHeader}
onChange={checked => {
changeSetting('fixedHeader', checked);
}}
/>
),
},
{
title: formatMessage({
id: 'app.setting.fixedsidebar',
defaultMessage: 'Fixed Sidebar',
}),
disabled: layout === 'top',
disabledReason: formatMessage({
id: 'app.setting.fixedsidebar.hint',
defaultMessage: 'Works on Side Menu Layout',
}),
action: (
<Switch
size="small"
disabled
className="fix-siderbar"
checked={!!fixSiderbar}
onChange={checked => changeSetting('fixSiderbar', checked)}
/>
),
},
{
title: formatMessage({ id: 'app.setting.splitMenus' }),
disabled: layout !== 'mix',
action: (
<Switch
size="small"
checked={!!splitMenus}
className="split-menus"
onChange={checked => {
changeSetting('splitMenus', checked);
}}
/>
),
},
]}
renderItem={renderLayoutSettingItem}
/>
);
};
export default LayoutSetting;
import React from 'react';
import { Switch, List } from 'antd';
import { getFormatMessage } from './index';
import { renderLayoutSettingItem } from './LayoutChange';
const RegionalSetting = ({ settings = {}, changeSetting }) => {
const formatMessage = getFormatMessage();
const regionalSetting = ['header', 'footer', 'menu', 'menuHeader'];
return (
<List
split={false}
renderItem={renderLayoutSettingItem}
dataSource={regionalSetting.map((key) => {
return {
title: formatMessage({ id: `app.setting.regionalsettings.${key}` }),
action: (
<Switch
size="small"
className={`regional-${key}`}
checked={settings[`${key}Render`] || settings[`${key}Render`] === undefined}
onChange={(checked) =>
changeSetting(`${key}Render`, checked === true ? undefined : false)
}
/>
),
};
})}
/>
);
};
export default RegionalSetting;
\ No newline at end of file
import './ThemeColor.less';
import { CheckOutlined } from '@ant-design/icons';
import { Tooltip } from 'antd';
import React from 'react';
import { genThemeToString } from './utils';
const Tag = React.forwardRef(({ color, check, ...rest }, ref) => (
<div {...rest} style={{ backgroundColor: color }} ref={ref}>
{check ? <CheckOutlined /> : ''}
</div>
));
const ThemeColor = ( { colors, value, onChange, formatMessage }, ref) => {
const colorList = colors || [];
if (colorList.length < 1) {
return null;
}
return (
<div className="theme-color" ref={ref}>
<div className="theme-color-content">
{colorList.map(({ key, color }) => {
const themeKey = genThemeToString(color);
return (
<Tooltip
key={color}
title={
themeKey
? formatMessage({
id: `app.setting.themecolor.${themeKey}`,
})
: key
}
>
<Tag
className="theme-color-block"
color={color}
check={value === key || genThemeToString(value) === key}
onClick={() => onChange && onChange(key)}
/>
</Tooltip>
);
})}
</div>
</div>
);
};
export default React.forwardRef(ThemeColor);
\ No newline at end of file
@import './index.less';
.@{ant-pro-setting-drawer}-content {
.theme-color {
margin-top: 16px;
overflow: hidden;
.theme-color-title {
margin-bottom: 12px;
font-size: 14px;
line-height: 22px;
}
.theme-color-block {
float: left;
width: 20px;
height: 20px;
margin-top: 8px;
margin-right: 8px;
color: #fff;
font-weight: bold;
text-align: center;
border-radius: 2px;
cursor: pointer;
}
}
}
\ No newline at end of file
import './index.less';
import { isBrowser } from '@ant-design/pro-utils';
import { useUrlSearchParams } from '@umijs/use-params';
import { Divider, Drawer, message } from 'antd';
import React, { useState, useEffect, useRef } from 'react';
import useMergedState from 'rc-util/lib/hooks/useMergedState';
import merge from 'lodash.merge';
import omit from 'omit.js';
import defaultSettings from '../../../config/defaultSetting';
import BlockCheckbox from './BlockCheckbox';
import ThemeColor from './ThemeColor';
import getLocales, { getLanguage } from './locales';
import { genStringToTheme } from './utils';
import LayoutSetting, { renderLayoutSettingItem } from './LayoutChange';
import RegionalSetting from './RegionalChange';
const Body = ({ children, prefixCls, title }) => (
<div style={{ marginBottom: 24 }}>
<h3 className={`${prefixCls}-drawer-title`}>{title}</h3>
{children}
</div>
);
const getDifferentSetting = (state)=> {
const stateObj = {};
Object.keys(state).forEach((key) => {
if (state[key] !== defaultSettings[key] && key !== 'collapse') {
stateObj[key] = state[key];
} else {
stateObj[key] = undefined;
}
if (key.includes('Render')) {
stateObj[key] = state[key] === false ? false : undefined;
}
});
stateObj.menu = undefined;
return stateObj;
};
export const getFormatMessage = () => {
const formatMessage = ({ id }) => {
const locales = getLocales();
return locales[id];
};
return formatMessage;
};
const updateTheme = (dark, color, publicPath = '/theme', hideMessageLoading) => {
if (typeof window === 'undefined' || !(window).umi_plugin_ant_themeVar) {
return;
}
const formatMessage = getFormatMessage();
let hide = () => null;
if (!hideMessageLoading) {
hide = message.loading(
formatMessage({
id: 'app.setting.loading',
defaultMessage: '正在加载主题',
}),
);
}
const href = dark ? `${publicPath}/dark` : `${publicPath}/`;
// 如果是 dark,并且是 color=daybreak,无需进行拼接
let colorFileName =
dark && color ? `-${encodeURIComponent(color)}` : encodeURIComponent(color || '');
if (color === 'daybreak' && dark) {
colorFileName = '';
}
const dom = document.getElementById('theme-style');
// 如果这两个都是空
if (!href && !colorFileName) {
if (dom) {
dom.remove();
localStorage.removeItem('site-theme');
}
return;
}
const url = `${href}${colorFileName || ''}.css`;
if (dom) {
dom.onload = () => {
window.setTimeout(() => {
hide();
});
};
console.log(url.replace(/3020/, 8080))
dom.href = url.replace(/3020/, 8080);
} else {
const style = document.createElement('link');
style.type = 'text/css';
style.rel = 'stylesheet';
style.id = 'theme-style';
style.onload = () => {
window.setTimeout(() => {
hide();
});
};
console.log(url.replace(/3020/, 8080))
style.href = url.replace(/3020/, 8080);
if (document.body.append) {
document.body.append(style);
} else {
document.body.appendChild(style);
}
}
localStorage.setItem('site-theme', dark ? 'dark' : 'light');
};
const getThemeList = (settings) => {
const formatMessage = getFormatMessage();
const list = (window).umi_plugin_ant_themeVar || [];
const themeList = [
// {
// key: 'light',
// title: formatMessage({ id: 'app.setting.pagestyle.light' }),
// },
];
const darkColorList = [
{
key: 'daybreak',
color: '#1890ff',
theme: 'dark',
},
];
const lightColorList = [
// {
// key: 'daybreak',
// color: '#1890ff',
// theme: 'dark',
// },
];
if (settings.layout !== 'mix') {
themeList.push({
key: 'dark',
title: formatMessage({
id: 'app.setting.pagestyle.dark',
defaultMessage: '',
}),
});
}
// if (list.find((item) => item.theme === 'dark')) {
// themeList.push({
// key: 'realDark',
// title: formatMessage({
// id: 'app.setting.pagestyle.dark',
// defaultMessage: '',
// }),
// });
// }
// insert theme color List
list.forEach((item) => {
const color = (item.modifyVars || {})['@primary-color'];
if (item.theme === 'dark' && color) {
darkColorList.push({
color,
...item,
});
}
if (!item.theme || item.theme === 'light') {
lightColorList.push({
color,
...item,
});
}
});
return {
colorList: {
dark: darkColorList,
light: lightColorList,
},
themeList,
};
};
/**
* 初始化的时候需要做的工作
*
* @param param0
*/
const initState = (urlParams, settings, onSettingChange, publicPath) => {
if (!isBrowser()) return;
let loadedStyle = false;
const replaceSetting = {};
// Object.keys(urlParams).forEach((key) => {
// if (defaultSettings[key] || defaultSettings[key] === undefined) {
// replaceSetting[key] = urlParams[key];
// }
// });
// 同步数据到外部
onSettingChange?.(merge({}, settings, replaceSetting));
// 如果 url 中设置主题,进行一次加载。
if (defaultSettings.navTheme !== urlParams.navTheme && urlParams.navTheme) {
updateTheme(settings.navTheme === 'realDark', urlParams.primaryColor, publicPath, true);
loadedStyle = true;
}
if (loadedStyle) {
return;
}
// 如果 url 中没有设置主题,并且 url 中的没有加载,进行一次加载。
if (defaultSettings.navTheme !== settings.navTheme && settings.navTheme) {
updateTheme(settings.navTheme === 'realDark', settings.primaryColor, publicPath, true);
}
};
const getParamsFromUrl = (urlParams, settings) => {
if (!isBrowser()) return defaultSettings;
return {
...defaultSettings,
...(settings || {}),
...urlParams,
};
};
const genCopySettingJson = (settingState) =>
JSON.stringify(
omit(
{
...settingState,
primaryColor: genStringToTheme(settingState.primaryColor),
},
['colorWeak'],
),
null,
2,
);
/**
* 可视化配置组件
*
* @param props
*/
const SettingDrawer = (props) => {
const {
settings: propsSettings = undefined,
hideLoading = false,
hideColors,
hideHintAlert,
hideCopyButton,
getContainer,
onSettingChange,
prefixCls = 'panda-console-base-pro',
pathname = window.location.pathname,
disableUrlParams = false,
} = props;
const firstRender = useRef(true);
const [show, setShow] = useMergedState(false, {
value: props.collapse,
onChange: props.onCollapseChange,
});
const [language, setLanguage] = useState(getLanguage());
const [urlParams, setUrlParams] = useUrlSearchParams({});
const [settingState, setSettingState] = useMergedState(
() => getParamsFromUrl(urlParams, propsSettings),
{
value: propsSettings,
onChange: onSettingChange,
},
);
const preStateRef = useRef(settingState);
const { navTheme, primaryColor, layout, colorWeak } = settingState || {};
useEffect(() => {
// 语言修改,这个是和 locale 是配置起来的
const onLanguageChange = () => {
if (language !== getLanguage()) {
setLanguage(getLanguage());
}
};
/** 如果不是浏览器 都没有必要做了 */
if (!isBrowser()) return () => null;
initState(
getParamsFromUrl(urlParams, propsSettings),
settingState,
setSettingState,
props.publicPath,
);
window.document.addEventListener('languagechange', onLanguageChange, {
passive: true,
});
return () => window.document.removeEventListener('languagechange', onLanguageChange);
}, []);
/**
* 修改设置
*
* @param key
* @param value
* @param hideMessageLoading
*/
const changeSetting = (key, value, hideMessageLoading) => {
const nextState = { ...preStateRef.current };
nextState[key] = value;
if (key === 'navTheme') {
updateTheme(value === 'realDark', undefined, props.publicPath, !!hideMessageLoading);
nextState.primaryColor = 'daybreak';
}
if (key === 'primaryColor') {
updateTheme(
nextState.navTheme === 'realDark',
value === 'daybreak' ? '' : value,
props.publicPath,
!!hideMessageLoading,
);
}
if (key === 'layout') {
nextState.contentWidth = value === 'top' ? 'Fixed' : 'Fluid';
}
if (key === 'layout' && value !== 'mix') {
nextState.splitMenus = false;
}
if (key === 'layout' && value === 'mix') {
nextState.navTheme = 'light';
}
if (key === 'colorWeak' && value === true) {
const dom = document.querySelector('body');
if (dom) {
dom.dataset.prosettingdrawer = dom.style.filter;
dom.style.filter = 'invert(80%)';
}
}
if (key === 'colorWeak' && value === false) {
const dom = document.querySelector('body');
if (dom) {
dom.style.filter = dom.dataset.prosettingdrawer || 'none';
delete dom.dataset.prosettingdrawer;
}
}
preStateRef.current = nextState;
setSettingState(nextState);
};
const formatMessage = getFormatMessage();
const themeList = getThemeList(settingState);
useEffect(() => {
/** 如果不是浏览器 都没有必要做了 */
if (!isBrowser()) return;
if (disableUrlParams) return;
if (firstRender.current) {
firstRender.current = false;
return;
}
// const diffParams = getDifferentSetting({ ...urlParams, ...settingState });
// setUrlParams(diffParams);
}, [setUrlParams, settingState, urlParams, pathname, disableUrlParams]);
window.share.event.on('event:theme', () => {
setShow(!show);
});
const baseClassName = `${prefixCls}-setting`;
return (
<Drawer
visible={show}
width={300}
onClose={() => setShow(false)}
placement="right"
getContainer={getContainer}
// handler={
// <div className={`${baseClassName}-drawer-handle`} onClick={() => setShow(!show)}>
// {show ? (
// <CloseOutlined
// style={{
// color: '#fff',
// fontSize: 20,
// }}
// />
// ) : (
// <SettingOutlined
// style={{
// color: '#fff',
// fontSize: 20,
// }}
// />
// )}
// </div>
// }
style={{
zIndex: 999,
}}
>
<div className={`${baseClassName}-drawer-content`}>
<Body
title={formatMessage({
id: 'app.setting.pagestyle',
defaultMessage: 'Page style setting',
})}
prefixCls={baseClassName}
>
<BlockCheckbox
prefixCls={baseClassName}
list={themeList.themeList}
value={navTheme}
configType="theme"
key="navTheme"
onChange={(value) => changeSetting('navTheme', value, hideLoading)}
/>
</Body>
<Body
title={formatMessage({
id: 'app.setting.themecolor',
defaultMessage: 'Theme color',
})}
prefixCls={baseClassName}
>
<ThemeColor
value={primaryColor}
colors={
hideColors ? [] : themeList.colorList[navTheme === 'realDark' ? 'dark' : 'light']
}
formatMessage={formatMessage}
onChange={(color) => changeSetting('primaryColor', color, hideLoading)}
/>
</Body>
<Divider />
<Body prefixCls={baseClassName} title={formatMessage({ id: 'app.setting.navigationmode' })}>
<BlockCheckbox
prefixCls={baseClassName}
value={layout}
key="layout"
configType="layout"
list={[
// {
// key: 'side',
// title: formatMessage({ id: 'app.setting.sidemenu' }),
// },
// {
// key: 'top',
// title: formatMessage({ id: 'app.setting.topmenu' }),
// },
{
key: 'mix',
title: formatMessage({ id: 'app.setting.mixmenu' }),
},
]}
onChange={(value) => changeSetting('layout', value, hideLoading)}
/>
</Body>
<LayoutSetting settings={settingState} changeSetting={changeSetting} />
<Divider />
{/* <Body
prefixCls={baseClassName}
title={formatMessage({ id: 'app.setting.regionalsettings' })}
>
<RegionalSetting settings={settingState} changeSetting={changeSetting} />
</Body>
<Divider /> */}
{/* <Body prefixCls={baseClassName} title={formatMessage({ id: 'app.setting.othersettings' })}>
<List
split={false}
renderItem={renderLayoutSettingItem}
dataSource={[
{
title: formatMessage({ id: 'app.setting.weakmode' }),
action: (
<Switch
size="small"
className="color-weak"
checked={!!colorWeak}
onChange={(checked) => {
changeSetting('colorWeak', checked);
}}
/>
),
},
]}
/>
</Body> */}
{/* {hideHintAlert && hideCopyButton ? null : <Divider />}
{hideHintAlert ? null : (
<Alert
type="warning"
message={formatMessage({
id: 'app.setting.production.hint',
})}
icon={<NotificationOutlined />}
showIcon
style={{ marginBottom: 16 }}
/>
)} */}
{/* {hideCopyButton ? null : (
<Button
block
icon={<CopyOutlined />}
style={{ marginBottom: 24 }}
onClick={async () => {
try {
await navigator.clipboard.writeText(genCopySettingJson(settingState));
message.success(formatMessage({ id: 'app.setting.copyinfo' }));
} catch (error) {
// console.log(error);
}
}}
>
{formatMessage({ id: 'app.setting.copy' })}
</Button>
)} */}
</div>
</Drawer>
);
};
export default SettingDrawer;
@import '~antd/es/style/themes/default.less';
@ant-pro-setting-drawer: ~'@{ant-prefix}-setting-drawer';
.@{ant-pro-setting-drawer} {
&-content {
position: relative;
min-height: 100%;
.@{ant-prefix}-list-item {
span {
flex: 1;
}
}
}
&-block-checkbox {
display: flex;
&-item {
position: relative;
width: 44px;
height: 36px;
margin-right: 16px;
overflow: hidden;
background-color: #f0f2f5;
border-radius: 4px;
box-shadow: 0 1px 2.5px 0 rgba(0, 0, 0, 0.18);
cursor: pointer;
&::before {
position: absolute;
top: 0;
left: 0;
width: 33%;
height: 100%;
background-color: #fff;
content: '';
}
&::after {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 25%;
background-color: #fff;
content: '';
}
&-realDark {
background-color: fade(@menu-dark-bg, 85%);
&::before {
background-color: fade(@menu-dark-bg, 65%);
content: '';
}
&::after {
background-color: fade(@menu-dark-bg, 85%);
}
}
// 亮色主题
&-light {
&::before {
background-color: @white;
content: '';
}
&::after {
background-color: @white;
}
}
// 暗色主题
&-dark,
// 侧边菜单布局
&-side {
&::before {
z-index: 1;
background-color: @menu-dark-bg;
content: '';
}
&::after {
background-color: @white;
}
}
// 顶部菜单布局
&-top {
&::before {
background-color: transparent;
content: '';
}
&::after {
background-color: @menu-dark-bg;
}
}
// 顶部菜单布局
&-mix {
&::before {
background-color: @white;
content: '';
}
&::after {
background-color: @menu-dark-bg;
}
}
}
&-selectIcon {
position: absolute;
right: 6px;
bottom: 4px;
color: @primary-color;
font-weight: bold;
font-size: 14px;
pointer-events: none;
.action {
color: @primary-color;
}
}
}
&-color_block {
display: inline-block;
width: 38px;
height: 22px;
margin: 4px;
margin-right: 12px;
vertical-align: middle;
border-radius: 4px;
cursor: pointer;
}
&-title {
margin-bottom: 12px;
color: @heading-color;
font-size: 14px;
line-height: 22px;
}
&-handle {
position: absolute;
top: 240px;
right: 300px;
z-index: 0;
display: flex;
align-items: center;
justify-content: center;
width: 48px;
height: 48px;
font-size: 16px;
text-align: center;
background: @primary-color;
border-radius: 4px 0 0 4px;
cursor: pointer;
pointer-events: auto;
}
&-production-hint {
margin-top: 16px;
font-size: 12px;
}
}
import { isBrowser } from '@ant-design/pro-utils';
import zhLocal from './zh-CN';
const locales = {
'zh-CN': zhLocal,
};
const getLanguage = () => {
if (!isBrowser()) return 'zh-CN';
const lang = window.localStorage.getItem('umi_locale');
return lang || (window).g_locale || navigator.language;
};
export { getLanguage };
export default ()=> {
const gLocale = getLanguage();
if (locales[gLocale]) {
return locales[gLocale];
}
return locales['zh-CN'];
};
import settingDrawer from './zh-CN/settingDrawer';
export default {
...settingDrawer,
};
\ No newline at end of file
export default {
'app.setting.pagestyle': '整体风格设置',
'app.setting.pagestyle.dark': '暗色菜单风格',
'app.setting.pagestyle.light': '亮色菜单风格',
'app.setting.content-width': '内容区域宽度',
'app.setting.content-width.fixed': '定宽',
'app.setting.content-width.fluid': '流式',
'app.setting.themecolor': '主题色',
'app.setting.themecolor.dust': '薄暮',
'app.setting.themecolor.volcano': '火山',
'app.setting.themecolor.sunset': '日暮',
'app.setting.themecolor.cyan': '明青',
'app.setting.themecolor.green': '极光绿',
'app.setting.themecolor.daybreak': '拂晓蓝(默认)',
'app.setting.themecolor.geekblue': '极客蓝',
'app.setting.themecolor.purple': '酱紫',
'app.setting.navigationmode': '导航模式',
'app.setting.regionalsettings': '内容区域',
'app.setting.regionalsettings.header': '顶栏',
'app.setting.regionalsettings.menu': '菜单',
'app.setting.regionalsettings.footer': '页脚',
'app.setting.regionalsettings.menuHeader': '菜单头',
'app.setting.sidemenu': '侧边菜单布局',
'app.setting.topmenu': '顶部菜单布局',
'app.setting.mixmenu': '混合菜单布局',
'app.setting.splitMenus': '自动分割菜单',
'app.setting.fixedheader': '固定 Header',
'app.setting.fixedsidebar': '固定侧边菜单',
'app.setting.fixedsidebar.hint': '侧边菜单布局时可配置',
'app.setting.hideheader': '下滑时隐藏 Header',
'app.setting.hideheader.hint': '固定 Header 时可配置',
'app.setting.othersettings': '其他设置',
'app.setting.weakmode': '色弱模式',
'app.setting.copy': '拷贝设置',
'app.setting.loading': '正在加载主题',
'app.setting.copyinfo': '拷贝成功,请到 src/defaultSettings.js 中替换默认配置',
'app.setting.production.hint':
'配置栏只在开发环境用于预览,生产环境不会展现,请拷贝后手动修改配置文件',
};
\ No newline at end of file
export const getOpenKeysFromMenuData = (menuData) => {
return (menuData || []).reduce((pre, item) => {
if(item.key) {
pre.push(item.key);
}
if(item.children) {
const newArray = pre.concat(getOpenKeysFromMenuData(item.children) || []);
return newArray;
}
return pre;
}, []);
};
const themeConfig = {
daybreak: 'daybreak',
'#1890ff': 'daybreak',
'#F5222D': 'dust',
'#FA541C': 'volcano',
'#FAAD14': 'sunset',
'#13C2C2': 'cyan',
'#52C41A': 'green',
'#2F54EB': 'geekblue',
'#722ED1': 'purple',
};
const invertKeyValues = (obj) => {
Object.keys(obj).reduce((acc, key) => {
acc[obj[key]] = key;
return acc;
}, {})
}
export function genThemeToString(val) {
return val && themeConfig[val] ? themeConfig[val] : undefined;
};
export function genStringToTheme(val) {
const stringConfig = invertKeyValues(themeConfig);
return val && stringConfig[val] ? stringConfig[val] : val;
};
// eslint-disable-next-line import/extensions
// import arcgisConfig from '@wisdom-map/arcgismap/lib/arcgisapi/4.20/@arcgis/core/config';
import React from 'react';
// eslint-disable-next-line import/extensions
import { ArcGISMap as MapComponent } from '@wisdom-map/arcgismap';
......@@ -8,8 +7,6 @@ import { ArcGISMap as MapComponent } from '@wisdom-map/arcgismap';
// eslint-disable-next-line react/prefer-stateless-function
export default class ArcGISMap extends React.Component {
render() {
// arcgisConfig.assetsPath = `${window.location.origin
// }/${pkg.name.toLocaleLowerCase()}/assets`;
return <MapComponent {...this.props} />;
}
}
import 'swagger-ui-react/swagger-ui.css';
import React from 'react';
import { Card } from 'antd';
// import SwaggerUI from 'swagger-ui-react';
export default () => (
<Card>
{/* <SwaggerUI url={`${window.location.origin}/civ-plugins_openapi.json`} /> */}
</Card>
);
......@@ -22,8 +22,8 @@ import {
import ProLayout, { getPageTitle } from '@ant-design/pro-layout';
import { getMatchMenu } from '@umijs/route-utils';
import { useHistory } from '@wisdom-utils/runtime';
import RightContent from '@/components/GlobalHeader/RightContent';
import { Panel } from '@wisdom-utils/components';
import RightContent from '@/components/GlobalHeader/RightContent';
import { actionCreators } from '@/containers/App/store';
import Authorized from '@/utils/Authorized';
import { findPathByLeafId, getBaseName } from '@/utils/utils';
......
......@@ -45,7 +45,7 @@ import SecurityLayout from './SecurityLayout';
import Site from './Site';
import styles from './UserLayout.less';
import layoutStyles from './BasicLayout.less';
import SettingDrawer from '../components/SettingDrawer';
// eslint-disable-next-line import/extensions
const { TabPane } = Tabs;
const { layout: defaultSetting } = require('../../config/config');
// import Login from '../pages/user/login/login';
......@@ -718,7 +718,7 @@ const BasicLayout = props => {
</div>
<PageContainer style={{paddingTop: '0px', height: '100%'}}>
{
renderRoutes(props.route.routes)
renderRoutes(props.route.routes, this.props.global)
}
{
......@@ -742,7 +742,7 @@ const BasicLayout = props => {
): (
<PageContainer style={{paddingTop: '0px', height: '100%'}}>
{
renderRoutes(props.route.routes)
renderRoutes(props.route.routes, this.props.global)
}
{
......
......@@ -2,4 +2,4 @@ import React from 'react';
const Layout = ({ children }) => <>{children}</>;
export default Layout;
\ No newline at end of file
export default Layout;
......@@ -7,8 +7,8 @@ import Cookies from 'js-cookie';
import { cityJson } from '@wisdom-utils/utils';
import { appService } from '../api';
import { CitySelector } from '@wisdom-utils/components';
import { appService } from '../api';
import Login from '../pages/user/login/login';
import styles from './UserLayout.less';
import { initMicroApps } from '@/micro';
......
......@@ -34,7 +34,7 @@ const UserLayout = props => {
<div className={styles.container}>
<div className={styles.content}>
{renderRoutes(route.routes)}
{renderRoutes(route.routes, props.global)}
{props.children}
</div>
{/* <DefaultFooter links={[]} copyright="Copyright © 熊猫智慧水务 2020 All Rights Reserved 沪ICP备11036640-1"/> */}
......@@ -42,10 +42,7 @@ const UserLayout = props => {
</HelmetProvider>
);
};
const mapStateToProps = state => ({
global: state.getIn(['global', 'globalConfig']),
});
export default connect(
mapStateToProps,
null,
)(UserLayout);
// const mapStateToProps = state => ({
// global: state.getIn(['global', 'globalConfig']),
// });
export default UserLayout;
// import 'moment/locale/zh-cn';
import 'moment/dist/locale/zh-cn';
import React from 'react';
import { ConfigProvider } from 'antd';
import moment from 'moment';
import {
getDirection,
getIntl,
getLocale,
localeInfo,
RawIntlProvider,
setIntl,
} from './localeExports';
export const LANG_CHANGE_EVENT = Symbol('LANG_CHANGE');
export function onCreate() {
const locale = getLocale();
if (moment.locale) {
moment.locale(
(localeInfo[locale] && localeInfo[locale].momentLocale) || '',
);
}
setIntl(locale);
}
export const LocaleContainer = props => {
const [locale, setLocale] = React.useState(() => getLocale());
const [intl, setContainerIntl] = React.useState(() => getIntl(locale, true));
const defaultAntdLocale = {};
const direcition = getDirection();
return (
<ConfigProvider
direction={direcition}
locale={
(localeInfo[locale] && localeInfo[locale].antd.default) || defaultAntdLocale
}
>
<RawIntlProvider value={intl}>{props.children}</RawIntlProvider>
</ConfigProvider>
);
};
import { createIntl } from 'react-intl';
import zhCN from './zh-CN';
/* eslint-disable */
export {
createIntl,
createIntlCache,
defineMessages,
FormattedDate,
FormattedDateParts,
FormattedDisplayName,
FormattedHTMLMessage,
FormattedList,
FormattedMessage,
FormattedNumber,
FormattedNumberParts,
FormattedPlural,
FormattedRelativeTime,
FormattedTime,
FormattedTimeParts,
injectIntl,
IntlContext,
IntlProvider,
RawIntlProvider,
useIntl,
} from 'react-intl';
let g_intl;
const useLocalStorage = true;
export const localeInfo = {
'zh-CN': {
messages: {
...zhCN,
},
locale: 'zh-CN',
antd: {
...require('antd/es/locale/zh_CN'),
},
momentLocale: 'zh-cn',
},
};
/**
* 增加一个新的国际化语言
* @param name 语言的 key
* @param messages 对应的枚举对象
* @param extraLocale momentLocale, antd 国际化
*/
export const addLocale = (name, messages, extraLocales) => {
if (!name) {
return;
}
// 可以合并
const mergeMessages =
localeInfo[name] && localeInfo[name].messages
? Object.assign({}, localeInfo[name].messages, messages)
: messages;
const { momentLocale, antd } = extraLocales || {};
localeInfo[name] = {
messages: mergeMessages,
locale: name.split('-').join('-'),
momentLocale,
antd,
};
};
export const getIntl = (locale, changeIntl) => {
// 如果全局的 g_intl 存在,且不是 setIntl 调用
if (g_intl && !changeIntl && !locale) {
return g_intl;
}
// 如果存在于 localeInfo 中
if (locale && localeInfo[locale]) {
return createIntl(localeInfo[locale]);
}
// 不存在需要一个报错提醒
// warning(
// !locale||!!localeInfo[locale],
// `The current popular language does not exist, please check the locales folder!`,
// );
// 使用 zh-CN
if (localeInfo['zh-CN']) return createIntl(localeInfo['zh-CN']);
// 如果还没有,返回一个空的
return createIntl({
locale: 'zh-CN',
messages: {},
});
};
export const setIntl = locale => {
g_intl = getIntl(locale, true);
};
/**
* 获取当前选择的语言
* @returns string
*/
export const getLocale = () => {
// please clear localStorage if you change the baseSeparator config
// because changing will break the app
const lang =
typeof localStorage !== 'undefined' && useLocalStorage
? window.localStorage.getItem('umi_locale')
: '';
// support baseNavigator, default true
let browserLang;
const isNavigatorLanguageValid =
typeof navigator !== 'undefined' && typeof navigator.language === 'string';
browserLang = isNavigatorLanguageValid
? navigator.language.split('-').join('-')
: '';
return lang || browserLang || 'zh-CN';
};
/**
* 获取当前选择的方向
* @returns string
*/
export const getDirection = () => {
const lang = getLocale();
// array with all prefixs for rtl langueges ex: ar-EG , he-IL
const rtlLangs = ['he', 'ar', 'fa', 'ku'];
const direction = rtlLangs.filter(lng => lang.startsWith(lng)).length
? 'rtl'
: 'ltr';
return direction;
};
/**
* 切换语言
* @param lang 语言的 key
* @param realReload 是否刷新页面,默认刷新
* @returns string
*/
export const setLocale = (lang, realReload) => {
const localeExp = new RegExp(`^([a-z]{2})-?([A-Z]{2})?$`);
if (lang !== undefined && !localeExp.test(lang)) {
// for reset when lang === undefined
throw new Error('setLocale lang format error');
}
if (getLocale() !== lang) {
if (typeof window.localStorage !== 'undefined' && useLocalStorage) {
window.localStorage.setItem('umi_locale', lang || '');
}
setIntl(lang);
if (realReload) {
window.location.reload();
} else {
// event.emit(LANG_CHANGE_EVENT, lang);
// chrome 不支持这个事件。所以人肉触发一下
if (window.dispatchEvent) {
const event = new Event('languagechange');
window.dispatchEvent(event);
}
}
}
};
let firstWaring = true;
/**
* intl.formatMessage 的语法糖
* @deprecated 使用此 api 会造成切换语言的时候无法自动刷新,请使用 useIntl 或 injectIntl
* @param descriptor { id : string, defaultMessage : string }
* @param values { [key:string] : string }
* @returns string
*/
export const formatMessage = (descriptor, values) => {
if (firstWaring) {
warning(
false,
`Using this API will cause automatic refresh when switching languages, please use useIntl or injectIntl.
使用此 api 会造成切换语言的时候无法自动刷新,请使用 useIntl 或 injectIntl。
http://j.mp/37Fkd5Q
`,
);
firstWaring = false;
}
return g_intl.formatMessage(descriptor, values);
};
import globalHeader from './zh-CN/globalHeader';
import pages from './zh-CN/pages';
import pwa from './zh-CN/pwa';
import settings from './zh-CN/settings';
const packs = {
...globalHeader,
...pwa,
...pages,
...settings,
};
export default packs;
// function registerLanguge() {
// Object.keys(packs).forEach(pack => {
// const script = document.createElement('script');
// script.type = 'json/i18n';
// script.innerHTML = JSON.stringify(packs[pack]);
// document.head.appendChild(script);
// });
// }
// registerLanguge();
export default {
'component.noticeIcon.clear': '清空',
'component.noticeIcon.cleared': '清空了',
'component.noticeIcon.allClear': '暂无新通知',
'component.noticeIcon.empty': '暂无数据',
'component.noticeIcon.view-more': '查看更多',
'component.noticeIcon.title': '通知',
'component.noticeIocn.allClear': '你已查看所有通知',
'component.noticeIcon.modal.alarm.title': '报警消息',
'component.noticeIcon.model.system.title': '系统通知',
'component.noticeIcon.messsage.statused': '点击标为已读',
'component.avatar.account': '账号',
'component.avatar.name': '姓名',
'component.avatar.depart': '部门',
'component.avatar.role': '角色',
'component.siteCode': '企业编号',
'component.avatar.update.success': '头像修改成功',
'component.avatar.update.fail': '头像修改失败',
'component.account.password.update.success': '修改密码成功',
'component.account.oldpassword.errorMessage': '原密码输入错误',
'component.account.password.update.fail': '修改密码失败',
'component.getVersion.errorMessage': '获取版本号错误,请联系相关开发人员',
'component.password.update': '修改密码',
'component.exit.login': '退出登录',
'component.search.menu.placeholder': '搜索菜单',
'component.header.icon.home': '首页',
'component.header.icon.order': '工单',
'component.header.icon.alarm': '报警',
};
export default {
'pages.login.welcome': '欢迎登录',
'pages.login.accountLogin.errorMessage': '账户或密码错误',
'pages.login.username.placeholder': '请输入用户名',
'pages.login.username.required': '请输入用户名!',
'pages.login.password.placeholder': '请输入密码',
'pages.login.password.required': '请输入密码!',
'pages.login.phoneLogin.errorMessage': '验证码填写错误,请重新获取',
'pages.login.phoneLogin.errorCodeMessage': '获取验证码失败',
'pages.login.phoneNumber.placeholder': '请输入手机号!',
'pages.login.phoneNumber.required': '手机号是必填项!',
'pages.login.phoneNumber.invalid': '不合法的手机号!',
'pages.login.captcha.placeholder': '请输入短信验证码!',
'pages.login.phoneLogin.getVerificationCode': '获取验证码',
'pages.login.phoneLogin.sendCationCode': '验证码已发送',
'pages.getCaptchaSecondText': '秒后重新获取',
'pages.login.rememberMe': '下次自动登录',
'pages.login.forgotPassword': '忘记密码 ?',
'pages.login.submit': '登录',
'pages.login.accountLogin.tab': '账号密码登录',
'pages.login.phoneLogin.tab': '手机号登录',
'pages.login.weChart.tab': '微信扫码登录',
};
export default {
'app.pwd.offline': '当前处于离线状态',
'app.pwa.serviceworker.updated': '有新内容',
'app.pwa.serviceworker.updated.hint': '请点击“刷新”按钮或者手动刷新页面',
'app.pwa.serviceworker.updated.ok': '刷新',
};
export default {
'app.settings.bootpage.title': '熊猫智慧城市监控管理解决方案',
};
......@@ -4,7 +4,7 @@ import { Space, Spin } from 'antd';
import classNames from 'classnames';
import { connect } from 'react-redux';
import { useIntl } from '@/locales/localeExports';
import { useIntl } from '@wisdom-utils/components';
import { useDocumentTitle } from '@ant-design/pro-utils';
import defaultSetting from '../../../config/defaultSetting';
......
......@@ -14,7 +14,7 @@ import {
} from 'antd';
import omit from 'omit.js';
import { useIntl } from '@/locales/localeExports';
import { useIntl } from '@wisdom-utils/components';
import services from '../../../../../api/service/base';
import styles from './index.less';
......
......@@ -3,7 +3,7 @@ import React from 'react';
import { Form } from 'antd';
import classNames from 'classnames';
import { useIntl } from '@/locales/localeExports';
import { useIntl } from '@wisdom-utils/components';
import styles from './index.less';
import LoginContext from './LoginContext';
......
import { Checkbox } from 'antd';
import React from 'react';
import { useIntl } from '@wisdom-utils/components';
import LoginForm from '../components/Login';
import LoginMessage from './loginMessage';
import { useIntl } from '@/locales/localeExports';
/* eslint-disable */
const { UserName, Password, Submit } = LoginForm;
const useAccount = props => (
......
......@@ -4,7 +4,7 @@ import { LOGIN_DISPLAY, LOGIN_WAY } from '@/constants';
import Account from './useAccount';
import IOTQRCode from './useIOTQRCode';
import Phone from './usePhone';
import { useIntl } from '@/locales/localeExports';
import { useIntl } from '@wisdom-utils/components';
import styles from '../style.less';
const useIOTComponent = props => {
......
......@@ -13,7 +13,7 @@ import { withRouter } from 'react-router-dom';
import { LOGIN_DISPLAY, LOGIN_WAY } from '@/constants';
import { actionCreators } from '@/containers/App/store';
import { FormattedMessage, useIntl } from '@/locales/localeExports';
import { FormattedMessage, useIntl } from '@wisdom-utils/components';
import defaultSetting from '../../../../../config/defaultSetting';
import LoginForm from '../components/Login';
......
......@@ -4,10 +4,9 @@ import { history } from '@wisdom-utils/runtime';
import { Provider } from 'react-redux';
import { ConfigProvider } from 'antd';
import { ConnectedRouter } from 'connected-react-router/immutable';
import { ErrorBoundary, LocaleContainer } from '@wisdom-utils/components';
import store from './stores';
import { ErrorBoundary } from '@wisdom-utils/components';
import Container from './components/Container';
import { LocaleContainer } from './locales/locale';
import App from './containers/App';
const MOUNT_NODE = document.getElementById('root');
export const render = () => {
......
......@@ -27,8 +27,8 @@ export const dyRoutes = (routes, layout) => {
{
name: 'noscret',
path: '/user/noscret',
component: NoSecret
}
component: NoSecret,
},
],
},
{
......@@ -82,7 +82,7 @@ export const dyRoutes = (routes, layout) => {
component: dynamic({
loader: () =>
import(
/* webpackChunkName: 'civ__plugin-openapi__openapi' */ '../components/openapi/openapi'
/* webpackChunkName: 'civ__plugin-openapi__openapi' */ '@wisdom-utils/components/lib/AppLayout/openapi/index'
),
loading: LoadingComponent,
}),
......
export function getAuthority(str) {
const authorityString = str
const authorityString = str;
let authority;
try {
......
......@@ -15,7 +15,7 @@ const generRotes = (widgets, parent, level = 0) => {
const ret = [];
if(!widgets || widgets.length === 0){
return
}
};
(widgets).forEach((item, index) => {
if (item.hasOwnProperty('widgets') && item.widgets !== null && Array.isArray(item.widgets) && item.widgets.length > 0) {
......
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