feat: user management
This commit is contained in:
parent
45c333cf37
commit
c5443dc9a7
@ -26,7 +26,7 @@ module.exports = Object.assign({}, base, {
|
|||||||
context: ['/'],
|
context: ['/'],
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
secure: false,
|
secure: false,
|
||||||
target: 'http://localhost:8848',
|
target: 'http://11.239.112.161:8848',
|
||||||
pathRewrite: {'^/v1' : '/nacos/v1'}
|
pathRewrite: {'^/v1' : '/nacos/v1'}
|
||||||
}],
|
}],
|
||||||
disableHostCheck: true,
|
disableHostCheck: true,
|
||||||
|
@ -27,55 +27,55 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@alifd/next-theme-loader": "^1.3.1",
|
"@alifd/next-theme-loader": "^1.3.1",
|
||||||
"@babel/cli": "^7.2.3",
|
"@babel/cli": "^7.7.7",
|
||||||
"@babel/core": "^7.2.2",
|
"@babel/core": "^7.7.7",
|
||||||
"@babel/plugin-proposal-decorators": "^7.2.3",
|
"@babel/plugin-proposal-decorators": "^7.7.4",
|
||||||
"@babel/preset-env": "^7.2.3",
|
"@babel/preset-env": "^7.7.7",
|
||||||
"@babel/runtime": "^7.2.0",
|
"@babel/runtime": "^7.7.7",
|
||||||
"babel-eslint": "^10.0.1",
|
"babel-eslint": "^10.0.1",
|
||||||
"babel-loader": "^8.0.4",
|
"babel-loader": "^8.0.4",
|
||||||
"babel-plugin-import": "^1.12.0",
|
"babel-plugin-import": "^1.13.0",
|
||||||
"babel-preset-react-app": "^6.1.0",
|
"babel-preset-react-app": "^9.1.0",
|
||||||
"clean-webpack-plugin": "^0.1.19",
|
"clean-webpack-plugin": "^3.0.0",
|
||||||
"copy-webpack-plugin": "^4.6.0",
|
"copy-webpack-plugin": "^5.1.1 ",
|
||||||
"cross-env": "^5.2.0",
|
"cross-env": "^6.0.3",
|
||||||
"css-loader": "^2.0.2",
|
"css-loader": "^3.4.0",
|
||||||
"eslint": "^5.11.0",
|
"eslint": "^6.8.0",
|
||||||
"eslint-config-ali": "^4.1.0",
|
"eslint-config-ali": "^9.0.2",
|
||||||
"eslint-config-prettier": "^3.3.0",
|
"eslint-config-prettier": "^6.8.0",
|
||||||
"eslint-loader": "^2.1.1",
|
"eslint-loader": "^3.0.3",
|
||||||
"eslint-plugin-import": "^2.14.0",
|
"eslint-plugin-import": "^2.14.0",
|
||||||
"eslint-plugin-prettier": "^3.0.0",
|
"eslint-plugin-prettier": "^3.0.0",
|
||||||
"eslint-plugin-react": "^7.11.1",
|
"eslint-plugin-react": "^7.17.0",
|
||||||
"file-loader": "^2.0.0",
|
"file-loader": "^5.0.2",
|
||||||
"html-webpack-plugin": "^3.2.0",
|
"html-webpack-plugin": "^3.2.0",
|
||||||
"husky": "^1.1.4",
|
"husky": "^3.1.0",
|
||||||
"lint-staged": "^8.0.4",
|
"lint-staged": "^9.5.0",
|
||||||
"mini-css-extract-plugin": "^0.5.0",
|
"mini-css-extract-plugin": "^0.9.0",
|
||||||
"node-sass": "^4.11.0",
|
"node-sass": "^4.13.0",
|
||||||
"optimize-css-assets-webpack-plugin": "^5.0.1",
|
"optimize-css-assets-webpack-plugin": "^5.0.3",
|
||||||
"prettier": "1.15.2",
|
"prettier": "1.19.1",
|
||||||
"sass-loader": "^7.1.0",
|
"sass-loader": "^8.0.0",
|
||||||
"style-loader": "^0.23.1",
|
"style-loader": "^1.1.2",
|
||||||
"uglifyjs-webpack-plugin": "^2.1.0",
|
"uglifyjs-webpack-plugin": "^2.2.0",
|
||||||
"url-loader": "^1.1.2",
|
"url-loader": "^3.0.0",
|
||||||
"webpack": "^4.28.2",
|
"webpack": "^4.41.4",
|
||||||
"webpack-cli": "^3.1.2",
|
"webpack-cli": "^3.3.10",
|
||||||
"webpack-dev-server": "^3.1.13"
|
"webpack-dev-server": "^3.10.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@alifd/next": "^1.15.12",
|
"@alifd/next": "^1.17.4",
|
||||||
"axios": "^0.18.0",
|
"axios": "^0.18.0",
|
||||||
"jquery": "^3.3.1",
|
"jquery": "^3.3.1",
|
||||||
"moment": "^2.23.0",
|
"moment": "^2.23.0",
|
||||||
"prop-types": "^15.6.2",
|
"prop-types": "^15.6.2",
|
||||||
"react": "^16.7.0",
|
"react": "^16.12.0",
|
||||||
"react-dom": "^16.7.0",
|
"react-dom": "^16.12.0",
|
||||||
"react-redux": "^5.1.1",
|
"react-redux": "^7.1.3",
|
||||||
"react-router": "^4.3.1",
|
"react-router": "^5.1.2",
|
||||||
"react-router-dom": "^4.3.1",
|
"react-router-dom": "^5.1.2",
|
||||||
"react-router-redux": "^4.0.8",
|
"react-router-redux": "^4.0.8",
|
||||||
"redux": "^4.0.1",
|
"redux": "^4.0.5",
|
||||||
"redux-thunk": "^2.3.0",
|
"redux-thunk": "^2.3.0",
|
||||||
"yamljs": "^0.3.0"
|
"yamljs": "^0.3.0"
|
||||||
}
|
}
|
||||||
|
@ -23,3 +23,9 @@ export const GET_STATE = 'GET_STATE';
|
|||||||
|
|
||||||
export const GET_SUBSCRIBERS = 'GET_SUBSCRIBERS';
|
export const GET_SUBSCRIBERS = 'GET_SUBSCRIBERS';
|
||||||
export const REMOVE_SUBSCRIBERS = 'REMOVE_SUBSCRIBERS';
|
export const REMOVE_SUBSCRIBERS = 'REMOVE_SUBSCRIBERS';
|
||||||
|
|
||||||
|
export const UPDATE_USER = 'UPDATE_USER';
|
||||||
|
export const SIGN_IN = 'SIGN_IN';
|
||||||
|
export const USER_LIST = 'USER_LIST';
|
||||||
|
|
||||||
|
export const ROLE_LIST = 'ROLE_LIST';
|
||||||
|
@ -12,9 +12,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import projectConfig from './config';
|
import projectConfig from './config';
|
||||||
import moment from 'moment';
|
|
||||||
import $ from 'jquery';
|
import $ from 'jquery';
|
||||||
import i18DocObj from './i18ndoc';
|
|
||||||
|
|
||||||
const global = window;
|
const global = window;
|
||||||
|
|
||||||
@ -205,120 +203,6 @@ const nacosUtils = (function(_global) {
|
|||||||
};
|
};
|
||||||
})(global);
|
})(global);
|
||||||
|
|
||||||
const aliwareIntl = (function(_global) {
|
|
||||||
/**
|
|
||||||
* 国际化构造方法
|
|
||||||
* @param {Object} options 配置信息
|
|
||||||
*/
|
|
||||||
function AliwareI18n(options) {
|
|
||||||
// let currentLocal = options.currentLocal || navigator.language || navigator.userLanguage;
|
|
||||||
|
|
||||||
const nowData = options.locals;
|
|
||||||
this.nowData = nowData;
|
|
||||||
this.setMomentLocale(this.currentLanguageCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
let aliwareLocal = aliwareGetCookieByKeyName('aliyun_lang') || 'zh';
|
|
||||||
let aliwareLocalSite = aliwareGetCookieByKeyName('aliyun_country') || 'cn';
|
|
||||||
aliwareLocal = aliwareLocal.toLowerCase();
|
|
||||||
aliwareLocalSite = aliwareLocalSite.toLowerCase();
|
|
||||||
// 当前语言
|
|
||||||
AliwareI18n.prototype.currentLocal = aliwareLocal;
|
|
||||||
// 当前地区
|
|
||||||
AliwareI18n.prototype.currentSite = aliwareLocalSite;
|
|
||||||
// 当前语言-地区
|
|
||||||
AliwareI18n.prototype.currentLanguageCode =
|
|
||||||
aliwareGetCookieByKeyName('docsite_language') || `${aliwareLocal}-${aliwareLocalSite}`;
|
|
||||||
/**
|
|
||||||
* 通过key获取对应国际化文案
|
|
||||||
* @param {String} key 国际化key
|
|
||||||
*/
|
|
||||||
AliwareI18n.prototype.get = function(key) {
|
|
||||||
return this.nowData[key];
|
|
||||||
};
|
|
||||||
/**
|
|
||||||
* 修改国际化文案数据
|
|
||||||
* @param {String} local 语言信息
|
|
||||||
*/
|
|
||||||
AliwareI18n.prototype.changeLanguage = function(local) {
|
|
||||||
this.nowData = i18DocObj[local] || {};
|
|
||||||
};
|
|
||||||
/**
|
|
||||||
* 数字国际化
|
|
||||||
* @param {Number} num 数字
|
|
||||||
*/
|
|
||||||
AliwareI18n.prototype.intlNumberFormat = function(num) {
|
|
||||||
if (typeof Intl !== 'object' || typeof Intl.NumberFormat !== 'function') {
|
|
||||||
return num;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
return new Intl.NumberFormat(this.currentLanguageCode).format(num || 0);
|
|
||||||
} catch (error) {
|
|
||||||
return num;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
/**
|
|
||||||
* 时间戳格式化
|
|
||||||
* @param {Number} num 时间戳
|
|
||||||
* @param {Object} initOption 配置信息
|
|
||||||
*/
|
|
||||||
AliwareI18n.prototype.intlTimeFormat = function(num = Date.now(), initOption = {}) {
|
|
||||||
try {
|
|
||||||
const date = Object.prototype.toString.call(num) === '[object Date]' ? num : new Date(num);
|
|
||||||
const options = Object.assign(
|
|
||||||
{},
|
|
||||||
{
|
|
||||||
// weekday: "short",
|
|
||||||
hour12: false,
|
|
||||||
year: 'numeric',
|
|
||||||
month: 'short',
|
|
||||||
day: 'numeric',
|
|
||||||
hour: 'numeric',
|
|
||||||
minute: 'numeric',
|
|
||||||
second: 'numeric',
|
|
||||||
},
|
|
||||||
initOption
|
|
||||||
);
|
|
||||||
return date.toLocaleDateString(this.currentLanguageCode, options);
|
|
||||||
} catch (error) {
|
|
||||||
return typeof moment === 'function' ? moment(num).format() : '--';
|
|
||||||
}
|
|
||||||
};
|
|
||||||
/**
|
|
||||||
* 获取当前时间格式
|
|
||||||
* @param {String} language 语言信息: zh/en
|
|
||||||
*/
|
|
||||||
AliwareI18n.prototype.getIntlTimeFormat = function(_language) {
|
|
||||||
const language = _language || aliwareLocal;
|
|
||||||
const langObj = {
|
|
||||||
zh: 'YYYY年M月D日 HH:mm:ss',
|
|
||||||
en: 'MMM D, YYYY, h:mm:ss A',
|
|
||||||
default: 'YYYY-MM-DD HH:mm:ss',
|
|
||||||
};
|
|
||||||
return langObj[language] ? langObj[language] : langObj.default;
|
|
||||||
};
|
|
||||||
/**
|
|
||||||
* 设置moment的locale
|
|
||||||
* @param {String} languageCode 语言信息: zh-ch/en-us
|
|
||||||
*/
|
|
||||||
AliwareI18n.prototype.setMomentLocale = function(languageCode) {
|
|
||||||
if (Object.prototype.toString.call(moment) === '[object Function]') {
|
|
||||||
moment.locale(languageCode || this.currentLanguageCode);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
return new AliwareI18n({
|
|
||||||
currentLocal: `${aliwareLocal}`,
|
|
||||||
locals:
|
|
||||||
i18DocObj[AliwareI18n.prototype.currentLanguageCode] ||
|
|
||||||
i18DocObj['en-us'] ||
|
|
||||||
i18DocObj['zh-cn'] ||
|
|
||||||
{},
|
|
||||||
});
|
|
||||||
})(global);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取url中的参数
|
* 获取url中的参数
|
||||||
*/
|
*/
|
||||||
@ -645,7 +529,6 @@ export {
|
|||||||
nacosEvent,
|
nacosEvent,
|
||||||
nacosUtils,
|
nacosUtils,
|
||||||
aliwareGetCookieByKeyName,
|
aliwareGetCookieByKeyName,
|
||||||
aliwareIntl,
|
|
||||||
getParams,
|
getParams,
|
||||||
setParam,
|
setParam,
|
||||||
setParams,
|
setParams,
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -44,6 +44,9 @@ import ServiceList from './pages/ServiceManagement/ServiceList';
|
|||||||
import ServiceDetail from './pages/ServiceManagement/ServiceDetail';
|
import ServiceDetail from './pages/ServiceManagement/ServiceDetail';
|
||||||
import SubscriberList from './pages/ServiceManagement/SubscriberList';
|
import SubscriberList from './pages/ServiceManagement/SubscriberList';
|
||||||
import ClusterNodeList from './pages/ClusterManagement/ClusterNodeList';
|
import ClusterNodeList from './pages/ClusterManagement/ClusterNodeList';
|
||||||
|
import UserManagement from './pages/AuthorityControl/UserManagement';
|
||||||
|
import PermissionsManagement from './pages/AuthorityControl/PermissionsManagement';
|
||||||
|
import RolesManagement from './pages/AuthorityControl/RolesManagement';
|
||||||
import Welcome from './pages/Welcome/Welcome';
|
import Welcome from './pages/Welcome/Welcome';
|
||||||
|
|
||||||
import reducers from './reducers';
|
import reducers from './reducers';
|
||||||
@ -65,10 +68,7 @@ const reducer = combineReducers({
|
|||||||
|
|
||||||
const store = createStore(
|
const store = createStore(
|
||||||
reducer,
|
reducer,
|
||||||
compose(
|
compose(applyMiddleware(thunk), window[REDUX_DEVTOOLS] ? window[REDUX_DEVTOOLS]() : f => f)
|
||||||
applyMiddleware(thunk),
|
|
||||||
window[REDUX_DEVTOOLS] ? window[REDUX_DEVTOOLS]() : f => f
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const MENU = [
|
const MENU = [
|
||||||
@ -89,12 +89,12 @@ const MENU = [
|
|||||||
{ path: '/serviceDetail', component: ServiceDetail },
|
{ path: '/serviceDetail', component: ServiceDetail },
|
||||||
{ path: '/subscriberList', component: SubscriberList },
|
{ path: '/subscriberList', component: SubscriberList },
|
||||||
{ path: '/clusterManagement', component: ClusterNodeList },
|
{ path: '/clusterManagement', component: ClusterNodeList },
|
||||||
|
{ path: '/userManagement', component: UserManagement },
|
||||||
|
{ path: '/rolesManagement', component: RolesManagement },
|
||||||
|
{ path: '/permissionsManagement', component: PermissionsManagement },
|
||||||
];
|
];
|
||||||
|
|
||||||
@connect(
|
@connect(state => ({ ...state.locale }), { changeLanguage })
|
||||||
state => ({ ...state.locale }),
|
|
||||||
{ changeLanguage }
|
|
||||||
)
|
|
||||||
class App extends React.Component {
|
class App extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
locale: PropTypes.object,
|
locale: PropTypes.object,
|
||||||
|
@ -1217,10 +1217,6 @@ form.vertical-margin-lg .form-group {
|
|||||||
border-color: #e0e0e0 !important;
|
border-color: #e0e0e0 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.main-container {
|
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.row-bg-green {
|
.row-bg-green {
|
||||||
background-color: #e4fdda;
|
background-color: #e4fdda;
|
||||||
}
|
}
|
||||||
|
@ -13,506 +13,122 @@
|
|||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { withRouter } from 'react-router-dom';
|
import { withRouter } from 'react-router-dom';
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import { ConfigProvider, Icon } from '@alifd/next';
|
|
||||||
import Header from './Header';
|
|
||||||
import $ from 'jquery';
|
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { setParams } from '../globalLib';
|
import PropTypes from 'prop-types';
|
||||||
|
import { ConfigProvider, Icon, Menu } from '@alifd/next';
|
||||||
|
import Header from './Header';
|
||||||
import { getState } from '../reducers/base';
|
import { getState } from '../reducers/base';
|
||||||
import _menu from '../menu';
|
import getMenuData from './menu';
|
||||||
|
|
||||||
import './index.scss';
|
const { SubMenu, Item } = Menu;
|
||||||
|
|
||||||
@withRouter
|
@withRouter
|
||||||
@connect(
|
@connect(state => ({ ...state.locale, ...state.base }), { getState })
|
||||||
state => ({ ...state.locale, ...state.base }),
|
|
||||||
{ getState }
|
|
||||||
)
|
|
||||||
@ConfigProvider.config
|
@ConfigProvider.config
|
||||||
class MainLayout extends React.Component {
|
class MainLayout extends React.Component {
|
||||||
static displayName = 'MainLayout';
|
static displayName = 'MainLayout';
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
history: PropTypes.object,
|
|
||||||
location: PropTypes.object,
|
|
||||||
locale: PropTypes.object,
|
locale: PropTypes.object,
|
||||||
children: PropTypes.any,
|
history: PropTypes.object,
|
||||||
version: PropTypes.any,
|
version: PropTypes.any,
|
||||||
functionMode: PropTypes.any,
|
|
||||||
getState: PropTypes.func,
|
getState: PropTypes.func,
|
||||||
|
functionMode: PropTypes.string,
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.deepNav = [];
|
|
||||||
this.oneLevelNavArr = {}; // 平行导航map
|
|
||||||
this.state = {
|
|
||||||
navList: [..._menu.data],
|
|
||||||
leftBarClose: false,
|
|
||||||
showLink: null,
|
|
||||||
navRow: [],
|
|
||||||
noChild: false,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this.props.getState();
|
this.props.getState();
|
||||||
this.refreshNav();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
goBack() {
|
goBack() {
|
||||||
this.props.history.goBack();
|
this.props.history.goBack();
|
||||||
}
|
}
|
||||||
|
|
||||||
nacosToggleNav(id, event) {
|
|
||||||
event.preventDefault();
|
|
||||||
const nowNav = document.getElementById(id);
|
|
||||||
const iconClass = nowNav.querySelector('.iconshow');
|
|
||||||
const subNav = nowNav.querySelector('.subnavlist');
|
|
||||||
const { classList } = iconClass;
|
|
||||||
let tmpClassName = 'iconshow ';
|
|
||||||
for (let i = 0; i < classList.length; i++) {
|
|
||||||
if (classList[i] === 'icon-arrow-down') {
|
|
||||||
subNav.style.display = 'none';
|
|
||||||
subNav.className += ' hidden';
|
|
||||||
tmpClassName += 'icon-arrow-right';
|
|
||||||
}
|
|
||||||
if (classList[i] === 'icon-arrow-right') {
|
|
||||||
tmpClassName += 'icon-arrow-down';
|
|
||||||
subNav.className = subNav.className.replace(/hidden/g, '');
|
|
||||||
subNav.style.display = 'block';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
iconClass.className = tmpClassName;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Click the back button
|
|
||||||
* TODO: this.props.history.goBack(); ???
|
|
||||||
* @param url
|
|
||||||
*/
|
|
||||||
nacosGoBack(url) {
|
|
||||||
const params = window.location.hash.split('?')[1];
|
|
||||||
const urlArr = params.split('&') || [];
|
|
||||||
const queryParams = [];
|
|
||||||
for (let i = 0; i < urlArr.length; i++) {
|
|
||||||
if (
|
|
||||||
urlArr[i].split('=')[0] !== '_k' &&
|
|
||||||
urlArr[i].split('=')[0] !== 'dataId' &&
|
|
||||||
urlArr[i].split('=')[0] !== 'group'
|
|
||||||
) {
|
|
||||||
if (urlArr[i].split('=')[0] === 'searchDataId') {
|
|
||||||
queryParams.push(`dataId=${urlArr[i].split('=')[1]}`);
|
|
||||||
} else if (urlArr[i].split('=')[0] === 'searchGroup') {
|
|
||||||
queryParams.push(`group=${urlArr[i].split('=')[1]}`);
|
|
||||||
} else {
|
|
||||||
queryParams.push(urlArr[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (localStorage.getItem('namespace')) {
|
|
||||||
queryParams.push(`namespace=${localStorage.getItem('namespace')}`);
|
|
||||||
}
|
|
||||||
this.props.history.push(`/${url}?${queryParams.join('&')}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
nacosEnterBack() {
|
|
||||||
document.getElementById('backarrow').style.color = '#09c';
|
|
||||||
}
|
|
||||||
|
|
||||||
nacosOutBack() {
|
|
||||||
document.getElementById('backarrow').style.color = '#546478';
|
|
||||||
}
|
|
||||||
|
|
||||||
nacosToggleLeftBar() {
|
|
||||||
if (!this.nacosOutDom) return;
|
|
||||||
if (!this.state.leftBarClose) {
|
|
||||||
// 关闭
|
|
||||||
this.nacosOutDom.className = 'viewFramework-product';
|
|
||||||
this.nacosLeftBarDom.style.width = 0;
|
|
||||||
this.nacosBodyDom.style.left = 0;
|
|
||||||
this.nacosToggleIconDom.style.left = 0;
|
|
||||||
} else {
|
|
||||||
this.nacosOutDom.className = 'viewFramework-product viewFramework-product-col-1';
|
|
||||||
this.nacosLeftBarDom.style.width = '180px';
|
|
||||||
this.nacosBodyDom.style.left = '180px';
|
|
||||||
this.nacosToggleIconDom.style.left = '160px';
|
|
||||||
}
|
|
||||||
|
|
||||||
this.setState({
|
|
||||||
leftBarClose: !this.state.leftBarClose,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
navTo(url) {
|
navTo(url) {
|
||||||
if (url !== '/configdetail' && url !== '/configeditor') {
|
const { search } = this.props.location;
|
||||||
// 二级菜单不清空
|
this.props.history.push([url, search].join(''));
|
||||||
setParams({
|
|
||||||
dataId: '',
|
|
||||||
group: '',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const params = window.location.hash.split('?')[1];
|
|
||||||
const urlArr = params.split('&') || [];
|
|
||||||
const queryParams = [];
|
|
||||||
for (let i = 0; i < urlArr.length; i++) {
|
|
||||||
if (urlArr[i].split('=')[0] !== '_k') {
|
|
||||||
queryParams.push(urlArr[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.props.history.push(`${url}?${queryParams.join('&')}`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nacosSetSpecialNav(item) {
|
isCurrentPath(url) {
|
||||||
item.children.forEach(_item => {
|
const { location } = this.props;
|
||||||
const obj = _item;
|
return url === location.pathname ? 'current-path' : undefined;
|
||||||
|
}
|
||||||
|
|
||||||
if (obj.dontUseChild === true) {
|
defaultOpenKeys() {
|
||||||
obj.parentName = item.title;
|
const MenuData = getMenuData(this.props.functionMode);
|
||||||
obj.parentId = item.id;
|
for (let i = 0, len = MenuData.length; i < len; i++) {
|
||||||
obj.parentPath = `/${item.id}`;
|
const { children } = MenuData[i];
|
||||||
this.deepNav.push(obj);
|
if (children && children.filter(({ url }) => url === this.props.location.pathname).length) {
|
||||||
}
|
return String(i);
|
||||||
if (_item.children) {
|
|
||||||
this.nacosSetSpecialNav(_item);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
isShowGoBack() {
|
||||||
|
const urls = [];
|
||||||
|
const MenuData = getMenuData(this.props.functionMode);
|
||||||
|
MenuData.forEach(item => {
|
||||||
|
if (item.url) urls.push(item.url);
|
||||||
|
if (item.children) item.children.forEach(({ url }) => urls.push(url));
|
||||||
});
|
});
|
||||||
}
|
return !urls.includes(this.props.location.pathname);
|
||||||
|
|
||||||
nacosNavAct(serviceName, match, location) {
|
|
||||||
if (!match) {
|
|
||||||
const formatpath = location.pathname.substr(1); // 得到当前路径
|
|
||||||
const nowpathobj = this.oneLevelNavArr[formatpath]; // 根据平行导航匹配父类
|
|
||||||
if (nowpathobj) {
|
|
||||||
if (nowpathobj.parent === serviceName) {
|
|
||||||
// 如果父类等于当前的导航则高亮
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
nacosLoopNavDeeply(data, parentServiceName) {
|
|
||||||
// 深度遍历获取所有的导航数据
|
|
||||||
data.forEach(item => {
|
|
||||||
if (item) {
|
|
||||||
const navObj = item;
|
|
||||||
|
|
||||||
const _parentServiceName = item.serviceName;
|
|
||||||
navObj.parentServiceName = parentServiceName;
|
|
||||||
this.oneLevelNavArr[item.serviceName] = navObj; // 得到每一个层级的导航映射
|
|
||||||
if (item.children && item.children.length > 0) {
|
|
||||||
this.nacosLoopNavDeeply(item.children, _parentServiceName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
activeNav(id) {
|
|
||||||
if (this.preActNav) {
|
|
||||||
this.preActNav.removeClass('active');
|
|
||||||
}
|
|
||||||
const nowNav = $(`#${id}`);
|
|
||||||
nowNav.addClass('active');
|
|
||||||
this.preActNav = nowNav;
|
|
||||||
}
|
|
||||||
|
|
||||||
nacosLoopNav(data, _index = 0, parent) {
|
|
||||||
const { locale = {}, location = {} } = this.props;
|
|
||||||
const { pathname } = location;
|
|
||||||
let index = _index;
|
|
||||||
// 遍历导航,只显示2级
|
|
||||||
const self = this;
|
|
||||||
return data.map(item => {
|
|
||||||
if (!item) return '';
|
|
||||||
index++;
|
|
||||||
if (item.dontUseChild === true) return '';
|
|
||||||
if (item.children && item.children.length > 0) {
|
|
||||||
if (item.isVirtual) {
|
|
||||||
// 如果是虚拟菜单需要增加展开箭头
|
|
||||||
const icon = item.isExtend ? (
|
|
||||||
<span className="icon-arrow-down iconshow" />
|
|
||||||
) : (
|
|
||||||
<span className="icon-arrow-right iconshow" />
|
|
||||||
);
|
|
||||||
const hiddenClass = item.isExtend ? '' : 'hidden';
|
|
||||||
return (
|
|
||||||
<li
|
|
||||||
style={{ display: item.enable ? 'block' : 'none' }}
|
|
||||||
key={`${item.serviceName}`}
|
|
||||||
data-spm-click={`gostr=/aliyun;locaid=${item.serviceName}`}
|
|
||||||
id={`${item.serviceName}`}
|
|
||||||
>
|
|
||||||
<div>
|
|
||||||
<a href="" onClick={this.nacosToggleNav.bind(this, item.serviceName)}>
|
|
||||||
<div className="nav-icon">{icon}</div>
|
|
||||||
<div className="nav-title">{locale[item.serviceName]}</div>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<ul className={`subnavlist ${hiddenClass}`}>
|
|
||||||
{self.nacosLoopNav(item.children, index)}
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return (
|
|
||||||
<li
|
|
||||||
className={pathname === `/${item.serviceName}` ? 'selected' : ''}
|
|
||||||
key={`${item.serviceName}`}
|
|
||||||
data-spm-click={`gostr=/aliyun;locaid=${item.serviceName}`}
|
|
||||||
onClick={this.navTo.bind(this, `/${item.serviceName}`)}
|
|
||||||
>
|
|
||||||
<a
|
|
||||||
href="javascript:;"
|
|
||||||
id={`${item.serviceName}`}
|
|
||||||
onClick={this.activeNav.bind(this, `nav${index}`)}
|
|
||||||
>
|
|
||||||
<div className="nav-icon" />
|
|
||||||
<div className="nav-title">{locale[item.serviceName]}</div>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<li
|
|
||||||
className={pathname === `/${item.serviceName}` ? 'selected' : ''}
|
|
||||||
key={`${item.serviceName}`}
|
|
||||||
data-spm-click={`gostr=/aliyun;locaid=${item.serviceName}`}
|
|
||||||
onClick={this.navTo.bind(this, `/${item.serviceName}`)}
|
|
||||||
>
|
|
||||||
<a
|
|
||||||
href={'javascript:;'}
|
|
||||||
id={`${item.serviceName}`}
|
|
||||||
onClick={this.activeNav.bind(this, `nav${index}`)}
|
|
||||||
>
|
|
||||||
<div className="nav-icon" />
|
|
||||||
<div className="nav-title">{locale[item.serviceName]}</div>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
nacosGetNav(navList) {
|
|
||||||
let navRow = ''; // 导航
|
|
||||||
if (navList.length > 0) {
|
|
||||||
navRow = <ul>{this.nacosLoopNav(navList)}</ul>;
|
|
||||||
this.nacosLoopNavDeeply(navList); // 深度遍历导航树获得平行map
|
|
||||||
}
|
|
||||||
return navRow;
|
|
||||||
}
|
|
||||||
|
|
||||||
renderNav() {
|
|
||||||
const { navList } = this.state;
|
|
||||||
this.nacosLeftBarDom = document.getElementById('viewFramework-product-navbar');
|
|
||||||
this.nacosBodyDom = document.getElementById('viewFramework-product-body');
|
|
||||||
this.nacosToggleIconDom = document.getElementById('viewFramework-product-navbar-collapse');
|
|
||||||
this.nacosOutDom = document.getElementById('page-header-mask');
|
|
||||||
const defaultNav = '/configurationManagement';
|
|
||||||
this.props.history.listen(location => {
|
|
||||||
if (this.preSimplePath && this.preSimplePath !== '/') {
|
|
||||||
if (location.pathname.indexOf(this.preSimplePath) !== -1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const simplePath = window.location.hash.split('?')[0];
|
|
||||||
const navName = simplePath.substr('2');
|
|
||||||
this.preSimplePath = simplePath;
|
|
||||||
|
|
||||||
if (navName === '') {
|
|
||||||
this.props.history.push(defaultNav);
|
|
||||||
setTimeout(() => {
|
|
||||||
this.activeNav('configurationManagement');
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const nowNavObj = this.oneLevelNavArr[navName];
|
|
||||||
if (!nowNavObj) {
|
|
||||||
this.setState({
|
|
||||||
noChild: true,
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const { parentServiceName } = nowNavObj;
|
|
||||||
|
|
||||||
const parentNav = this.oneLevelNavArr[parentServiceName];
|
|
||||||
if (simplePath !== '/' && nowNavObj && parentNav && !parentNav.isVirtual) {
|
|
||||||
this.setState({
|
|
||||||
showLink: (
|
|
||||||
<div>
|
|
||||||
<Icon
|
|
||||||
type="arrow-left"
|
|
||||||
onClick={this.nacosGoBack.bind(this, parentServiceName)}
|
|
||||||
id={'backarrow'}
|
|
||||||
onMouseOver={this.nacosEnterBack.bind(this)}
|
|
||||||
onMouseLeave={this.nacosOutBack.bind(this)}
|
|
||||||
style={{
|
|
||||||
marginLeft: 77,
|
|
||||||
marginTop: 0,
|
|
||||||
fontWeight: 'bold',
|
|
||||||
cursor: 'pointer',
|
|
||||||
color: '#546478',
|
|
||||||
fontSize: '20px',
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
),
|
|
||||||
|
|
||||||
navRow: <ul>{this.nacosLoopNav([nowNavObj])}</ul>,
|
|
||||||
});
|
|
||||||
setTimeout(() => {
|
|
||||||
const navid = navName;
|
|
||||||
this.activeNav(navid);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.setState({
|
|
||||||
showLink: null,
|
|
||||||
navRow: <ul>{this.nacosLoopNav(navList)}</ul>,
|
|
||||||
});
|
|
||||||
setTimeout(() => {
|
|
||||||
const navid = navName;
|
|
||||||
this.activeNav(navid);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
refreshNav() {
|
|
||||||
const { navList } = this.state;
|
|
||||||
const { location, history, functionMode } = this.props;
|
|
||||||
const [configUrl, serviceUrl, clusterUrl] = [
|
|
||||||
'/configurationManagement',
|
|
||||||
'/serviceManagement',
|
|
||||||
'/clusterManagement',
|
|
||||||
];
|
|
||||||
this.setState(
|
|
||||||
{
|
|
||||||
navList: navList.map(item => {
|
|
||||||
if (
|
|
||||||
item.serviceName === 'configurationManagementVirtual' &&
|
|
||||||
(functionMode === null || functionMode === 'config')
|
|
||||||
) {
|
|
||||||
item.enable = true;
|
|
||||||
}
|
|
||||||
if (
|
|
||||||
item.serviceName === 'serviceManagementVirtual' &&
|
|
||||||
(functionMode === null || functionMode === 'naming')
|
|
||||||
) {
|
|
||||||
item.enable = true;
|
|
||||||
}
|
|
||||||
if (
|
|
||||||
item.serviceName === 'clusterManagementVirtual' &&
|
|
||||||
(functionMode === null || functionMode === 'cluster')
|
|
||||||
) {
|
|
||||||
item.enable = true;
|
|
||||||
}
|
|
||||||
return item;
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
() => this.setState({ navRow: this.nacosGetNav(navList) }, () => this.renderNav())
|
|
||||||
);
|
|
||||||
if (functionMode === 'config' && location.pathname === serviceUrl) {
|
|
||||||
history.push(configUrl);
|
|
||||||
}
|
|
||||||
if (functionMode === 'naming' && location.pathname === configUrl) {
|
|
||||||
history.push(serviceUrl);
|
|
||||||
}
|
|
||||||
if (functionMode === 'cluster' && location.pathname === clusterUrl) {
|
|
||||||
history.push(clusterUrl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillReceiveProps() {
|
|
||||||
setTimeout(() => this.refreshNav());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { locale = {}, version } = this.props;
|
const { locale = {}, version, functionMode } = this.props;
|
||||||
const { nacosName, doesNotExist } = locale;
|
const MenuData = getMenuData(functionMode);
|
||||||
const { showLink, navRow, leftBarClose, noChild } = this.state;
|
|
||||||
return (
|
return (
|
||||||
<div className="viewFramework-product" style={{ top: 66 }}>
|
<>
|
||||||
<Header />
|
<Header />
|
||||||
<div
|
<div className="main-container">
|
||||||
className="viewFramework-product-navbar"
|
<div className="left-panel">
|
||||||
style={{ width: 180, marginLeft: 0 }}
|
{this.isShowGoBack() ? (
|
||||||
id="viewFramework-product-navbar"
|
<div className="go-back" onClick={() => this.goBack()}>
|
||||||
data-spm="acm_nav"
|
<Icon type="arrow-left" />
|
||||||
>
|
|
||||||
<div className="viewFramework-product-navbar-removed">
|
|
||||||
<div>
|
|
||||||
<div className="product-nav-scene product-nav-main-scene">
|
|
||||||
{showLink ? (
|
|
||||||
<div className="product-nav-icon env" style={{ height: 80, paddingTop: 25 }}>
|
|
||||||
{showLink}
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<div
|
|
||||||
style={{ textIndent: 0, display: !version ? 'none' : 'block' }}
|
|
||||||
className="product-nav-title"
|
|
||||||
title={nacosName}
|
|
||||||
>
|
|
||||||
<span>{nacosName}</span>
|
|
||||||
<span style={{ marginLeft: 5 }}>{version}</span>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
<div
|
|
||||||
className="product-nav-list"
|
|
||||||
style={{ position: 'relative', top: 0, height: '100%' }}
|
|
||||||
>
|
|
||||||
{navRow}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="viewFramework-product-navbar-collapse"
|
|
||||||
id="viewFramework-product-navbar-collapse"
|
|
||||||
onClick={this.nacosToggleLeftBar.bind(this)}
|
|
||||||
>
|
|
||||||
<div className="product-navbar-collapse-inner">
|
|
||||||
<div className="product-navbar-collapse-bg" />
|
|
||||||
<div className="product-navbar-collapse">
|
|
||||||
{leftBarClose ? (
|
|
||||||
<span className="icon-collapse-right" style={{ display: 'block' }} />
|
|
||||||
) : (
|
|
||||||
<span className="icon-collapse-left" />
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="viewFramework-product-body"
|
|
||||||
style={{ marginLeft: 180 }}
|
|
||||||
id="viewFramework-product-body"
|
|
||||||
>
|
|
||||||
<div>
|
|
||||||
{!noChild ? (
|
|
||||||
<div>{this.props.children}</div>
|
|
||||||
) : (
|
) : (
|
||||||
<div
|
<>
|
||||||
style={{
|
<h1 className="nav-title">
|
||||||
height: 300,
|
{locale.nacosName}
|
||||||
lineHeight: 300,
|
<span>{version}</span>
|
||||||
textAlign: 'center',
|
</h1>
|
||||||
fontSize: 18,
|
<Menu
|
||||||
}}
|
defaultOpenKeys={this.defaultOpenKeys()}
|
||||||
>
|
className="nav-menu"
|
||||||
{doesNotExist}
|
openMode="single"
|
||||||
</div>
|
>
|
||||||
|
{MenuData.map((subMenu, idx) =>
|
||||||
|
subMenu.children ? (
|
||||||
|
<SubMenu key={String(idx)} label={locale[subMenu.key]}>
|
||||||
|
{subMenu.children.map((item, i) => (
|
||||||
|
<Item
|
||||||
|
key={[idx, i].join('-')}
|
||||||
|
onClick={() => this.navTo(item.url)}
|
||||||
|
className={this.isCurrentPath(item.url)}
|
||||||
|
>
|
||||||
|
{locale[item.key]}
|
||||||
|
</Item>
|
||||||
|
))}
|
||||||
|
</SubMenu>
|
||||||
|
) : (
|
||||||
|
<Item
|
||||||
|
key={idx}
|
||||||
|
className={['first-menu', this.isCurrentPath(subMenu.url)]
|
||||||
|
.filter(c => c)
|
||||||
|
.join(' ')}
|
||||||
|
onClick={() => this.navTo(subMenu.url)}
|
||||||
|
>
|
||||||
|
{locale[subMenu.key]}
|
||||||
|
</Item>
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
</Menu>
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
<div className="right-panel">{this.props.children}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,14 +11,6 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
.header-container {
|
|
||||||
position: fixed;
|
|
||||||
left: 0;
|
|
||||||
top: 0;
|
|
||||||
width: 100%;
|
|
||||||
z-index: 1000;
|
|
||||||
background-color: #fff;
|
|
||||||
}
|
|
||||||
.header-container-primary {
|
.header-container-primary {
|
||||||
background: #252a2f;
|
background: #252a2f;
|
||||||
}
|
}
|
||||||
@ -1396,5 +1388,62 @@ h6 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.product-nav-list li.selected a {
|
.product-nav-list li.selected a {
|
||||||
background-color: #F4F6F8;
|
background-color: #f4f6f8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-container {
|
||||||
|
height: calc(100vh - 66px);
|
||||||
|
.left-panel,
|
||||||
|
.right-panel {
|
||||||
|
float: left;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
.left-panel {
|
||||||
|
width: 180px;
|
||||||
|
background-color: #eaedf1;
|
||||||
|
}
|
||||||
|
.right-panel {
|
||||||
|
width: calc(100% - 180px);
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
.nav-title {
|
||||||
|
margin: 0;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: bold;
|
||||||
|
line-height: 70px;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
background-color: #d9dee4;
|
||||||
|
span {
|
||||||
|
margin-left: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.nav-menu {
|
||||||
|
padding: 0;
|
||||||
|
background: transparent;
|
||||||
|
border: 0;
|
||||||
|
line-height: 40px;
|
||||||
|
div.next-menu-item,
|
||||||
|
.first-menu > .next-menu-item-inner {
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
.next-menu-item-inner {
|
||||||
|
height: 40px;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
.current-path {
|
||||||
|
background-color: #f2f3f7;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.go-back {
|
||||||
|
text-align: center;
|
||||||
|
color: rgb(84, 100, 120);
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: bold;
|
||||||
|
padding: 10px 0;
|
||||||
|
margin-top: 14px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,61 @@
|
|||||||
|
export default function(model) {
|
||||||
|
const configurationMenu = {
|
||||||
|
key: 'configurationManagementVirtual',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
key: 'configurationManagement',
|
||||||
|
url: '/configurationManagement',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'listeningToQuery',
|
||||||
|
url: '/listeningToQuery',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
return [
|
||||||
|
model === 'naming' ? undefined : configurationMenu,
|
||||||
|
{
|
||||||
|
key: 'serviceManagementVirtual',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
key: 'serviceManagement',
|
||||||
|
url: '/serviceManagement',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'subscriberList',
|
||||||
|
url: '/subscriberList',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'clusterManagementVirtual',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
key: 'clusterManagement',
|
||||||
|
url: '/clusterManagement',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'authorityControl',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
key: 'userList',
|
||||||
|
url: '/userManagement',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'roleManagement',
|
||||||
|
url: '/rolesManagement',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'privilegeManagement',
|
||||||
|
url: '/permissionsManagement',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'namespace',
|
||||||
|
url: '/namespace',
|
||||||
|
},
|
||||||
|
].filter(item => item);
|
||||||
|
}
|
@ -50,6 +50,10 @@ const I18N_CONF = {
|
|||||||
namespace: 'Namespace',
|
namespace: 'Namespace',
|
||||||
clusterManagementVirtual: 'ClusterManagement',
|
clusterManagementVirtual: 'ClusterManagement',
|
||||||
clusterManagement: 'Cluster Node List',
|
clusterManagement: 'Cluster Node List',
|
||||||
|
authorityControl: 'Authority Control',
|
||||||
|
userList: 'User List',
|
||||||
|
roleManagement: 'Role Management',
|
||||||
|
privilegeManagement: 'Privilege Management',
|
||||||
},
|
},
|
||||||
Password: {
|
Password: {
|
||||||
passwordNotConsistent: 'The passwords are not consistent',
|
passwordNotConsistent: 'The passwords are not consistent',
|
||||||
|
@ -50,6 +50,10 @@ const I18N_CONF = {
|
|||||||
namespace: '命名空间',
|
namespace: '命名空间',
|
||||||
clusterManagementVirtual: '集群管理',
|
clusterManagementVirtual: '集群管理',
|
||||||
clusterManagement: '节点列表',
|
clusterManagement: '节点列表',
|
||||||
|
authorityControl: '权限控制',
|
||||||
|
userList: '用户列表',
|
||||||
|
roleManagement: '角色管理',
|
||||||
|
privilegeManagement: '权限管理',
|
||||||
},
|
},
|
||||||
Password: {
|
Password: {
|
||||||
passwordNotConsistent: '两次输入密码不一致',
|
passwordNotConsistent: '两次输入密码不一致',
|
||||||
|
@ -1,295 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
data: [
|
|
||||||
{
|
|
||||||
enable: false,
|
|
||||||
isExtend: true,
|
|
||||||
name: '配置管理',
|
|
||||||
title: '配置管理',
|
|
||||||
isVirtual: true,
|
|
||||||
projectName: 'nacos',
|
|
||||||
serviceName: 'configurationManagementVirtual',
|
|
||||||
link: 'configurationManagementVirtual',
|
|
||||||
hasFusion: true,
|
|
||||||
template: '',
|
|
||||||
registerName: 'com.alibaba.nacos.page.configurationManagementVirtual',
|
|
||||||
useRouter: false,
|
|
||||||
id: 'com.alibaba.nacos.page.configurationManagementVirtual',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
isExtend: false,
|
|
||||||
name: '配置列表',
|
|
||||||
title: '配置列表',
|
|
||||||
isVirtual: false,
|
|
||||||
projectName: 'nacos',
|
|
||||||
serviceName: 'configurationManagement',
|
|
||||||
link: 'configurationManagement',
|
|
||||||
hasFusion: true,
|
|
||||||
template: '',
|
|
||||||
dontUseChild: false,
|
|
||||||
registerName: 'com.alibaba.nacos.page.configurationManagement',
|
|
||||||
useRouter: false,
|
|
||||||
id: 'configurationManagement',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
isExtend: false,
|
|
||||||
name: '配置详情',
|
|
||||||
title: '配置详情',
|
|
||||||
isVirtual: false,
|
|
||||||
projectName: 'nacos',
|
|
||||||
serviceName: 'configdetail',
|
|
||||||
link: 'Configdetail',
|
|
||||||
hasFusion: true,
|
|
||||||
template: '',
|
|
||||||
dontUseChild: false,
|
|
||||||
registerName: 'com.alibaba.nacos.page.configdetail',
|
|
||||||
useRouter: false,
|
|
||||||
id: 'configdetail',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
isExtend: false,
|
|
||||||
name: '同步配置',
|
|
||||||
title: '同步配置',
|
|
||||||
isVirtual: false,
|
|
||||||
projectName: 'nacos',
|
|
||||||
serviceName: 'configsync',
|
|
||||||
link: 'configsync',
|
|
||||||
hasFusion: true,
|
|
||||||
template: '',
|
|
||||||
dontUseChild: true,
|
|
||||||
registerName: 'com.alibaba.nacos.page.configsync',
|
|
||||||
useRouter: false,
|
|
||||||
id: 'configsync',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
isExtend: false,
|
|
||||||
name: '配置编辑',
|
|
||||||
title: '配置编辑',
|
|
||||||
isVirtual: false,
|
|
||||||
projectName: 'nacos',
|
|
||||||
serviceName: 'configeditor',
|
|
||||||
link: 'configeditor',
|
|
||||||
hasFusion: true,
|
|
||||||
template: '',
|
|
||||||
registerName: 'com.alibaba.nacos.page.configeditor',
|
|
||||||
useRouter: false,
|
|
||||||
id: 'configeditor',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
isExtend: false,
|
|
||||||
name: '新建配置',
|
|
||||||
title: '新建配置',
|
|
||||||
isVirtual: false,
|
|
||||||
projectName: 'nacos',
|
|
||||||
serviceName: 'newconfig',
|
|
||||||
link: 'newconfig',
|
|
||||||
hasFusion: true,
|
|
||||||
template: '',
|
|
||||||
registerName: 'com.alibaba.nacos.page.newconfig',
|
|
||||||
useRouter: false,
|
|
||||||
id: 'newconfig',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
isExtend: false,
|
|
||||||
name: '历史版本',
|
|
||||||
title: '历史版本',
|
|
||||||
isVirtual: false,
|
|
||||||
projectName: 'nacos',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
isExtend: false,
|
|
||||||
name: '配置回滚',
|
|
||||||
title: '配置回滚',
|
|
||||||
isVirtual: false,
|
|
||||||
projectName: 'nacos',
|
|
||||||
serviceName: 'configRollback',
|
|
||||||
link: 'configRollback',
|
|
||||||
hasFusion: true,
|
|
||||||
template: '',
|
|
||||||
registerName: 'com.alibaba.nacos.page.configRollback',
|
|
||||||
useRouter: false,
|
|
||||||
id: 'configRollback',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
isExtend: false,
|
|
||||||
name: '历史详情',
|
|
||||||
title: '历史详情',
|
|
||||||
isVirtual: false,
|
|
||||||
projectName: 'nacos',
|
|
||||||
serviceName: 'historyDetail',
|
|
||||||
link: 'historyDetail',
|
|
||||||
hasFusion: true,
|
|
||||||
template: '',
|
|
||||||
registerName: 'com.alibaba.nacos.page.historyDetail',
|
|
||||||
useRouter: false,
|
|
||||||
id: 'historyDetail',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
serviceName: 'historyRollback',
|
|
||||||
link: 'historyRollback',
|
|
||||||
hasFusion: true,
|
|
||||||
template: '',
|
|
||||||
dontUseChild: false,
|
|
||||||
registerName: 'com.alibaba.nacos.page.historyRollback',
|
|
||||||
useRouter: false,
|
|
||||||
id: 'historyRollback',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
isExtend: false,
|
|
||||||
name: '监听查询',
|
|
||||||
title: '监听查询',
|
|
||||||
isVirtual: false,
|
|
||||||
projectName: 'nacos',
|
|
||||||
serviceName: 'listeningToQuery',
|
|
||||||
link: 'listeningToQuery',
|
|
||||||
hasFusion: true,
|
|
||||||
template: '',
|
|
||||||
registerName: 'com.alibaba.nacos.page.listeningToQuery',
|
|
||||||
useRouter: false,
|
|
||||||
id: 'listeningToQuery',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
enable: false,
|
|
||||||
isExtend: true,
|
|
||||||
name: '服务管理',
|
|
||||||
title: '服务管理',
|
|
||||||
isVirtual: true,
|
|
||||||
projectName: 'nacos',
|
|
||||||
serviceName: 'serviceManagementVirtual',
|
|
||||||
link: 'serviceManagementVirtual',
|
|
||||||
hasFusion: true,
|
|
||||||
template: '',
|
|
||||||
registerName: 'com.alibaba.nacos.page.serviceManagementVirtual',
|
|
||||||
useRouter: false,
|
|
||||||
id: 'com.alibaba.nacos.page.serviceManagementVirtual',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
isExtend: false,
|
|
||||||
name: '服务列表',
|
|
||||||
title: '服务列表',
|
|
||||||
isVirtual: false,
|
|
||||||
projectName: 'nacos',
|
|
||||||
serviceName: 'serviceManagement',
|
|
||||||
link: 'serviceManagement',
|
|
||||||
hasFusion: true,
|
|
||||||
template: '',
|
|
||||||
registerName: 'com.alibaba.nacos.page.serviceManagement',
|
|
||||||
useRouter: false,
|
|
||||||
id: 'serviceManagement',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
isExtend: true,
|
|
||||||
name: '服务详情',
|
|
||||||
title: '服务详情',
|
|
||||||
isVirtual: true,
|
|
||||||
projectName: 'nacos',
|
|
||||||
serviceName: 'serviceDetail',
|
|
||||||
link: 'serviceDetail',
|
|
||||||
hasFusion: true,
|
|
||||||
template: '',
|
|
||||||
registerName: 'com.alibaba.nacos.page.ServiceDetail',
|
|
||||||
useRouter: false,
|
|
||||||
id: 'serviceDetail',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
isExtend: false,
|
|
||||||
name: '订阅者列表',
|
|
||||||
title: '订阅者列表',
|
|
||||||
isVirtual: false,
|
|
||||||
projectName: 'nacos',
|
|
||||||
serviceName: 'subscriberList',
|
|
||||||
link: 'subscriberList',
|
|
||||||
hasFusion: true,
|
|
||||||
template: '',
|
|
||||||
registerName: 'com.alibaba.nacos.page.subscriberList',
|
|
||||||
useRouter: false,
|
|
||||||
id: 'subscriberList',
|
|
||||||
children: [],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
enable: true,
|
|
||||||
isExtend: false,
|
|
||||||
name: '命名空间',
|
|
||||||
title: '命名空间',
|
|
||||||
isVirtual: false,
|
|
||||||
projectName: 'nacos',
|
|
||||||
serviceName: 'namespace',
|
|
||||||
link: 'namespace',
|
|
||||||
hasFusion: true,
|
|
||||||
template: '',
|
|
||||||
dontUseChild: false,
|
|
||||||
registerName: 'com.alibaba.nacos.page.namespace',
|
|
||||||
useRouter: false,
|
|
||||||
id: 'namespace',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
enable: true,
|
|
||||||
isExtend: false,
|
|
||||||
name: '修改密码',
|
|
||||||
title: '修改密码',
|
|
||||||
isVirtual: false,
|
|
||||||
projectName: 'nacos',
|
|
||||||
serviceName: 'password',
|
|
||||||
link: 'password',
|
|
||||||
hasFusion: true,
|
|
||||||
template: '',
|
|
||||||
dontUseChild: true,
|
|
||||||
registerName: 'com.alibaba.nacos.page.password',
|
|
||||||
useRouter: false,
|
|
||||||
id: 'password',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
enable: false,
|
|
||||||
isExtend: true,
|
|
||||||
name: '集群管理',
|
|
||||||
title: '集群管理',
|
|
||||||
isVirtual: true,
|
|
||||||
projectName: 'nacos',
|
|
||||||
serviceName: 'clusterManagementVirtual',
|
|
||||||
link: 'clusterManagementVirtual',
|
|
||||||
hasFusion: true,
|
|
||||||
template: '',
|
|
||||||
registerName: 'com.alibaba.nacos.page.clusterManagementVirtual',
|
|
||||||
useRouter: false,
|
|
||||||
id: 'com.alibaba.nacos.page.clusterManagementVirtual',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
isExtend: false,
|
|
||||||
name: '节点状态',
|
|
||||||
title: '节点状态',
|
|
||||||
isVirtual: false,
|
|
||||||
projectName: 'nacos',
|
|
||||||
serviceName: 'clusterManagement',
|
|
||||||
link: 'clusterManagement',
|
|
||||||
hasFusion: true,
|
|
||||||
template: '',
|
|
||||||
registerName: 'com.alibaba.nacos.page.clusterManagement',
|
|
||||||
useRouter: false,
|
|
||||||
id: 'clusterManagement',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
defaultKey: 'configurationManagement',
|
|
||||||
projectName: 'nacos',
|
|
||||||
};
|
|
@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import {
|
||||||
|
Button,
|
||||||
|
Field,
|
||||||
|
Form,
|
||||||
|
Grid,
|
||||||
|
Input,
|
||||||
|
Loading,
|
||||||
|
Pagination,
|
||||||
|
Table,
|
||||||
|
ConfigProvider,
|
||||||
|
} from '@alifd/next';
|
||||||
|
|
||||||
|
import './PermissionsManagement.scss';
|
||||||
|
|
||||||
|
@ConfigProvider.config
|
||||||
|
class PermissionsManagement extends React.Component {
|
||||||
|
static displayName = 'UserManagement';
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
locale: PropTypes.object,
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<h1>PermissionsManagement</h1>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PermissionsManagement;
|
@ -0,0 +1,12 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
@ -0,0 +1,16 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import PermissionsManagement from './PermissionsManagement';
|
||||||
|
|
||||||
|
export default PermissionsManagement;
|
@ -0,0 +1,7 @@
|
|||||||
|
# 权限控制
|
||||||
|
|
||||||
|
> AuthorityControl
|
||||||
|
|
||||||
|
1. UserManagement => 用户管理
|
||||||
|
2. RolesManagement => 角色管理
|
||||||
|
3. PermissionsManagement => 权限管理
|
@ -0,0 +1,96 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import {
|
||||||
|
Button,
|
||||||
|
Field,
|
||||||
|
Form,
|
||||||
|
Input,
|
||||||
|
Dialog,
|
||||||
|
Pagination,
|
||||||
|
Table,
|
||||||
|
ConfigProvider,
|
||||||
|
// Field,
|
||||||
|
} from '@alifd/next';
|
||||||
|
|
||||||
|
const FormItem = Form.Item;
|
||||||
|
|
||||||
|
const formItemLayout = {
|
||||||
|
labelCol: { fixedSpan: 3 },
|
||||||
|
wrapperCol: { span: 20 },
|
||||||
|
};
|
||||||
|
|
||||||
|
@ConfigProvider.config
|
||||||
|
class NewRole extends React.Component {
|
||||||
|
static displayName = 'NewRole';
|
||||||
|
|
||||||
|
field = new Field(this);
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
locale: PropTypes.object,
|
||||||
|
visible: PropTypes.bool,
|
||||||
|
};
|
||||||
|
|
||||||
|
check() {
|
||||||
|
const errors = {
|
||||||
|
role: '角色不能为空!',
|
||||||
|
username: '用户名不能为空!',
|
||||||
|
};
|
||||||
|
const vals = ['role', 'username'].map(key => {
|
||||||
|
const val = this.field.getValue(key);
|
||||||
|
if (!val) {
|
||||||
|
this.field.setError(key, errors[key]);
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
});
|
||||||
|
if (vals.filter(v => v).length === 2) {
|
||||||
|
return vals;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { getError } = this.field;
|
||||||
|
const { visible, onOk, onCancel } = this.props;
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Dialog
|
||||||
|
title="绑定角色"
|
||||||
|
visible={visible}
|
||||||
|
onOk={() => {
|
||||||
|
const vals = this.check();
|
||||||
|
if (vals) {
|
||||||
|
onOk(vals).then(() => onCancel());
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
onClose={onCancel}
|
||||||
|
onCancel={onCancel}
|
||||||
|
afterClose={() => this.field.reset()}
|
||||||
|
>
|
||||||
|
<Form style={{ width: 400 }} {...formItemLayout} field={this.field}>
|
||||||
|
<FormItem label="角色名" required help={getError('role')}>
|
||||||
|
<Input name="role" trim placeholder="Please Enter Role" />
|
||||||
|
</FormItem>
|
||||||
|
<FormItem label="用户名" required help={getError('username')}>
|
||||||
|
<Input name="username" placeholder="Please Enter Username" />
|
||||||
|
</FormItem>
|
||||||
|
</Form>
|
||||||
|
</Dialog>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default NewRole;
|
@ -0,0 +1,138 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { Button, Field, Form, Input, Dialog, Pagination, Table, ConfigProvider } from '@alifd/next';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { getRoles, createRole, deleteRole } from '../../../reducers/authority';
|
||||||
|
import RegionGroup from '../../../components/RegionGroup';
|
||||||
|
import NewRole from './NewRole';
|
||||||
|
|
||||||
|
import './RolesManagement.scss';
|
||||||
|
|
||||||
|
const FormItem = Form.Item;
|
||||||
|
|
||||||
|
const formItemLayout = {
|
||||||
|
labelCol: { fixedSpan: 3 },
|
||||||
|
wrapperCol: { span: 20 },
|
||||||
|
};
|
||||||
|
|
||||||
|
@connect(state => ({ roles: state.authority.roles }), { getRoles })
|
||||||
|
@ConfigProvider.config
|
||||||
|
class RolesManagement extends React.Component {
|
||||||
|
static displayName = 'RolesManagement';
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
locale: PropTypes.object,
|
||||||
|
roles: PropTypes.object,
|
||||||
|
getRoles: PropTypes.func,
|
||||||
|
};
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
loading: true,
|
||||||
|
pageNo: 1,
|
||||||
|
pageSize: 9,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.getRoles();
|
||||||
|
}
|
||||||
|
|
||||||
|
getRoles() {
|
||||||
|
const { pageNo, pageSize } = this.state;
|
||||||
|
this.props
|
||||||
|
.getRoles({ pageNo, pageSize })
|
||||||
|
.then(() => {
|
||||||
|
if (this.state.loading) {
|
||||||
|
this.setState({ loading: false });
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(() => this.setState({ loading: false }));
|
||||||
|
}
|
||||||
|
|
||||||
|
colseCreateRole() {
|
||||||
|
this.setState({ createRoleVisible: false });
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { roles } = this.props;
|
||||||
|
const { loading, pageSize, pageNo, createRoleVisible, passwordResetUser } = this.state;
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<RegionGroup left={'角色管理'} />
|
||||||
|
<div className="filter-panel">
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
className="create-user-btn"
|
||||||
|
onClick={() => this.setState({ createRoleVisible: true })}
|
||||||
|
>
|
||||||
|
绑定角色
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
<Table dataSource={roles.pageItems} loading={loading} maxBodyHeight={476} fixedHeader>
|
||||||
|
<Table.Column title="角色名" dataIndex="role" />
|
||||||
|
<Table.Column title="用户名" dataIndex="username" />
|
||||||
|
<Table.Column
|
||||||
|
title="操作"
|
||||||
|
dataIndex="username"
|
||||||
|
cell={(value, index, record) => (
|
||||||
|
<>
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
warning
|
||||||
|
onClick={() =>
|
||||||
|
Dialog.confirm({
|
||||||
|
title: '确认',
|
||||||
|
content: '是否要删除该角色?',
|
||||||
|
onOk: () =>
|
||||||
|
deleteRole(record).then(() =>
|
||||||
|
this.setState({ pageNo: 1 }, () => this.getRoles())
|
||||||
|
),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
>
|
||||||
|
刪除
|
||||||
|
</Button>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</Table>
|
||||||
|
{roles.totalCount > pageSize && (
|
||||||
|
<Pagination
|
||||||
|
className="users-pagination"
|
||||||
|
current={pageNo}
|
||||||
|
total={roles.totalCount}
|
||||||
|
pageSize={pageSize}
|
||||||
|
onChange={pageNo => this.setState({ pageNo }, () => this.getRoles())}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<NewRole
|
||||||
|
visible={createRoleVisible}
|
||||||
|
onOk={role =>
|
||||||
|
createRole(role).then(res => {
|
||||||
|
this.getRoles();
|
||||||
|
return res;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
onCancel={() => this.colseCreateRole()}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default RolesManagement;
|
@ -0,0 +1,12 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
@ -0,0 +1,16 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import RolesManagement from './RolesManagement';
|
||||||
|
|
||||||
|
export default RolesManagement;
|
@ -0,0 +1,97 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import {
|
||||||
|
Button,
|
||||||
|
Field,
|
||||||
|
Form,
|
||||||
|
Input,
|
||||||
|
Dialog,
|
||||||
|
Pagination,
|
||||||
|
Table,
|
||||||
|
ConfigProvider,
|
||||||
|
// Field,
|
||||||
|
} from '@alifd/next';
|
||||||
|
import './UserManagement.scss';
|
||||||
|
|
||||||
|
const FormItem = Form.Item;
|
||||||
|
|
||||||
|
const formItemLayout = {
|
||||||
|
labelCol: { fixedSpan: 3 },
|
||||||
|
wrapperCol: { span: 20 },
|
||||||
|
};
|
||||||
|
|
||||||
|
@ConfigProvider.config
|
||||||
|
class NewUser extends React.Component {
|
||||||
|
static displayName = 'NewUser';
|
||||||
|
|
||||||
|
field = new Field(this);
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
locale: PropTypes.object,
|
||||||
|
visible: PropTypes.bool,
|
||||||
|
};
|
||||||
|
|
||||||
|
check() {
|
||||||
|
const errors = {
|
||||||
|
username: '用户名不能为空!',
|
||||||
|
password: '密码不能为空!',
|
||||||
|
};
|
||||||
|
const vals = ['username', 'password'].map(key => {
|
||||||
|
const val = this.field.getValue(key);
|
||||||
|
if (!val) {
|
||||||
|
this.field.setError(key, errors[key]);
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
});
|
||||||
|
if (vals.filter(v => v).length === 2) {
|
||||||
|
return vals;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { getError } = this.field;
|
||||||
|
const { visible, onOk, onCancel } = this.props;
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Dialog
|
||||||
|
title="创建用户"
|
||||||
|
visible={visible}
|
||||||
|
onOk={() => {
|
||||||
|
const vals = this.check();
|
||||||
|
if (vals) {
|
||||||
|
onOk(vals).then(() => onCancel());
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
onClose={onCancel}
|
||||||
|
onCancel={onCancel}
|
||||||
|
afterClose={() => this.field.reset()}
|
||||||
|
>
|
||||||
|
<Form style={{ width: 400 }} {...formItemLayout} field={this.field}>
|
||||||
|
<FormItem label="用户名" required help={getError('username')}>
|
||||||
|
<Input name="username" trim placeholder="Please Enter Username" />
|
||||||
|
</FormItem>
|
||||||
|
<FormItem label="密码" required help={getError('password')}>
|
||||||
|
<Input name="password" htmlType="password" placeholder="Please Enter Password" />
|
||||||
|
</FormItem>
|
||||||
|
</Form>
|
||||||
|
</Dialog>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default NewUser;
|
@ -0,0 +1,94 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import {
|
||||||
|
Button,
|
||||||
|
Field,
|
||||||
|
Form,
|
||||||
|
Input,
|
||||||
|
Dialog,
|
||||||
|
Pagination,
|
||||||
|
Table,
|
||||||
|
ConfigProvider,
|
||||||
|
// Field,
|
||||||
|
} from '@alifd/next';
|
||||||
|
import './UserManagement.scss';
|
||||||
|
|
||||||
|
const FormItem = Form.Item;
|
||||||
|
|
||||||
|
const formItemLayout = {
|
||||||
|
labelCol: { fixedSpan: 3 },
|
||||||
|
wrapperCol: { span: 20 },
|
||||||
|
};
|
||||||
|
|
||||||
|
@ConfigProvider.config
|
||||||
|
class PasswordReset extends React.Component {
|
||||||
|
static displayName = 'PasswordReset';
|
||||||
|
|
||||||
|
field = new Field(this);
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
locale: PropTypes.object,
|
||||||
|
visible: PropTypes.bool,
|
||||||
|
};
|
||||||
|
|
||||||
|
check() {
|
||||||
|
const errors = { password: '密码不能为空!' };
|
||||||
|
const vals = ['password'].map(key => {
|
||||||
|
const val = this.field.getValue(key);
|
||||||
|
if (!val) {
|
||||||
|
this.field.setError(key, errors[key]);
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
});
|
||||||
|
if (vals.filter(v => v).length === 1) {
|
||||||
|
return [this.props.username, ...vals];
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { getError } = this.field;
|
||||||
|
const { username, onOk, onCancel } = this.props;
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Dialog
|
||||||
|
title="密码重置"
|
||||||
|
visible={username}
|
||||||
|
onOk={() => {
|
||||||
|
const vals = this.check();
|
||||||
|
if (vals) {
|
||||||
|
onOk(vals).then(() => onCancel());
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
onClose={onCancel}
|
||||||
|
onCancel={onCancel}
|
||||||
|
afterClose={() => this.field.reset()}
|
||||||
|
>
|
||||||
|
<Form style={{ width: 400 }} {...formItemLayout} field={this.field}>
|
||||||
|
<FormItem label="用户名" required>
|
||||||
|
<p>{username}</p>
|
||||||
|
</FormItem>
|
||||||
|
<FormItem label="密码" required help={getError('password')}>
|
||||||
|
<Input name="password" htmlType="password" placeholder="Please Enter Password" />
|
||||||
|
</FormItem>
|
||||||
|
</Form>
|
||||||
|
</Dialog>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PasswordReset;
|
@ -0,0 +1,161 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { Button, Field, Form, Input, Dialog, Pagination, Table, ConfigProvider } from '@alifd/next';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { getUsers, createUser, deleteUser, passwordReset } from '../../../reducers/authority';
|
||||||
|
import RegionGroup from '../../../components/RegionGroup';
|
||||||
|
import NewUser from './NewUser';
|
||||||
|
import PasswordReset from './PasswordReset';
|
||||||
|
|
||||||
|
import './UserManagement.scss';
|
||||||
|
|
||||||
|
const FormItem = Form.Item;
|
||||||
|
|
||||||
|
const formItemLayout = {
|
||||||
|
labelCol: { fixedSpan: 3 },
|
||||||
|
wrapperCol: { span: 20 },
|
||||||
|
};
|
||||||
|
|
||||||
|
@connect(state => ({ users: state.authority.users }), { getUsers })
|
||||||
|
@ConfigProvider.config
|
||||||
|
class UserManagement extends React.Component {
|
||||||
|
static displayName = 'UserManagement';
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
locale: PropTypes.object,
|
||||||
|
users: PropTypes.object,
|
||||||
|
getUsers: PropTypes.func,
|
||||||
|
createUser: PropTypes.func,
|
||||||
|
};
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
loading: true,
|
||||||
|
pageNo: 1,
|
||||||
|
pageSize: 9,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.getUsers();
|
||||||
|
}
|
||||||
|
|
||||||
|
getUsers() {
|
||||||
|
const { pageNo, pageSize } = this.state;
|
||||||
|
this.props
|
||||||
|
.getUsers({ pageNo, pageSize })
|
||||||
|
.then(() => {
|
||||||
|
if (this.state.loading) {
|
||||||
|
this.setState({ loading: false });
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(() => this.setState({ loading: false }));
|
||||||
|
}
|
||||||
|
|
||||||
|
colseCreateUser() {
|
||||||
|
this.setState({ createUserVisible: false });
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { users } = this.props;
|
||||||
|
const { loading, pageSize, pageNo, createUserVisible, passwordResetUser } = this.state;
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<RegionGroup left={'用户管理'} />
|
||||||
|
<div className="filter-panel">
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
className="create-user-btn"
|
||||||
|
onClick={() => this.setState({ createUserVisible: true })}
|
||||||
|
>
|
||||||
|
创建用户
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
<Table dataSource={users.pageItems} loading={loading} maxBodyHeight={476} fixedHeader>
|
||||||
|
<Table.Column title="用户名" dataIndex="username" />
|
||||||
|
<Table.Column
|
||||||
|
title="密码"
|
||||||
|
dataIndex="password"
|
||||||
|
cell={value => value.replace(/\S/g, '*')}
|
||||||
|
/>
|
||||||
|
<Table.Column
|
||||||
|
title="操作"
|
||||||
|
dataIndex="username"
|
||||||
|
cell={username => (
|
||||||
|
<>
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
onClick={() => this.setState({ passwordResetUser: username })}
|
||||||
|
>
|
||||||
|
修改
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
warning
|
||||||
|
onClick={() =>
|
||||||
|
Dialog.confirm({
|
||||||
|
title: '确认',
|
||||||
|
content: '是否要删除该用户?',
|
||||||
|
onOk: () =>
|
||||||
|
deleteUser(username).then(() =>
|
||||||
|
this.setState({ pageNo: 1 }, () => this.getUsers())
|
||||||
|
),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
>
|
||||||
|
刪除
|
||||||
|
</Button>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</Table>
|
||||||
|
{users.totalCount > pageSize && (
|
||||||
|
<Pagination
|
||||||
|
className="users-pagination"
|
||||||
|
current={pageNo}
|
||||||
|
total={users.totalCount}
|
||||||
|
pageSize={pageSize}
|
||||||
|
onChange={pageNo => this.setState({ pageNo }, () => this.getUsers())}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<NewUser
|
||||||
|
visible={createUserVisible}
|
||||||
|
onOk={user =>
|
||||||
|
createUser(user).then(res => {
|
||||||
|
this.setState({ pageNo: 1 }, () => this.getUsers());
|
||||||
|
return res;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
onCancel={() => this.colseCreateUser()}
|
||||||
|
/>
|
||||||
|
<PasswordReset
|
||||||
|
username={passwordResetUser}
|
||||||
|
onOk={user =>
|
||||||
|
passwordReset(user).then(res => {
|
||||||
|
this.getUsers();
|
||||||
|
return res;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
onCancel={() => this.setState({ passwordResetUser: undefined })}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default UserManagement;
|
@ -0,0 +1,18 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
@import '../authority.scss';
|
||||||
|
|
||||||
|
.users-pagination {
|
||||||
|
float: right;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import UserManagement from './UserManagement';
|
||||||
|
|
||||||
|
export default UserManagement;
|
@ -0,0 +1,17 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.filter-panel {
|
||||||
|
text-align: right;
|
||||||
|
padding: 10px 0;
|
||||||
|
}
|
@ -1095,7 +1095,7 @@ class ConfigurationManagement extends React.Component {
|
|||||||
render() {
|
render() {
|
||||||
const { locale = {} } = this.props;
|
const { locale = {} } = this.props;
|
||||||
return (
|
return (
|
||||||
<div>
|
<>
|
||||||
<BatchHandle ref={ref => (this.batchHandle = ref)} />
|
<BatchHandle ref={ref => (this.batchHandle = ref)} />
|
||||||
<Loading
|
<Loading
|
||||||
shape={'flower'}
|
shape={'flower'}
|
||||||
@ -1107,7 +1107,7 @@ class ConfigurationManagement extends React.Component {
|
|||||||
<div className={this.state.hasdash ? 'dash-page-container' : ''}>
|
<div className={this.state.hasdash ? 'dash-page-container' : ''}>
|
||||||
<div
|
<div
|
||||||
className={this.state.hasdash ? 'dash-left-container' : ''}
|
className={this.state.hasdash ? 'dash-left-container' : ''}
|
||||||
style={{ position: 'relative', padding: 10 }}
|
style={{ position: 'relative' }}
|
||||||
>
|
>
|
||||||
<div style={{ display: this.inApp ? 'none' : 'block', marginTop: -15 }}>
|
<div style={{ display: this.inApp ? 'none' : 'block', marginTop: -15 }}>
|
||||||
<RegionGroup
|
<RegionGroup
|
||||||
@ -1359,7 +1359,7 @@ class ConfigurationManagement extends React.Component {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</Loading>
|
</Loading>
|
||||||
</div>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,4 @@
|
|||||||
|
|
||||||
.next-pagination-size-selector{
|
.next-pagination-size-selector{
|
||||||
position: static !important;
|
position: static !important;
|
||||||
}
|
}
|
||||||
.next-overlay-inner{
|
|
||||||
top:154px !important;
|
|
||||||
}
|
|
@ -183,7 +183,7 @@ class ListeningToQuery extends React.Component {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
return (
|
return (
|
||||||
<div style={{ padding: 10 }}>
|
<>
|
||||||
<Loading
|
<Loading
|
||||||
shape="flower"
|
shape="flower"
|
||||||
style={{ position: 'relative' }}
|
style={{ position: 'relative' }}
|
||||||
@ -320,7 +320,7 @@ class ListeningToQuery extends React.Component {
|
|||||||
,
|
,
|
||||||
</div>
|
</div>
|
||||||
</Loading>
|
</Loading>
|
||||||
</div>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -301,7 +301,7 @@ class NameSpace extends React.Component {
|
|||||||
namespaceOperation,
|
namespaceOperation,
|
||||||
} = locale;
|
} = locale;
|
||||||
return (
|
return (
|
||||||
<div style={{ padding: 10 }} className="clearfix">
|
<>
|
||||||
<RegionGroup left={namespace} />
|
<RegionGroup left={namespace} />
|
||||||
<div className="fusion-demo">
|
<div className="fusion-demo">
|
||||||
<Loading
|
<Loading
|
||||||
@ -348,7 +348,7 @@ class NameSpace extends React.Component {
|
|||||||
<EditorNameSpace ref={this.editgroup} getNameSpaces={this.getNameSpaces.bind(this)} />
|
<EditorNameSpace ref={this.editgroup} getNameSpaces={this.getNameSpaces.bind(this)} />
|
||||||
</Loading>
|
</Loading>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,15 +24,8 @@ class Welcome extends React.Component {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { functionMode } = this.props;
|
const { functionMode } = this.props;
|
||||||
return (
|
const path = functionMode === 'naming' ? 'serviceManagement' : 'configurationManagement';
|
||||||
<div>
|
return <>{functionMode !== '' && <Redirect to={`/${path}`} />}</>;
|
||||||
{functionMode !== '' && (
|
|
||||||
<Redirect
|
|
||||||
to={`/${functionMode === 'naming' ? 'serviceManagement' : 'configurationManagement'}`}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,96 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 1999-2018 Alibaba Group Holding Ltd.
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Message } from '@alifd/next';
|
||||||
|
import request from '../utils/request';
|
||||||
|
import { UPDATE_USER, SIGN_IN, USER_LIST, ROLE_LIST } from '../constants';
|
||||||
|
|
||||||
|
const initialState = {
|
||||||
|
users: {
|
||||||
|
totalCount: 0,
|
||||||
|
pageNumber: 1,
|
||||||
|
pagesAvailable: 1,
|
||||||
|
pageItems: [],
|
||||||
|
},
|
||||||
|
roles: {},
|
||||||
|
};
|
||||||
|
|
||||||
|
const successMsg = res => {
|
||||||
|
if (res.code === 200) {
|
||||||
|
Message.success(res.message);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户列表
|
||||||
|
* @param {*} params
|
||||||
|
*/
|
||||||
|
const getUsers = params => dispatch =>
|
||||||
|
request.get('v1/auth/users', { params }).then(data => dispatch({ type: USER_LIST, data }));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建用户
|
||||||
|
* @param {*} param0
|
||||||
|
*/
|
||||||
|
const createUser = ([username, password]) =>
|
||||||
|
request.post('v1/auth/users', { username, password }).then(res => successMsg(res));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除用户
|
||||||
|
* @param {*} username
|
||||||
|
*/
|
||||||
|
const deleteUser = username =>
|
||||||
|
request.delete('v1/auth/users', { params: { username } }).then(res => successMsg(res));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重置密码
|
||||||
|
* @param {*} param0
|
||||||
|
*/
|
||||||
|
const passwordReset = ([username, newPassword]) =>
|
||||||
|
request.put('v1/auth/users', { username, newPassword }).then(res => successMsg(res));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 角色列表
|
||||||
|
* @param {*} params
|
||||||
|
*/
|
||||||
|
|
||||||
|
const getRoles = params => dispatch =>
|
||||||
|
request.get('v1/auth/roles', { params }).then(data => dispatch({ type: ROLE_LIST, data }));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建角色
|
||||||
|
* @param {*} param0
|
||||||
|
*/
|
||||||
|
const createRole = ([role, username]) =>
|
||||||
|
request.post('v1/auth/roles', { role, username }).then(res => successMsg(res));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除角色
|
||||||
|
* @param {*} param0
|
||||||
|
*/
|
||||||
|
const deleteRole = role =>
|
||||||
|
request.delete('v1/auth/roles', { params: role }).then(res => successMsg(res));
|
||||||
|
|
||||||
|
export default (state = initialState, action) => {
|
||||||
|
switch (action.type) {
|
||||||
|
case USER_LIST:
|
||||||
|
return { ...state, users: { ...action.data } };
|
||||||
|
case ROLE_LIST:
|
||||||
|
return { ...state, roles: { ...action.data } };
|
||||||
|
default:
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export { getUsers, createUser, deleteUser, passwordReset, getRoles, createRole, deleteRole };
|
@ -14,5 +14,6 @@
|
|||||||
import locale from './locale';
|
import locale from './locale';
|
||||||
import base from './base';
|
import base from './base';
|
||||||
import subscribers from './subscribers';
|
import subscribers from './subscribers';
|
||||||
|
import authority from './authority';
|
||||||
|
|
||||||
export default { locale, base, subscribers };
|
export default { locale, base, subscribers, authority };
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
import qs from 'qs';
|
||||||
import { Message } from '@alifd/next';
|
import { Message } from '@alifd/next';
|
||||||
// import { SUCCESS_RESULT_CODE } from '../constants';
|
// import { SUCCESS_RESULT_CODE } from '../constants';
|
||||||
|
|
||||||
@ -7,6 +8,21 @@ const API_GENERAL_ERROR_MESSAGE = 'Request error, please try again later!';
|
|||||||
const request = () => {
|
const request = () => {
|
||||||
const instance = axios.create();
|
const instance = axios.create();
|
||||||
|
|
||||||
|
instance.interceptors.request.use(
|
||||||
|
function(config) {
|
||||||
|
if (['post', 'put'].includes(config.method)) {
|
||||||
|
config.data = qs.stringify(config.data);
|
||||||
|
config.headers = {
|
||||||
|
'Content-Type': 'application/x-www-form-urlencoded',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return config;
|
||||||
|
},
|
||||||
|
function(error) {
|
||||||
|
return Promise.reject(error);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
instance.interceptors.response.use(
|
instance.interceptors.response.use(
|
||||||
response => {
|
response => {
|
||||||
const { success, resultCode, resultMessage = API_GENERAL_ERROR_MESSAGE } = response.data;
|
const { success, resultCode, resultMessage = API_GENERAL_ERROR_MESSAGE } = response.data;
|
||||||
|
Loading…
Reference in New Issue
Block a user