liujiangyong
1 year ago
18 changed files with 707 additions and 11 deletions
@ -0,0 +1,146 @@ |
|||||
|
'use strict'; |
||||
|
const Hex = require('crypto-js/enc-hex'); |
||||
|
const MD5 = require('crypto-js/md5'); |
||||
|
const CryptoJS = require('crypto-js'); |
||||
|
|
||||
|
function getOrganizationList(opts) { |
||||
|
return async function (ctx, next) { |
||||
|
|
||||
|
const models = ctx.fs.dc.models; |
||||
|
const { page, limit, name } = ctx.query; |
||||
|
const Op = ctx.fs.dc.ORM.Op; |
||||
|
let errMsg = { message: '获取机构失败' } |
||||
|
try { |
||||
|
let searchWhere = { |
||||
|
} |
||||
|
let option = { |
||||
|
where: searchWhere, |
||||
|
order: [["id", "desc"]], |
||||
|
attributes: { exclude: ['password'] }, |
||||
|
} |
||||
|
|
||||
|
if (name) { |
||||
|
searchWhere.name = { $like: '%' + name + '%' }; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
option.where = searchWhere |
||||
|
let limit_ = limit || 10; |
||||
|
let page_ = page || 1; |
||||
|
let offset = (page_ - 1) * limit_; |
||||
|
if (limit && page) { |
||||
|
option.limit = limit_ |
||||
|
option.offset = offset |
||||
|
} |
||||
|
|
||||
|
const res = await models.Organization.findAndCount(option); |
||||
|
ctx.status = 200; |
||||
|
ctx.body = res; |
||||
|
} catch (error) { |
||||
|
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); |
||||
|
ctx.status = 400; |
||||
|
ctx.body = errMsg |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 新增机构
|
||||
|
function addOrganization(opts) { |
||||
|
return async function (ctx, next) { |
||||
|
|
||||
|
const models = ctx.fs.dc.models; |
||||
|
try { |
||||
|
const { name, code } = ctx.request.body |
||||
|
const checkName = await models.Organization.findOne({ where: { name, code } }); |
||||
|
if (checkName) { |
||||
|
ctx.status = 400; |
||||
|
ctx.body = { message: "该机构名称&代码组合已存在" } |
||||
|
} else { |
||||
|
let rslt = ctx.request.body; |
||||
|
await models.Organization.create(Object.assign({}, rslt)) |
||||
|
ctx.status = 204; |
||||
|
ctx.body = { message: '新建机构成功' } |
||||
|
} |
||||
|
|
||||
|
} catch (error) { |
||||
|
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); |
||||
|
ctx.status = 400; |
||||
|
ctx.body = { message: '新建机构失败' } |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 修改机构
|
||||
|
function editOrganization(opts) { |
||||
|
return async function (ctx, next) { |
||||
|
|
||||
|
try { |
||||
|
const models = ctx.fs.dc.models; |
||||
|
const { id } = ctx.params; |
||||
|
const body = ctx.request.body; |
||||
|
const { name, code } = ctx.request.body |
||||
|
const checkName = await models.Organization.findOne({ where: { id: { $not: id }, name, code } }); |
||||
|
if (checkName) { |
||||
|
ctx.status = 400; |
||||
|
ctx.body = { message: '该机构名称&代码组合已存在' } |
||||
|
} else { |
||||
|
await models.Organization.update( |
||||
|
body, |
||||
|
{ where: { id: id, } } |
||||
|
) |
||||
|
ctx.status = 204; |
||||
|
ctx.body = { message: '修改机构成功' } |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
} catch (error) { |
||||
|
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); |
||||
|
ctx.status = 400; |
||||
|
ctx.body = { message: '修改机构失败' } |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 删除机构
|
||||
|
function deleteOrganization(opts) { |
||||
|
return async function (ctx, next) { |
||||
|
|
||||
|
try { |
||||
|
const models = ctx.fs.dc.models; |
||||
|
const { id } = ctx.params; |
||||
|
|
||||
|
// const checkName1 = await models.MetadataDatabase.findOne({ where: { createBy: id } });
|
||||
|
// const checkName2 = await models.MetadataFile.findOne({ where: { createBy: id } });
|
||||
|
// const checkName3 = await models.MetadataRestapi.findOne({ where: { createBy: id } });
|
||||
|
// if (checkName1 || checkName2 || checkName3) {
|
||||
|
// ctx.status = 400;
|
||||
|
// ctx.body = { message: '该机构下存在依赖资源无法删除!' }
|
||||
|
// } else {
|
||||
|
await models.Organization.destroy({ |
||||
|
where: { |
||||
|
id: id |
||||
|
} |
||||
|
}) |
||||
|
ctx.status = 204; |
||||
|
ctx.body = { message: '删除机构成功' } |
||||
|
// }
|
||||
|
|
||||
|
} catch (error) { |
||||
|
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); |
||||
|
ctx.status = 400; |
||||
|
ctx.body = { message: '删除机构失败' } |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
module.exports = { |
||||
|
getOrganizationList, |
||||
|
addOrganization, |
||||
|
editOrganization, |
||||
|
deleteOrganization, |
||||
|
|
||||
|
} |
@ -0,0 +1,53 @@ |
|||||
|
/* eslint-disable*/ |
||||
|
|
||||
|
'use strict'; |
||||
|
|
||||
|
module.exports = dc => { |
||||
|
const DataTypes = dc.ORM; |
||||
|
const sequelize = dc.orm; |
||||
|
const Organization = sequelize.define("organization", { |
||||
|
id: { |
||||
|
type: DataTypes.INTEGER, |
||||
|
allowNull: false, |
||||
|
defaultValue: null, |
||||
|
comment: null, |
||||
|
primaryKey: true, |
||||
|
field: "id", |
||||
|
autoIncrement: true, |
||||
|
unique: "organization_id_uindex" |
||||
|
}, |
||||
|
name: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: null, |
||||
|
primaryKey: false, |
||||
|
field: "name", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
code: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: null, |
||||
|
primaryKey: false, |
||||
|
field: "code", |
||||
|
autoIncrement: false |
||||
|
}, |
||||
|
ability: { |
||||
|
type: DataTypes.STRING, |
||||
|
allowNull: true, |
||||
|
defaultValue: null, |
||||
|
comment: "职能", |
||||
|
primaryKey: false, |
||||
|
field: "ability", |
||||
|
autoIncrement: false |
||||
|
} |
||||
|
}, { |
||||
|
tableName: "organization", |
||||
|
comment: "", |
||||
|
indexes: [] |
||||
|
}); |
||||
|
dc.models.Organization = Organization; |
||||
|
return Organization; |
||||
|
}; |
@ -0,0 +1,23 @@ |
|||||
|
'use strict'; |
||||
|
|
||||
|
const organization = require('../../controllers/organization/index'); |
||||
|
|
||||
|
module.exports = function (app, router, opts, AuthCode) { |
||||
|
|
||||
|
app.fs.api.logAttr['POST/organization'] = { content: '增加机构', visible: true }; |
||||
|
router.post('/organization', organization.addOrganization(opts)) |
||||
|
|
||||
|
// 修改机构信息
|
||||
|
app.fs.api.logAttr['PUT/organization/:id'] = { content: '修改机构信息', visible: true }; |
||||
|
router.put('/organization/:id', organization.editOrganization(opts)) |
||||
|
|
||||
|
// 删除机构信息
|
||||
|
app.fs.api.logAttr['DEL/organization/:id'] = { content: '删除机构信息', visible: true }; |
||||
|
router.del('/organization/:id', organization.deleteOrganization(opts)) |
||||
|
|
||||
|
//获取机构信息列表
|
||||
|
app.fs.api.logAttr['GET/organization'] = { content: '获取机构信息列表', visible: true }; |
||||
|
router.get('/organization', organization.getOrganizationList(opts)); |
||||
|
|
||||
|
|
||||
|
}; |
After Width: | Height: | Size: 66 KiB |
@ -0,0 +1,6 @@ |
|||||
|
'use strict'; |
||||
|
|
||||
|
import * as member from './organization'; |
||||
|
export default { |
||||
|
...member |
||||
|
} |
@ -0,0 +1,56 @@ |
|||||
|
'use strict'; |
||||
|
|
||||
|
import { basicAction } from '@peace/utils' |
||||
|
import { ApiTable } from '$utils' |
||||
|
|
||||
|
export function getOrganizationList(query) { |
||||
|
return dispatch => basicAction({ |
||||
|
type: 'get', |
||||
|
dispatch: dispatch, |
||||
|
query: query || {}, |
||||
|
actionType: 'GET_ORGANIZATION_REPORT', |
||||
|
url: `${ApiTable.getOrganizationList}`, |
||||
|
msg: { error: '获取机构列表失败' }, |
||||
|
reducer: { name: 'organization' } |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
export function addOrganization(params) { |
||||
|
return (dispatch) => basicAction({ |
||||
|
type: 'post', |
||||
|
data: params, |
||||
|
dispatch, |
||||
|
actionType: 'ADD_ORGANIZATION_REPORT', |
||||
|
url: ApiTable.addOrganization, |
||||
|
msg: { |
||||
|
option: '机构新增', |
||||
|
}, |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
export function deleteOrganization(id) { |
||||
|
return (dispatch) => basicAction({ |
||||
|
type: 'del', |
||||
|
dispatch, |
||||
|
actionType: 'DELETE_ORGANIZATION_REPORT', |
||||
|
url: ApiTable.modifyOrganization.replace('{id}', id), |
||||
|
msg: { |
||||
|
option: '机构删除', |
||||
|
}, |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
export function modifyOrganization(id, params, msg) { |
||||
|
return (dispatch) => basicAction({ |
||||
|
type: 'put', |
||||
|
data: params, |
||||
|
dispatch, |
||||
|
actionType: 'MODIFY_ORGANIZATION_REPORT', |
||||
|
url: ApiTable.modifyOrganization.replace('{id}', id), |
||||
|
msg: { |
||||
|
option: msg || '机构编辑', |
||||
|
}, |
||||
|
}); |
||||
|
} |
||||
|
|
@ -0,0 +1,68 @@ |
|||||
|
import React, { useRef } from 'react'; |
||||
|
import { Button, Form } from 'antd'; |
||||
|
|
||||
|
import { |
||||
|
ModalForm, |
||||
|
ProFormText, |
||||
|
} from '@ant-design/pro-form'; |
||||
|
|
||||
|
export default (props) => { |
||||
|
const { title, triggerRender, editData = null, onFinish, paramsName } = props; |
||||
|
const formItemLayout = { labelCol: { span: 6 }, wrapperCol: { span: 16 } }; |
||||
|
const initialValues = editData ? { |
||||
|
...editData, |
||||
|
} : {}; |
||||
|
const [form] = Form.useForm(); |
||||
|
const formRef = useRef(); |
||||
|
return ( |
||||
|
<ModalForm |
||||
|
formRef={formRef} |
||||
|
title={title || ''} |
||||
|
initialValues={initialValues} |
||||
|
trigger={ |
||||
|
triggerRender ? triggerRender : <Button type="primary" > |
||||
|
{title || ''} |
||||
|
</Button> |
||||
|
} |
||||
|
layout="horizontal" |
||||
|
grid={true} |
||||
|
{...formItemLayout} |
||||
|
modalProps={{ |
||||
|
destroyOnClose: true, |
||||
|
onCancel: () => { }, |
||||
|
}} |
||||
|
onFinish={async (values) => { |
||||
|
return onFinish && await onFinish(values, editData, form) |
||||
|
// return true;
|
||||
|
}} |
||||
|
width={500} |
||||
|
> |
||||
|
<ProFormText |
||||
|
rules={[{ required: true, message: '请输入机构名称' }, |
||||
|
{ max: 255, message: '机构名称长度不能大于255个字符' }, |
||||
|
]} |
||||
|
name="name" |
||||
|
label="机构名称" |
||||
|
/> |
||||
|
|
||||
|
<ProFormText |
||||
|
rules={[{ required: true, message: '请输入机构代码' }, |
||||
|
{ max: 255, message: '机构代码长度不能大于255个字符' }, |
||||
|
]} |
||||
|
name="code" |
||||
|
label="机构代码" |
||||
|
/> |
||||
|
|
||||
|
<ProFormText |
||||
|
rules={[{ required: true, message: '请输入机构职能' }, |
||||
|
{ max: 255, message: '机构职能长度不能大于255个字符' }, |
||||
|
]} |
||||
|
name="ability" |
||||
|
label="机构职能" |
||||
|
/> |
||||
|
|
||||
|
|
||||
|
|
||||
|
</ModalForm> |
||||
|
); |
||||
|
}; |
@ -0,0 +1,5 @@ |
|||||
|
'use strict'; |
||||
|
|
||||
|
import Organization from './organization'; |
||||
|
|
||||
|
export { Organization }; |
@ -0,0 +1,195 @@ |
|||||
|
import React, { useEffect, useState } from 'react' |
||||
|
import { Spin, Popconfirm, Select, Row, Col, Button, Input, Table } from 'antd'; |
||||
|
import { connect } from 'react-redux'; |
||||
|
import ProTable from '@ant-design/pro-table'; |
||||
|
import OrganizationModal from '../components/organizationModal'; |
||||
|
|
||||
|
import { useFsRequest, ApiTable } from '$utils'; |
||||
|
import './style.less'; |
||||
|
function organization(props) { |
||||
|
const { loading, clientHeight, actions, dispatch, organization, Organization } = props; |
||||
|
const [pageSize, setPageSize] = useState(10); |
||||
|
const [currentPage, setCurrentPage] = useState(1); |
||||
|
const [searchValue, setSearchValue] = useState('') |
||||
|
const [visible, setVisible] = useState(false);//是否展示新增编辑模态框
|
||||
|
const [editData, setEditData] = useState(null);//模态框编辑数据
|
||||
|
const [refreshTree, setRefreshTree] = useState(1); |
||||
|
const [searchRole, setSearchRole] = useState() |
||||
|
const queryData = (search) => { |
||||
|
const query = { |
||||
|
limit: search ? 10 : pageSize || 10, |
||||
|
page: search ? 1 : currentPage || 1, |
||||
|
name: searchValue, |
||||
|
role: searchRole |
||||
|
} |
||||
|
|
||||
|
dispatch(actions.organization.getOrganizationList(query)); |
||||
|
} |
||||
|
|
||||
|
useEffect(() => { |
||||
|
queryData(); |
||||
|
}, [pageSize, currentPage]); |
||||
|
|
||||
|
const columns = [ |
||||
|
{ |
||||
|
title: '序号', |
||||
|
dataIndex: 'index', |
||||
|
render: (text, record, index) => { return index + 1 } |
||||
|
}, |
||||
|
{ |
||||
|
title: '机构名称', |
||||
|
dataIndex: 'name', |
||||
|
}, |
||||
|
{ |
||||
|
title: '机构代码', |
||||
|
dataIndex: 'code', |
||||
|
}, |
||||
|
{ |
||||
|
title: '机构职能', |
||||
|
dataIndex: 'ability', |
||||
|
}, |
||||
|
{ |
||||
|
title: '操作', |
||||
|
width: 160, |
||||
|
key: 'option', |
||||
|
valueType: 'option', |
||||
|
render: (text, record) => { |
||||
|
const options = []; |
||||
|
options.push(<OrganizationModal |
||||
|
editData={record} |
||||
|
triggerRender={<a>编辑</a>} |
||||
|
title="编辑机构" |
||||
|
onFinish={onFinish} |
||||
|
key="editOrganization" |
||||
|
/>) |
||||
|
options.push( |
||||
|
<Popconfirm |
||||
|
key="del" |
||||
|
placement="top" |
||||
|
title={<><div>是否确认删除该机构?</div> |
||||
|
</>} |
||||
|
onConfirm={() => handleDelete(record.id)} |
||||
|
okText="是" |
||||
|
cancelText="否" |
||||
|
> |
||||
|
<a>删除</a> |
||||
|
</Popconfirm>) |
||||
|
|
||||
|
|
||||
|
return options; |
||||
|
|
||||
|
}, |
||||
|
}, |
||||
|
]; |
||||
|
|
||||
|
const handleDelete = (id) => { |
||||
|
dispatch(actions.organization.deleteOrganization(id)).then(() => { |
||||
|
queryData(); |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
const onFinish = async (values, editData) => { |
||||
|
if (editData) { |
||||
|
const dataToSave = { ...values } |
||||
|
return dispatch( |
||||
|
actions.organization.modifyOrganization(editData.id, dataToSave, values?.msg || ''), |
||||
|
).then((res) => { |
||||
|
if (res.success) { |
||||
|
queryData(); |
||||
|
return true; |
||||
|
} else { |
||||
|
return false; |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
return dispatch(actions.organization.addOrganization({ |
||||
|
...values, |
||||
|
})).then(res => { |
||||
|
if (res.success) { |
||||
|
queryData(); |
||||
|
return true; |
||||
|
} else { |
||||
|
return false; |
||||
|
} |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
return <Spin spinning={loading}> |
||||
|
<Row className='protable-title'> |
||||
|
<Col span={12}> |
||||
|
<OrganizationModal |
||||
|
triggerRender={<Button type='primary'>新建</Button>} |
||||
|
title="新建机构" |
||||
|
onFinish={onFinish} |
||||
|
key="addOrganization" |
||||
|
/> |
||||
|
</Col> |
||||
|
<Col span={12} style={{ display: 'flex', justifyContent: 'flex-end', alignItems: 'center' }}> |
||||
|
<span>机构名称: </span> <Input |
||||
|
value={searchValue} onChange={e => { setSearchValue(e.target.value) }} |
||||
|
style={{ width: 220, marginRight: 15 }} placeholder="请输入" /> |
||||
|
|
||||
|
<Button onClick={() => { |
||||
|
setCurrentPage(1) |
||||
|
setPageSize(10) |
||||
|
queryData(true) |
||||
|
}} type='primary'>查询</Button></Col> |
||||
|
|
||||
|
</Row> |
||||
|
<ProTable |
||||
|
columns={columns} |
||||
|
dateFormatter="string" |
||||
|
search={false} |
||||
|
scroll={ |
||||
|
{ |
||||
|
scrollToFirstRowOnChange: true, |
||||
|
y: clientHeight - 260 |
||||
|
} |
||||
|
} |
||||
|
pagination={{ |
||||
|
size: 'large', |
||||
|
total: organization?.count, |
||||
|
showSizeChanger: true, |
||||
|
showQuickJumper: true, |
||||
|
current: currentPage, |
||||
|
pageSize: pageSize || 10, |
||||
|
defaultPageSize: 10, |
||||
|
pageSizeOptions: [10, 20, 50], |
||||
|
showTotal: (total) => { |
||||
|
return <span style={{ fontSize: 15 }}>{`共${Math.ceil(total / pageSize)}页,${total}项`}</span> |
||||
|
}, |
||||
|
onShowSizeChange: (currentPage, pageSize) => { |
||||
|
setCurrentPage(currentPage); |
||||
|
setPageSize(pageSize); |
||||
|
|
||||
|
}, |
||||
|
onChange: (page, pageSize) => { |
||||
|
setCurrentPage(page); |
||||
|
setPageSize(pageSize); |
||||
|
|
||||
|
} |
||||
|
}} |
||||
|
dataSource={organization?.rows || []} |
||||
|
options={false} |
||||
|
/> |
||||
|
</Spin> |
||||
|
|
||||
|
} |
||||
|
|
||||
|
function mapStateToProps(state) { |
||||
|
const { |
||||
|
auth, global, datasources, organization |
||||
|
} = state; |
||||
|
return { |
||||
|
loading: datasources.isRequesting, |
||||
|
clientHeight: global.clientHeight, |
||||
|
actions: global.actions, |
||||
|
organization: organization?.data || {}, |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
export default connect(mapStateToProps)(organization); |
||||
|
|
||||
|
|
||||
|
|
@ -0,0 +1,5 @@ |
|||||
|
.protable-title { |
||||
|
margin-bottom: 16px; |
||||
|
padding-left: 24px; |
||||
|
padding-right: 24px; |
||||
|
} |
@ -0,0 +1,15 @@ |
|||||
|
'use strict'; |
||||
|
|
||||
|
import reducers from './reducers'; |
||||
|
import routes from './routes'; |
||||
|
import actions from './actions'; |
||||
|
import { getNavItem } from './nav-item'; |
||||
|
|
||||
|
export default { |
||||
|
key: 'organization', |
||||
|
name: '机构管理', |
||||
|
reducers: reducers, |
||||
|
routes: routes, |
||||
|
actions: actions, |
||||
|
getNavItem: getNavItem |
||||
|
}; |
@ -0,0 +1,20 @@ |
|||||
|
import React from 'react'; |
||||
|
import { Link } from 'react-router-dom'; |
||||
|
import { Menu } from 'antd'; |
||||
|
import { UserOutlined } from '@ant-design/icons'; |
||||
|
const SubMenu = Menu.SubMenu; |
||||
|
|
||||
|
export function getNavItem(user) { |
||||
|
|
||||
|
return ( |
||||
|
user?.role == '系统管理员' && <Menu.Item icon={<UserOutlined />} key="organization"> |
||||
|
<Link to="/organization">机构管理</Link> |
||||
|
</Menu.Item> |
||||
|
// user?.role == '系统管理员' && <SubMenu key="memberManagement" icon={<UserOutlined />} title='用户管理'>
|
||||
|
// <Menu.Item key="auth">
|
||||
|
// <Link to="/memberManagement/auth">用户权限</Link>
|
||||
|
// </Menu.Item>
|
||||
|
// </ SubMenu >
|
||||
|
) |
||||
|
|
||||
|
} |
@ -0,0 +1,5 @@ |
|||||
|
'use strict'; |
||||
|
|
||||
|
export default { |
||||
|
|
||||
|
} |
@ -0,0 +1,12 @@ |
|||||
|
'use strict'; |
||||
|
import { Organization } from './containers'; |
||||
|
export default [{ |
||||
|
type: 'inner', |
||||
|
route: { |
||||
|
path: '/organization', |
||||
|
key: 'organization', |
||||
|
breadcrumb: '机构管理', |
||||
|
component: Organization, |
||||
|
|
||||
|
} |
||||
|
}]; |
Loading…
Reference in new issue