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