Commit eaa6b851 authored by 李腾's avatar 李腾

feat: 新增系统管理模块代码

parent 0842ec3b
...@@ -12,5 +12,6 @@ module.exports = { ...@@ -12,5 +12,6 @@ module.exports = {
'no-plusplus': ['off'], 'no-plusplus': ['off'],
'@typescript-eslint/camelcase': ['off'], '@typescript-eslint/camelcase': ['off'],
'@typescript-eslint/no-unused-vars': ['off'], '@typescript-eslint/no-unused-vars': ['off'],
'import/no-unresolved': 0,
}, },
}; };
...@@ -229,6 +229,36 @@ export default { ...@@ -229,6 +229,36 @@ export default {
name: 'ServiceGoods', name: 'ServiceGoods',
component: './ServiceGoods/index', component: './ServiceGoods/index',
}, },
{
title: '商户管理后台-账号管理',
path: '/systemManage/account',
name: 'systemManageAccount',
component: './systemManage/Account',
},
{
title: '商户管理后台-账号管理-用户信息',
path: '/systemManage/account/userInfo',
name: 'accountUserInfo',
component: './systemManage/Account/UserInfo',
},
{
title: '商户管理后台-角色管理',
path: '/systemManage/role',
name: 'systemManageRole',
component: './systemManage/Role',
},
{
title: '商户管理后台-角色管理-角色信息',
path: '/systemManage/role/roleInfo',
name: 'roleInfo',
component: './systemManage/Role/RoleInfo',
},
{
title: '商户管理后台-日志管理',
path: '/systemManage/log',
name: 'systemManageLog',
component: './systemManage/Log',
},
{ {
component: './404', component: './404',
}, },
......
...@@ -2,19 +2,19 @@ const isProduction = process.env.NODE_ENV === 'production'; ...@@ -2,19 +2,19 @@ const isProduction = process.env.NODE_ENV === 'production';
const isPre = process.env.PRE_ENV === 'pre'; const isPre = process.env.PRE_ENV === 'pre';
const envAPi = { const envAPi = {
api: 'https://security.q-gp.com', //'https://security-xyqb.liangkebang.net', api: 'https://security-sc.liangkebang.net',
kdspOpApi: 'https://sc-merchant-api-xyqb.liangkebang.net', kdspOpApi: 'https://sc-merchant-api-sc.liangkebang.net',
kdspApi: 'https://sc-merchant-api-xyqb.liangkebang.net', kdspApi: 'https://sc-merchant-api-sc.liangkebang.net',
goodsApi: 'https://sc-merchant-api-xyqb.liangkebang.net', goodsApi: 'https://sc-merchant-api-sc.liangkebang.net',
// kdspOpApi: 'https://kdsp-operation-xyqb.liangkebang.net', // kdspOpApi: 'https://kdsp-operation-xyqb.liangkebang.net',
// kdspApi: 'https://sc-op-api-xyqb.liangkebang.net', // kdspApi: 'https://sc-op-api-xyqb.liangkebang.net',
// goodsApi: 'https://sc-op-api-xyqb.liangkebang.net', // goodsApi: 'https://sc-op-api-xyqb.liangkebang.net',
querysApi: 'https://sc-settlement-api-xyqb.liangkebang.net', querysApi: 'https://sc-settlement-api-sc.liangkebang.net',
// goodsApi: '//192.168.188.111:7000', // goodsApi: '//192.168.188.111:7000',
prologueDomain: 'https://mall-xyqb.liangkebang.net', prologueDomain: 'https://mall-sc.liangkebang.net',
// qiniuHost: 'https://appsync.lkbang.net', // qiniuHost: 'https://appsync.lkbang.net',
qiniuHost: 'https://kdspstatic.q-gp.com/', qiniuHost: 'https://kdspstatic.q-gp.com/',
opapiHost: 'https://opapi-xyqb.liangkebang.net', opapiHost: 'https://opapi-sc.liangkebang.net',
}; };
const prodApi = { const prodApi = {
......
import { getMenuData } from '@/services/menu'; import { getMenuData } from '@/services/menu';
export const filterPermission = list => {
const permissionData = {};
const filterArr = (arr, v) => {
arr.forEach(item => {
permissionData[item.node.code] = true;
if (item.childNodes.length) {
filterArr(item.childNodes, v);
}
});
};
filterArr(list);
return permissionData;
};
const MenuModel = { const MenuModel = {
namespace: 'menu', namespace: 'menu',
state: { state: {
...@@ -11,11 +25,13 @@ const MenuModel = { ...@@ -11,11 +25,13 @@ const MenuModel = {
key: '', key: '',
}, },
], ],
permissions: {},
}, },
effects: { effects: {
*getMenuData({ payload }, { put, call }) { *getMenuData({ payload }, { put, call }) {
const response = yield call(getMenuData, payload); const response = yield call(getMenuData, payload);
if (response.code === 2000) { if (response.code === 2000) {
window.localStorage.setItem('permissions', JSON.stringify(response.data));
// 拿到数据后response.data后组装成新的数据复制给menuData // 拿到数据后response.data后组装成新的数据复制给menuData
yield put({ yield put({
type: 'save', type: 'save',
...@@ -30,7 +46,7 @@ const MenuModel = { ...@@ -30,7 +46,7 @@ const MenuModel = {
const value = []; const value = [];
const data = [...tableData]; const data = [...tableData];
data data
.filter(item => item.node && item.node.uri !== '/systemManage') .filter(item => item.node && item.node.type.value < 3)
.forEach(item => { .forEach(item => {
let obj = {}; let obj = {};
obj = { ...item.node }; obj = { ...item.node };
...@@ -47,7 +63,17 @@ const MenuModel = { ...@@ -47,7 +63,17 @@ const MenuModel = {
return value; return value;
}; };
const menuData = initializationData(payload); const menuData = initializationData(payload);
return { ...state, menuData };
// 设置全局权限数据rules
let { permissions } = state;
if (JSON.stringify(permissions) === '{}') {
const currentPermissions = localStorage.getItem('permissions');
if (currentPermissions) {
const arr = JSON.parse(currentPermissions);
permissions = filterPermission(arr);
}
}
return { ...state, menuData, permissions };
}, },
}, },
}; };
......
import React, { useRef, useState, useEffect } from 'react';
import { Input, Checkbox, Button, notification } from 'antd';
import { Form } from '@ant-design/compatible';
import { PageHeaderWrapper } from '@ant-design/pro-layout';
import RolePermissionsModal from '../components/RolePermissionsModal';
import style from './index.less';
import { getRoleList, addUser } from '../../service';
import { shopGetBySupplierId } from '@/pages/ServiceGoods/service';
const AddUser = props => {
const { getFieldDecorator, validateFields, getFieldValue } = props.form;
const { id } = props.location.query;
const [title, setTitle] = useState('新增用户');
const [inputType, setInputType] = useState('text');
const [confirmInputType, setConfirmInputType] = useState('text');
const [roleList, setRoleList] = useState([]);
const [supplierList, setSupplierList] = useState([]);
const rolePermissionsModalRef = useRef();
// 表单布局
const formLayout = {
labelCol: { span: 4 },
wrapperCol: { span: 12 },
};
const btnLayout = {
wrapperCol: { offset: 4, span: 12 },
};
const handleConfirmPassword = (rule, value, callback) => {
if (value && value !== getFieldValue('password')) {
callback('两次输入不一致!');
}
callback();
};
// 表单验证
const formRules = {
account: [{ required: true, message: '请设置登录用户名' }],
name: [{ required: true, message: '请输入姓名' }],
password: [
{ required: true, message: '请设置密码' },
{
pattern: /^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[\W_]).{13,18}$/g,
message: '密码格式错误',
},
],
confirmPassword: [
{ required: true, message: '请确认登录密码' },
{ validator: handleConfirmPassword, message: '两次密码不一致' },
],
role: [{ required: true, type: 'array', message: '请选择用户角色' }],
};
// 角色权限 modal
const openRolePermissionsModal = record => {
rolePermissionsModalRef.current.open(record);
};
// 获取所有门店列表
const getAllSupplier = async () => {
const res = await shopGetBySupplierId();
console.log(res);
if (res.code !== 2000) {
notification.warning({
message: res.detail,
});
return;
}
setSupplierList(res.data);
};
// 获取所有角色列表
const getAllRoleList = async () => {
const params = {
page: 1,
size: 1000,
};
const res = await getRoleList(params);
if (res.code !== 2000) {
notification.warning({ message: res.detail });
return;
}
console.log(res);
const { content } = res.data;
setRoleList(content);
};
// 用户角色多选框
const userRoleCheckbox = () =>
roleList.map(item => (
<Checkbox value={item.id}>
<a
onClick={e => {
e.preventDefault();
openRolePermissionsModal(item);
}}
>
{item.name}
</a>
</Checkbox>
));
// 表单验证辅助函数
const rulesHandler = (field, initialValue = '') => ({
rules: formRules[field] || [],
initialValue,
});
// 提交
const onSubmit = () => {
validateFields(async (err, fieldsValue) => {
console.log(err, fieldsValue);
if (err) {
return;
}
// 提交
console.log(fieldsValue);
const params = {
...fieldsValue,
};
const res = await addUser(params);
});
};
// 处理初始化密码自动填充函数
const handlePasswordChange = (e, fn) => {
if (e.target.value) {
fn('password');
} else {
fn('text');
}
};
useEffect(() => {
getAllRoleList();
getAllSupplier();
if (id) {
setTitle('编辑用户');
}
}, []);
return (
<PageHeaderWrapper title={title}>
<div className={style['user-info']}>
<Form className={style['user-info--form']} {...formLayout}>
<Form.Item label="用户名" extra="限35字符以内,限英文/数字/“@”“ .”">
{getFieldDecorator('account', rulesHandler('account'))(
<Input placeholder="请输入用户名" maxLength={35} />,
)}
</Form.Item>
<Form.Item label="姓名" extra="限10字符以内">
{getFieldDecorator('name', rulesHandler('name'))(
<Input placeholder="请输入用户姓名" />,
)}
</Form.Item>
<Form.Item label="初始密码" extra="限13-18字符,包含大小写字母、数字和特殊字符">
{getFieldDecorator('password', rulesHandler('password'))(
<Input
type={inputType}
onChange={e => handlePasswordChange(e, setInputType)}
placeholder="请设置登录密码"
/>,
)}
</Form.Item>
<Form.Item label="确认密码">
{getFieldDecorator('confirmPassword', rulesHandler('confirmPassword'))(
<Input
type={confirmInputType}
onChange={e => handlePasswordChange(e, setConfirmInputType)}
placeholder="请确认登录密码"
/>,
)}
</Form.Item>
<Form.Item label="选择门店" extra="仅限POP商家设置">
{getFieldDecorator('store', rulesHandler('store', []))(
supplierList.length ? (
<Checkbox.Group style={{ width: '100%' }}>
<Checkbox value="1">门店1</Checkbox>
<Checkbox value="2">门店2</Checkbox>
</Checkbox.Group>
) : (
<div>暂无门店信息</div>
),
)}
</Form.Item>
<Form.Item label="用户角色">
{getFieldDecorator('organization', rulesHandler('organization'))(
<Checkbox.Group style={{ width: '100%' }}>{userRoleCheckbox()}</Checkbox.Group>,
)}
</Form.Item>
<Form.Item {...btnLayout}>
<Button type="default" onClick={() => window.history.back()}>
返回
</Button>
<Button className={style['submit-button']} type="primary" onClick={onSubmit}>
提交
</Button>
</Form.Item>
</Form>
</div>
<RolePermissionsModal ref={rolePermissionsModalRef} />
</PageHeaderWrapper>
);
};
export default Form.create({})(AddUser);
.user-info {
padding: 30px 0;
background: #fff;
&--form {
width: 1200px;
}
.submit-button {
margin-left: 20px;
}
}
import React, { forwardRef, useImperativeHandle, useState, useRef, useEffect } from 'react';
import { Modal, Input } from 'antd';
import { Form } from '@ant-design/compatible';
import { resetPassword } from '../../../service';
const FormComponent = props => {
const { record = {}, form } = props;
const { getFieldDecorator, setFieldsValue, getFieldValue } = form;
const [inputType, setInputType] = useState('text');
const [confirmInputType, setConfirmInputType] = useState('text');
const handlepassword = (rule, value, callback) => {
if (value && value !== getFieldValue('password')) {
callback('两次输入不一致!');
}
// Note: 必须总是返回一个 callback,否则 validateFieldsAndScroll 无法响应
callback();
};
// 处理初始化密码自动填充函数
const handlePasswordChange = (e, fn) => {
if (e.target.value) {
fn('password');
} else {
fn('text');
}
};
const formLayout = {
labelCol: { span: 4 },
wrapperCol: { span: 20 },
};
const formRules = {
newPassword: [
{ required: true, message: '请设置新密码' },
{
pattern: /^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[\W_]).{13,18}$/g,
message: '密码格式错误',
},
],
password: [
{ required: true, message: '请确认新密码' },
{ validator: handlepassword, message: '两次密码不一致' },
],
};
const rulesHandler = name => ({
rules: formRules[name],
});
useEffect(() => {
setFieldsValue(record);
}, [record]);
return (
<Form {...formLayout}>
<Form.Item label="用户名">{record.name}</Form.Item>
<Form.Item label="新密码" extra="限13-18字符,包含大小写字母、数字和特殊字符">
{getFieldDecorator('newPassword', rulesHandler('newPassword'))(
<Input
type={inputType}
onChange={e => handlePasswordChange(e, setInputType)}
placeholder="请设置新密码"
/>,
)}
</Form.Item>
<Form.Item label="确认密码">
{getFieldDecorator('password', rulesHandler('password'))(
<Input
type={confirmInputType}
onChange={e => handlePasswordChange(e, setConfirmInputType)}
placeholder="请确认新密码"
/>,
)}
</Form.Item>
</Form>
);
};
const FormWarpper = Form.create({})(forwardRef(FormComponent));
const ResetPasswordModal = (props, ref) => {
const formRef = useRef();
const [visible, setVisible] = useState(false);
const [confirmLoading, setConfirmLoading] = useState(false);
const [record, setRecord] = useState({
name: '',
id: '',
});
const open = item => {
setVisible(true);
const { name, id } = item;
// 初始化数据
setRecord({
name,
id,
});
};
const onCancel = () => {
setVisible(false);
formRef.current.resetFields();
};
const onOk = () => {
formRef.current.validateFields(async (err, fieldsValue) => {
console.log('fieldsValue :>>', fieldsValue);
if (err) {
return;
}
setConfirmLoading(true);
const params = {
id: record.id,
...fieldsValue,
};
const res = await resetPassword();
setTimeout(() => {
setConfirmLoading(false);
onCancel();
}, 2000);
});
};
useImperativeHandle(ref, () => ({
open,
}));
const modalProps = {
title: '重置密码',
visible,
confirmLoading,
onCancel,
onOk,
};
return (
<Modal {...modalProps}>
<FormWarpper ref={formRef} record={record} />
</Modal>
);
};
export default forwardRef(ResetPasswordModal);
import React, { forwardRef, useImperativeHandle, useState } from 'react';
import { Modal } from 'antd';
import { RoleInfoComponent } from '../../../Role/RoleInfo';
const RolePermissionsModal = (props, ref) => {
const [visible, setVisible] = useState(false);
const [roleInfo, setRoleInfo] = useState({});
const open = record => {
setVisible(true);
console.log('record', record);
setRoleInfo(record);
};
const onCancel = () => {
setVisible(false);
};
useImperativeHandle(ref, () => ({
open,
}));
const modalProps = {
title: '查看角色',
visible,
footer: null,
onCancel,
};
const roleProps = {
id: roleInfo.id,
submittable: false,
readyonly: true,
};
console.log(roleProps);
return (
<>
{visible ? (
<Modal {...modalProps}>
<RoleInfoComponent {...roleProps} />
</Modal>
) : null}
</>
);
};
export default forwardRef(RolePermissionsModal);
import React, { forwardRef, useImperativeHandle, useState, useRef, useEffect } from 'react';
import { Modal, Select, notification } from 'antd';
import { Form } from '@ant-design/compatible';
import { userEnabled, userDisabled, userDelete } from '@/pages/systemManage/service';
const FormComponent = props => {
const { record = {}, form } = props;
const { getFieldDecorator, setFieldsValue } = form;
const formLayout = {
labelCol: { span: 4 },
wrapperCol: { span: 20 },
};
const formRules = {
status: [{ required: true, message: '' }],
};
useEffect(() => {
setFieldsValue(record);
}, [record]);
const rulesHandler = name => ({
rules: formRules[name],
});
return (
<Form {...formLayout}>
<Form.Item label="用户名">{record.name}</Form.Item>
<Form.Item label="状态">
{getFieldDecorator('status', rulesHandler('status'))(
<Select>
<Select.Option value={2}>使用中</Select.Option>
<Select.Option value={3}>已禁用</Select.Option>
{record.currentStatus === 2 ? '' : <Select.Option value={1}>已删除</Select.Option>}
</Select>,
)}
</Form.Item>
</Form>
);
};
const FormWarpper = Form.create({})(forwardRef(FormComponent));
const UpdateStatusModal = (props, ref) => {
const { reload } = props;
const formRef = useRef();
const [visible, setVisible] = useState(false);
const [confirmLoading, setConfirmLoading] = useState(false);
const [record, setRecord] = useState({
name: '',
status: '',
id: '',
});
const open = item => {
setVisible(true);
const { name, status, id } = item;
// 初始化数据,currentStatus 用来判断状态选项
setRecord({
name,
status: status.value,
id,
currentStatus: status.value,
});
};
const onCancel = () => {
setVisible(false);
setConfirmLoading(false);
formRef.current.resetFields();
};
const onOk = () => {
formRef.current.validateFields(async (err, fieldsValue) => {
console.log('fieldsValue :>>', fieldsValue);
if (err) {
return;
}
const apiName = {
1: userDelete,
2: userEnabled,
3: userDisabled,
};
const params = {
id: record.id,
};
setConfirmLoading(true);
const res = await apiName[fieldsValue.status](params);
if (res.code !== 2000) {
notification.warning({
message: res.detail,
});
setConfirmLoading(false);
return;
}
setConfirmLoading(false);
notification.success({
message: '保存成功',
});
reload();
onCancel();
});
};
useImperativeHandle(ref, () => ({
open,
}));
const modalProps = {
title: '修改状态',
visible,
confirmLoading,
onCancel,
onOk,
};
return (
<Modal {...modalProps}>
<FormWarpper ref={formRef} record={record} />
</Modal>
);
};
export default forwardRef(UpdateStatusModal);
import React from 'react';
import { Divider } from 'antd';
export const getColumns = props => {
const {
toUserInfo,
openRolePermissionsModal,
openUpdateStatusModal,
openResetPasswordModal,
} = props;
return [
{
title: '用户ID',
dataIndex: 'id',
},
{
title: '用户名',
dataIndex: 'account',
},
{
title: '姓名',
dataIndex: 'name',
},
{
title: '创建时间',
dataIndex: 'createTime',
hideInSearch: true,
},
{
title: '最后一次登录时间',
dataIndex: 'updateTime',
hideInSearch: true,
},
{
title: '角色',
dataIndex: 'creator',
render: (value, record) => <a onClick={() => openRolePermissionsModal(record)}>{value}</a>,
},
{
title: '状态',
dataIndex: 'status',
width: 150,
initialValue: 'all',
valueEnum: {
all: { text: '全部', status: '' },
close: { text: '使用中', status: 0 },
running: { text: '已禁用', status: 1 },
online: { text: '已删除', status: 2 },
},
render: value => value.name,
},
{
title: '操作',
key: 'action',
width: 220,
hideInSearch: true,
render: (value, record) => (
<>
<a
onClick={() => {
toUserInfo(record);
}}
>
编辑
</a>
<Divider type="vertical" />
<a
onClick={() => {
openUpdateStatusModal(record);
}}
>
修改状态
</a>
<Divider type="vertical" />
<a
onClick={() => {
openResetPasswordModal(record);
}}
>
重置密码
</a>
</>
),
},
];
};
import React, { useRef, useState } from 'react';
import { useHistory } from 'react-router-dom';
import { Button, Divider } from 'antd';
import { PageHeaderWrapper } from '@ant-design/pro-layout';
import ProTable from '@ant-design/pro-table';
import { connect } from 'umi';
// data
import { getColumns } from './data';
// compoents
import RolePermissionsModal from './components/RolePermissionsModal';
import UpdateStatusModal from './components/UpdateStatusModal';
import ResetPasswordModal from './components/ResetPasswordModal';
// mock
import { getUserList } from '../service';
import { accountList } from '../mock/account';
const Account = props => {
const { permissions } = props;
const history = useHistory();
const actionRef = useRef();
const formRef = useRef();
const rolePermissionsModalRef = useRef();
const updateStatusModalRef = useRef();
const resetPasswordModal = useRef();
// 新增编辑
const toUserInfo = (record = {}) => {
const { id } = record;
history.push({
pathname: '/systemManage/account/userInfo',
query: {
id: 1,
},
});
};
// 角色权限 modal
const openRolePermissionsModal = record => {
rolePermissionsModalRef.current.open();
};
// 修改状态 modal
const openUpdateStatusModal = record => {
updateStatusModalRef.current.open(record);
};
// 重置密码 modal
const openResetPasswordModal = record => {
resetPasswordModal.current.open(record);
};
const reload = () => {
actionRef.current.reload();
};
// 获取列表配置
const columns = getColumns({
toUserInfo,
openRolePermissionsModal,
openUpdateStatusModal,
openResetPasswordModal,
});
// 表格属性
const tableProps = {
columns,
rowKey: 'id',
request: async params => {
console.log('搜索', params);
const { current: page, pageSize: size } = params;
const res = await getUserList({
page,
size,
});
const { content = [], totalElements } = res.data;
return {
data: content,
success: true,
total: totalElements,
};
},
toolBarRender: () => {
// TODO: 权限控制
if (permissions['010102']) {
return [
<Button type="primary" onClick={() => toUserInfo()}>
新增用户
</Button>,
];
}
return [];
},
};
// 搜索属性
const searchProps = {
collapsed: false,
collapseRender: () => null,
};
return (
<PageHeaderWrapper>
<ProTable
actionRef={actionRef}
formRef={formRef}
{...tableProps}
search={searchProps}
></ProTable>
<RolePermissionsModal ref={rolePermissionsModalRef} />
<UpdateStatusModal reload={reload} ref={updateStatusModalRef} />
<ResetPasswordModal reload={reload} ref={resetPasswordModal} />
</PageHeaderWrapper>
);
};
// export default Account;
export default connect(({ menu }) => ({
permissions: menu.permissions,
}))(Account);
import React, { useRef } from 'react';
import { useHistory } from 'react-router-dom';
import { Button, Divider } from 'antd';
import { PageHeaderWrapper } from '@ant-design/pro-layout';
import ProTable from '@ant-design/pro-table';
// mock
import { logList } from '../mock/log';
const columns = [
{
title: '操作人',
dataIndex: 'name',
},
{
title: '一级菜单',
dataIndex: 'menu',
},
{
title: '二级菜单',
dataIndex: 'subMenu',
},
{
title: '操作点',
dataIndex: 'status',
hideInSearch: true,
},
{
title: '操作时间',
hideInSearch: true,
dataIndex: 'actionTime',
},
{
title: '操作时间2',
hideInTable: true,
dataIndex: 'actionTime1',
valueType: 'dateRange',
},
{
title: '操作',
key: 'action',
hideInSearch: true,
render: () => (
<>
<a>查看</a>
</>
),
},
];
const SystemLog = props => {
const history = useHistory();
const actionRef = useRef();
const formRef = useRef();
const toUserInfo = (record = {}) => {
const { id } = record;
history.push({
pathname: '/SystemManage/Account/UserInfo',
query: {
id: 1,
},
});
};
// 表格属性
const tableProps = {
columns,
rowKey: 'id',
request: params => {
console.log('搜索', params);
return new Promise(resolve => {
setTimeout(() => {
resolve({
data: logList,
success: true,
});
}, 2000);
});
},
search: {
collapsed: false,
collapseRender: () => null,
},
};
// 搜索属性
const searchProps = {};
return (
<PageHeaderWrapper>
<ProTable actionRef={actionRef} formRef={formRef} {...tableProps}></ProTable>
</PageHeaderWrapper>
);
};
export default SystemLog;
import React, { forwardRef, useImperativeHandle, useState, useEffect } from 'react';
import { Input, Checkbox, Button, Tree, notification } from 'antd';
import { Form } from '@ant-design/compatible';
import { PageHeaderWrapper } from '@ant-design/pro-layout';
import { getUserPermissions } from '@/services/user';
import { addResource, getRoleDetail, modifyRole } from '../../service';
import UUID from '@/utils/uuid';
import style from './index.less';
import { APP_CODE, TENANT_ID } from '@/utils/constants';
// mock
const { TextArea } = Input;
const { TreeNode } = Tree;
/**
* 权限表单/权限展示
* @param {*} props
* @param {boolean} props.submittable 是否可提交(即:是否展示操作)
* @param {number} props.id 判断是否是新增
* @param {boolean} props.readyonly 是否全部为只读(查看操作)
*/
const RoleInfo = props => {
const { id, submittable = true, readyonly = false, defaultExpandAll = true } = props;
const { getFieldDecorator, getFieldValue, validateFields, setFieldsValue } = props.form;
// 可选的权限数据
const [permissionsData, setPermissionsData] = useState([]);
// 当前选中的权限-仅提交时使用
const [selectedPermissions, setSelectedPermissions] = useState([]);
const [detailInfo, setDetailInfo] = useState({});
// 表单布局
const formLayout = {
labelCol: { span: 4 },
wrapperCol: { span: 12 },
};
const btnLayout = {
wrapperCol: { offset: 4, span: 12 },
};
// 表单验证
const formRules = {
name: [{ required: true, message: '请设置角色名称' }],
description: [{ required: true, message: '请填写角色描述' }],
selected: [{ type: 'array', required: true, message: '请选择权限' }],
};
const treeProps = {
defaultExpandAll,
};
// 表单验证辅助函数
const rulesHandler = field => ({
rules: formRules[field] || [],
});
// 提交数据
const onSubmit = () => {
validateFields(async (err, fieldsValue) => {
console.log('fieldsValue :>>', fieldsValue);
if (err) {
return;
}
// 提交
const params = {
tenantId: TENANT_ID,
code: UUID.createUUID(),
app: {
appCode: APP_CODE,
selected: selectedPermissions,
},
...fieldsValue,
};
if (id) {
params.id = id;
}
// 删除提交时无用的字段
delete params.selected;
console.log('params :>>', params);
const res = await addResource(params);
if (res.code !== 2000) {
notification.warning({
message: `${res.msg}:${res.detail}`,
});
return;
}
notification.success({
message: '提交成功',
});
setTimeout(() => {
window.history.back();
}, 1000);
});
};
// 选择权限回调
const onPermissionsCheck = checkedKeys => {
if (readyonly) {
return;
}
setSelectedPermissions(checkedKeys);
setFieldsValue({
selected: checkedKeys,
});
};
// 初始化权限数据
const initPermissions = async () => {
const roleId = id || null;
const res = await getUserPermissions(roleId);
let resource = [];
let selected = [];
if (roleId) {
const { resource: resourceData, selected: selectedData } = res.data;
resource = resourceData;
selected = selectedData;
} else {
resource = res.data;
}
setPermissionsData(resource);
setSelectedPermissions(selected);
setFieldsValue({
selected,
});
};
// 初始化当前角色数据
const initRoleData = async () => {
const res = await getRoleDetail({ id });
if (res.code !== 2000) {
notification.warning({ message: res.detail });
return;
}
console.log(res.data);
const { name, description } = res.data;
setFieldsValue({
name,
description,
});
setDetailInfo({
name,
description,
});
};
useEffect(() => {
initPermissions();
if (id) {
initRoleData();
}
}, []);
const renderTreeNodes = data =>
data.map(item => {
if (item.childNodes) {
return (
<TreeNode title={item.node.name} key={item.node.id} dataRef={item}>
{renderTreeNodes(item.childNodes)}
</TreeNode>
);
}
return <TreeNode key={item.node.id} {...item} />;
});
return (
<div className={style['info-box']}>
<Form className={style['info-box--form']} {...formLayout}>
<Form.Item label="角色名称">
{readyonly
? detailInfo.name
: getFieldDecorator('name', rulesHandler('name'))(
<Input maxLength={10} placeholder="10个字以内" />,
)}
</Form.Item>
<Form.Item label="角色描述">
{readyonly
? detailInfo.description
: getFieldDecorator('description', rulesHandler('description'))(
<TextArea placeholder="30个字以内"></TextArea>,
)}
</Form.Item>
<Form.Item label="权限">
{getFieldDecorator('selected', rulesHandler('selected'))(
permissionsData.length ? (
<Tree
checkable
selectable={false}
defaultExpandAll
onCheck={onPermissionsCheck}
checkedKeys={selectedPermissions}
>
{renderTreeNodes(permissionsData)}
</Tree>
) : (
<></>
),
)}
</Form.Item>
{submittable ? (
<Form.Item {...btnLayout}>
<Button type="default" onClick={() => window.history.back()}>
返回
</Button>
<Button className={style['submit-button']} type="primary" onClick={onSubmit}>
提交
</Button>
</Form.Item>
) : (
''
)}
</Form>
</div>
);
};
export const RoleInfoComponent = Form.create({})(RoleInfo);
const PageWapperComponent = props => {
const { id } = props.location?.query;
const [title, setTitle] = useState('新增角色');
useEffect(() => {
if (id) {
setTitle('编辑角色');
}
}, []);
const roleInfo = {
id,
};
return (
<PageHeaderWrapper title={title}>
<RoleInfoComponent {...roleInfo} />
</PageHeaderWrapper>
);
};
export default PageWapperComponent;
.info-box {
padding: 30px 0;
background: #fff;
&--form {
max-width: 1200px;
}
.submit-button {
margin-left: 20px;
}
}
import React from 'react';
import { Divider, Popconfirm } from 'antd';
export const getColumns = props => {
const { onDeleteRole, toRoleInfo } = props;
return [
{
title: '角色ID',
dataIndex: 'id',
},
{
title: '角色名称',
dataIndex: 'name',
},
{
title: '角色描述',
dataIndex: 'description',
hideInSearch: true,
},
{
title: '状态',
dataIndex: 'status',
hideInSearch: true,
render: value => value.name,
},
{
title: '关联账号',
dataIndex: 'account',
hideInSearch: true,
},
{
title: '创建人',
dataIndex: 'creator',
hideInSearch: true,
render: value => <a>{value}</a>,
},
{
title: '创建日期',
hideInSearch: true,
dataIndex: 'createTime',
},
{
title: '操作',
key: 'action',
render: (value, record) => (
<>
<a onClick={() => toRoleInfo(record)}>编辑</a>
<Divider type="vertical" />
<Popconfirm
placement="top"
title="确定删除该角色吗?"
onConfirm={() => onDeleteRole(record)}
okText="确定"
cancelText="取消"
>
<a>删除</a>
</Popconfirm>
</>
),
},
];
};
import React, { useRef } from 'react';
import { useHistory } from 'react-router-dom';
import { Button, notification } from 'antd';
import { PageHeaderWrapper } from '@ant-design/pro-layout';
import ProTable from '@ant-design/pro-table';
import { connect } from 'umi';
import { deleteRole, getRoleList } from '../service';
// data
import { getColumns } from './data';
const Role = props => {
const actionRef = useRef();
const formRef = useRef();
const history = useHistory();
const toRoleInfo = ({ id = null } = {}) => {
const query = id ? { id } : {};
history.push({
pathname: '/systemManage/role/roleInfo',
query,
});
};
// 删除
const onDeleteRole = async ({ id }) => {
const res = await deleteRole({ id });
if (res.code !== 2000) {
notification.warning({
message: res.detail,
});
return;
}
notification.success({
message: '删除成功',
});
};
const columns = getColumns({
onDeleteRole,
toRoleInfo,
});
// 表格属性
const tableProps = {
columns,
rowKey: 'id',
request: async params => {
console.log('搜索:', params);
const { current: page, pageSize: size } = params;
const res = await getRoleList({ page, size, ...params });
const { content, totalElements } = res.data;
return {
data: content,
success: true,
total: totalElements,
};
},
toolBarRender: () => [
<Button type="primary" onClick={() => toRoleInfo()}>
新增角色
</Button>,
],
};
// 搜索属性
const searchProps = {
collapsed: false,
collapseRender: () => null,
};
return (
<PageHeaderWrapper>
<ProTable
actionRef={actionRef}
formRef={formRef}
{...tableProps}
search={searchProps}
></ProTable>
</PageHeaderWrapper>
);
};
export default connect(({ menu }) => ({
permissions: menu.permissions,
}))(Role);
export const accountList = [
{
id: 1,
username: 'liteng',
name: '李腾',
createAt: '2017-01-01',
lastAt: '2020-01-01',
role: '超级管理员',
status: '启用',
},
];
export const logList = [
{
id: 1,
name: 'liteng',
actionTime: '2017-01-01',
menu: '系统管理',
subMenu: '账号管理',
status: '编辑',
},
];
export const roleList = [
{
id: 1,
username: 'liteng',
name: '李腾',
createAt: '2017-01-01',
lastAt: '2020-01-01',
role: '超级管理员',
status: '启用',
},
];
export const treeData = [
{
title: '0-0',
key: '0-0',
children: [
{
title: '0-0-0',
key: '0-0-0',
children: [
{ title: '0-0-0-0', key: '0-0-0-0' },
{ title: '0-0-0-1', key: '0-0-0-1' },
{ title: '0-0-0-2', key: '0-0-0-2' },
],
},
{
title: '0-0-1',
key: '0-0-1',
children: [
{ title: '0-0-1-0', key: '0-0-1-0' },
{ title: '0-0-1-1', key: '0-0-1-1' },
{ title: '0-0-1-2', key: '0-0-1-2' },
],
},
{
title: '0-0-2',
key: '0-0-2',
},
],
},
{
title: '0-1',
key: '0-1',
children: [
{ title: '0-1-0-0', key: '0-1-0-0' },
{ title: '0-1-0-1', key: '0-1-0-1' },
{ title: '0-1-0-2', key: '0-1-0-2' },
],
},
{
title: '0-2',
key: '0-2',
},
];
import { stringify } from 'querystring';
import _ from 'lodash';
import request from '@/utils/request';
import { APP_CODE } from '@/utils/constants';
const PAGE = 1;
const SIZE = 20;
/**
* @name 子账号列表
* @param {Object} params
* @see http://yapi.quantgroups.com/project/509/interface/api/42832
*/
export function getUserList({ page = PAGE, size = SIZE }) {
return request.post(`/v2/user/list/${page}/${size}`, {
data: {},
});
}
/**
* @name 子账号详情
* @param {Object} params
* @param {number} params.id 子账号id
* @see http://yapi.quantgroups.com/project/509/interface/api/42856
*/
export function getUserDetail({ id }) {
return request.get(`/v2/user/info/${id}`);
}
/**
* @name 新增/修改子账号
* @see http://yapi.quantgroups.com/project/509/interface/api/42896
*/
export function addUser(params) {
return request.post('/v2/user/addnew', {
data: params,
});
}
/**
* @name 用户禁用
* @param {Object} params
* @param {number} params.id
* @see http://yapi.quantgroups.com/project/509/interface/api/42864
*/
export function userDisabled({ id }) {
return request.post(`/v2/user/disabled/${id}`);
}
/**
* @name 用户启用
* @param {Object} params
* @param {number} params.id
* @see http://yapi.quantgroups.com/project/509/interface/api/42880
*/
export function userEnabled({ id }) {
return request.post(`/v2/user/enabled/${id}`);
}
/**
* @name 删除用户
* @param {Object} params
* @param {number} params.id
* @see http://yapi.quantgroups.com/project/509/interface/api/43120
*/
export function userDelete({ id }) {
return request.post(`/v2/user/delete/${id}`);
}
/**
* @name 重置/修改密码
* @param {Object} params
* @param {string} params.newPassword 新密码
* @param {string} params.password 确认密码
* @see http://yapi.quantgroups.com/project/509/interface/api/41800
*/
export function resetPassword(params) {
return request.post('/v2/user/password/reset', params);
}
/**
* @name 角色列表-分页
* @param {Object} params
* @see http://yapi.quantgroups.com/project/509/interface/api/41816
*/
export function getRoleList({ page, size }) {
return request.post(`/v2/role/list/${page}/${size}?appCode=${APP_CODE}`, {
data: {},
});
}
/**
* @name 角色详情
* @param {Object} params
* @param {number} params.id 角色id
* @see http://yapi.quantgroups.com/project/509/interface/api/41848
*
*/
export async function getRoleDetail({ id }) {
return request.get(`/v2/role/info/${id}`);
}
/**
* @name 新增角色
* @param {Object} params
* @see http://yapi.quantgroups.com/project/509/interface/api/42920
*/
export async function addResource(params) {
return request.post('/v2/role/addResource', {
data: params,
});
}
/**
* @name 修改角色
* @param {Object} params
* @see http://yapi.quantgroups.com/project/509/interface/api/42928
*/
export async function modifyRole(params) {
return request.post('/v2/role/updateResource', params);
}
/**
* @name 删除角色
* @param {Object} params
* @param {number} params.id 角色id
* @see http://yapi.quantgroups.com/project/509/interface/api/41832
*/
export async function deleteRole({ id }) {
return request.post(`/v2/role/delete/${id}`);
}
import request from '@/utils/request'; import request from '@/utils/request';
import { APP_CODE } from '@/utils/constants';
export async function getMenuData() { export async function getMenuData() {
return request.post('/v2/resource/APP013'); return request.post(`/v2/resource/${APP_CODE}`);
} }
import { APP_CODE } from '@/utils/constants';
import request from '@/utils/request'; import request from '@/utils/request';
export async function queryCurrent() { export async function queryCurrent() {
...@@ -9,3 +10,10 @@ export async function homeInfo() { ...@@ -9,3 +10,10 @@ export async function homeInfo() {
// 查询主页信息 // 查询主页信息
return request.post('/home/info'); return request.post('/home/info');
} }
export function getUserPermissions(roleId) {
if (roleId) {
return request.post(`/v2/resource/${APP_CODE}/${roleId}`);
}
return request.post(`/v2/resource/${APP_CODE}`);
}
export const APP_CODE = 'APP013';
export const TENANT_ID = 560761;
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