update 人员管理/用户管理

This commit is contained in:
2021-06-25 17:36:15 +08:00
parent f6b9a81314
commit 934fc76a10
6 changed files with 504 additions and 104 deletions

View File

@@ -0,0 +1,115 @@
import React, { Component } from 'react'
import { Form, Spin, TreeSelect } from 'antd'
import { AntIcon } from 'components'
import { cloneDeep } from 'lodash'
import { api } from 'common/api'
export default class dataForm extends Component {
state = {
// 加载状态
loading: true,
options: {
orgData: [],
areaData: [],
orgCheckedKeys: [],
},
}
// 表单实例
form = React.createRef()
// 初始化数据
record = {}
/**
* mount后回调
*/
componentDidMount() {
this.props.created && this.props.created(this)
}
async fillData(params) {
this.record = cloneDeep(params.record)
//#region 从后端转换成前段所需格式
const orgData = await this.loadOrgData()
const areaData = await this.loadAreaData()
const orgCheckedKeys = await this.loadMemberOwn(this.record.id)
this.setState({
options: {
orgData,
areaData,
orgCheckedKeys,
},
})
this.form.current.setFieldsValue({
id: this.record.id,
grantOrgIdList: orgCheckedKeys,
grantAreaCodeList: [],
})
this.setState({
loading: false,
})
}
/**
* 获取数据
* 可以对postData进行数据结构调整
* [异步,必要]
* @returns
*/
async getData() {
const form = this.form.current
const valid = await form.validateFields()
if (valid) {
const postData = form.getFieldsValue()
if (this.record) {
postData.id = this.record.id
}
//#region 从前段转换后端所需格式
//#endregion
return postData
}
}
//#region 自定义方法
async loadOrgData() {
const { data } = await api.getOrgTree()
return data
}
async loadAreaData() {
const { data } = await api.getAreaTree()
return data
}
async loadMemberOwn(id) {
const { data } = await api.houseMemberOwnData({ id })
return data
}
render() {
return (
<Form ref={this.form} className="yo-form">
<Spin spinning={this.state.loading} indicator={<AntIcon type="loading" />}>
<div className="yo-form-group">
<Form.Item label="选择机构" name="grantOrgIdList">
<TreeSelect
showCheckedStrategy="SHOW_PARENT"
treeData={this.state.options.orgData}
placeholder="请选择机构"
treeCheckable
/>
</Form.Item>
<Form.Item label="选择区域" name="grantAreaCodeList">
<TreeSelect
showCheckedStrategy="SHOW_PARENT"
treeData={this.state.options.areaData}
placeholder="请选择所属区域"
treeCheckable
/>
</Form.Item>
</div>
</Spin>
</Form>
)
}
}

View File

@@ -20,6 +20,7 @@ import { isEqual } from 'lodash'
import getDictData from 'util/dic' import getDictData from 'util/dic'
import FormBody from './form' import FormBody from './form'
import Selector from './selector' import Selector from './selector'
import DataForm from './data'
// 配置页面所需接口函数 // 配置页面所需接口函数
const apiAction = { const apiAction = {
@@ -31,6 +32,8 @@ const apiAction = {
changeStatus: api.houseMemberChangeStatus, changeStatus: api.houseMemberChangeStatus,
resetPwd: api.sysUserResetPwd, resetPwd: api.sysUserResetPwd,
grantData: api.houseMemberGrantData,
} }
// 用于弹窗标题 // 用于弹窗标题
@@ -52,6 +55,7 @@ export default class index extends Component {
// 编辑窗口实例 // 编辑窗口实例
editForm = React.createRef() editForm = React.createRef()
dataForm = React.createRef()
// 树选中节点 // 树选中节点
selectId = undefined selectId = undefined
@@ -200,6 +204,9 @@ export default class index extends Component {
<Auth aut="houseMember:resetPwd"> <Auth aut="houseMember:resetPwd">
<a onClick={() => this.onResetPassword(record)}>重置密码</a> <a onClick={() => this.onResetPassword(record)}>重置密码</a>
</Auth>, </Auth>,
<Auth auth="houseMember:grantData">
<a onClick={() => this.onOpen(this.dataForm, record)}>授权额外数据</a>
</Auth>,
]} ]}
> >
<List.Item.Meta <List.Item.Meta
@@ -349,6 +356,15 @@ export default class index extends Component {
<FormBody mode="edit" /> <FormBody mode="edit" />
</ModalForm> </ModalForm>
<ModalForm
title="数据授权"
action={apiAction.grantData}
ref={this.dataForm}
onSuccess={() => this.list.current.onReloadData()}
>
<DataForm />
</ModalForm>
<ModalForm <ModalForm
bodyStyle={{ padding: 0 }} bodyStyle={{ padding: 0 }}
footer={false} footer={false}

View File

@@ -10,7 +10,6 @@ const { SHOW_PARENT } = TreeSelect
const initialValues = {} const initialValues = {}
export default class data extends Component { export default class data extends Component {
state = { state = {
// 加载状态 // 加载状态
loading: true, loading: true,
@@ -19,7 +18,7 @@ export default class data extends Component {
arerTreeData: [], arerTreeData: [],
orgCheckedKeys: [], orgCheckedKeys: [],
isDefine: false isDefine: false,
} }
// 表单实例 // 表单实例
@@ -39,10 +38,9 @@ export default class data extends Component {
* 填充数据 * 填充数据
* 可以在设置this.record之后对其作出数据结构调整 * 可以在设置this.record之后对其作出数据结构调整
* [异步,必要] * [异步,必要]
* @param {*} params * @param {*} params
*/ */
async fillData(params) { async fillData(params) {
this.record = cloneDeep(params.record) this.record = cloneDeep(params.record)
//#region 从后端转换成前段所需格式 //#region 从后端转换成前段所需格式
const { dataScopeType } = await getDictData('data_scope_type') const { dataScopeType } = await getDictData('data_scope_type')
@@ -53,17 +51,17 @@ export default class data extends Component {
dataScopeType, dataScopeType,
orgTreeData, orgTreeData,
arerTreeData, arerTreeData,
orgCheckedKeys orgCheckedKeys,
}) })
//#endregion //#endregion
this.form.current.setFieldsValue({ this.form.current.setFieldsValue({
dataScopeType: this.record.dataScopeType.toString() dataScopeType: this.record.dataScopeType.toString(),
}) })
this.onChange(this.record.dataScopeType) this.onChange(this.record.dataScopeType)
this.setState({ this.setState({
loading: false loading: false,
}) })
} }
@@ -71,7 +69,7 @@ export default class data extends Component {
* 获取数据 * 获取数据
* 可以对postData进行数据结构调整 * 可以对postData进行数据结构调整
* [异步,必要] * [异步,必要]
* @returns * @returns
*/ */
async getData() { async getData() {
const form = this.form.current const form = this.form.current
@@ -107,11 +105,11 @@ export default class data extends Component {
onChange(value) { onChange(value) {
if (value == 5) { if (value == 5) {
this.setState({ this.setState({
isDefine: true isDefine: true,
}) })
} else { } else {
this.setState({ this.setState({
isDefine: false isDefine: false,
}) })
} }
} }
@@ -119,29 +117,24 @@ export default class data extends Component {
render() { render() {
return ( return (
<Form <Form initialValues={initialValues} ref={this.form} className="yo-form">
initialValues={initialValues}
ref={this.form}
className="yo-form"
>
<Spin spinning={this.state.loading} indicator={<AntIcon type="loading" />}> <Spin spinning={this.state.loading} indicator={<AntIcon type="loading" />}>
<div className="yo-form-group"> <div className="yo-form-group">
<Form.Item label="授权范围" name="dataScopeType"> <Form.Item label="授权范围" name="dataScopeType">
<Select placeholder="请选择授权范围" onChange={(value) => this.onChange(value)}> <Select
{ placeholder="请选择授权范围"
this.state.dataScopeType.map(item => { onChange={value => this.onChange(value)}
return ( >
<Select.Option {this.state.dataScopeType.map(item => {
key={item.code} return (
value={item.code} <Select.Option key={item.code} value={item.code}>
>{item.value}</Select.Option> {item.value}
) </Select.Option>
}) )
} })}
</Select> </Select>
</Form.Item> </Form.Item>
{ {this.state.isDefine && (
this.state.isDefine &&
<> <>
<Form.Item label="选择机构" name="grantOrgIdList"> <Form.Item label="选择机构" name="grantOrgIdList">
<TreeSelect <TreeSelect
@@ -151,7 +144,11 @@ export default class data extends Component {
treeCheckable treeCheckable
/> />
</Form.Item> </Form.Item>
<Form.Item label="选择区域" name="grantAreaCodeList" help="缺少获取已保存的列表,react版本节点名无法设置"> <Form.Item
label="选择区域"
name="grantAreaCodeList"
help="缺少获取已保存的列表,react版本节点名无法设置"
>
<TreeSelect <TreeSelect
showCheckedStrategy={SHOW_PARENT} showCheckedStrategy={SHOW_PARENT}
treeData={this.state.arerTreeData} treeData={this.state.arerTreeData}
@@ -160,7 +157,7 @@ export default class data extends Component {
/> />
</Form.Item> </Form.Item>
</> </>
} )}
</div> </div>
</Spin> </Spin>
</Form> </Form>

View File

@@ -0,0 +1,115 @@
import React, { Component } from 'react'
import { Form, Spin, TreeSelect } from 'antd'
import { AntIcon } from 'components'
import { cloneDeep } from 'lodash'
import { api } from 'common/api'
export default class data extends Component {
state = {
// 加载状态
loading: true,
options: {
orgData: [],
areaData: [],
orgCheckedKeys: [],
},
}
// 表单实例
form = React.createRef()
// 初始化数据
record = {}
/**
* mount后回调
*/
componentDidMount() {
this.props.created && this.props.created(this)
}
async fillData(params) {
this.record = cloneDeep(params.record)
//#region 从后端转换成前段所需格式
const orgData = await this.loadOrgData()
const areaData = await this.loadAreaData()
const orgCheckedKeys = await this.loadMemberOwn(this.record.id)
this.setState({
options: {
orgData,
areaData,
orgCheckedKeys,
},
})
this.form.current.setFieldsValue({
id: this.record.id,
grantOrgIdList: orgCheckedKeys,
grantAreaCodeList: [],
})
this.setState({
loading: false,
})
}
/**
* 获取数据
* 可以对postData进行数据结构调整
* [异步,必要]
* @returns
*/
async getData() {
const form = this.form.current
const valid = await form.validateFields()
if (valid) {
const postData = form.getFieldsValue()
if (this.record) {
postData.id = this.record.id
}
//#region 从前段转换后端所需格式
//#endregion
return postData
}
}
//#region 自定义方法
async loadOrgData() {
const { data } = await api.getOrgTree()
return data
}
async loadAreaData() {
const { data } = await api.getAreaTree()
return data
}
async loadMemberOwn(id) {
const { data } = await api.sysUserOwnData({ id })
return data
}
render() {
return (
<Form ref={this.form} className="yo-form">
<Spin spinning={this.state.loading} indicator={<AntIcon type="loading" />}>
<div className="yo-form-group">
<Form.Item label="选择机构" name="grantOrgIdList">
<TreeSelect
showCheckedStrategy="SHOW_PARENT"
treeData={this.state.options.orgData}
placeholder="请选择机构"
treeCheckable
/>
</Form.Item>
<Form.Item label="选择区域" name="grantAreaCodeList">
<TreeSelect
showCheckedStrategy="SHOW_PARENT"
treeData={this.state.options.areaData}
placeholder="请选择所属区域"
treeCheckable
/>
</Form.Item>
</div>
</Spin>
</Form>
)
}
}

View File

@@ -1,11 +1,26 @@
import React, { Component } from 'react' import React, { Component } from 'react'
import { Button, Card, Descriptions, Form, Input, List, message as Message, Popconfirm, Select, Switch } from 'antd' import {
Button,
Card,
Descriptions,
Form,
Input,
List,
message as Message,
Popconfirm,
Select,
Switch,
Dropdown,
Menu,
} from 'antd'
import { AntIcon, Auth, Container, Image, ModalForm, QueryList, QueryTreeLayout } from 'components' import { AntIcon, Auth, Container, Image, ModalForm, QueryList, QueryTreeLayout } from 'components'
import { api } from 'common/api' import { api } from 'common/api'
import { toCamelCase } from 'util/format' import { toCamelCase } from 'util/format'
import { isEqual } from 'lodash' import { isEqual } from 'lodash'
import getDictData from 'util/dic' import getDictData from 'util/dic'
import FormBody from './form' import FormBody from './form'
import RoleForm from './role'
import DataForm from './data'
// 配置页面所需接口函数 // 配置页面所需接口函数
const apiAction = { const apiAction = {
@@ -16,19 +31,21 @@ const apiAction = {
delete: api.sysUserDelete, delete: api.sysUserDelete,
changeStatus: api.sysUserChangeStatus, changeStatus: api.sysUserChangeStatus,
resetPwd: api.sysUserResetPwd resetPwd: api.sysUserResetPwd,
grantRole: api.sysUserGrantRole,
grantData: api.sysUserGrantData,
} }
// 用于弹窗标题 // 用于弹窗标题
const name = '用户' const name = '用户'
export default class index extends Component { export default class index extends Component {
state = { state = {
codes: { codes: {
sex: [], sex: [],
commonStatus: [] commonStatus: [],
} },
} }
// 表格实例 // 表格实例
@@ -39,6 +56,8 @@ export default class index extends Component {
// 编辑窗口实例 // 编辑窗口实例
editForm = React.createRef() editForm = React.createRef()
roleForm = React.createRef()
dataForm = React.createRef()
// 树选中节点 // 树选中节点
selectId = undefined selectId = undefined
@@ -46,9 +65,9 @@ export default class index extends Component {
* 阻止外部组件引发的渲染,提升性能 * 阻止外部组件引发的渲染,提升性能
* 可自行添加渲染条件 * 可自行添加渲染条件
* [必要] * [必要]
* @param {*} props * @param {*} props
* @param {*} state * @param {*} state
* @returns * @returns
*/ */
shouldComponentUpdate(props, state) { shouldComponentUpdate(props, state) {
return !isEqual(this.state, state) return !isEqual(this.state, state)
@@ -61,28 +80,30 @@ export default class index extends Component {
componentDidMount() { componentDidMount() {
this.list.current.onLoading() this.list.current.onLoading()
getDictData('sex', 'common_status').then(res => { getDictData('sex', 'common_status').then(res => {
this.setState({ this.setState(
codes: res {
}, () => { codes: res,
this.list.current.onLoadData() },
}) () => {
this.list.current.onLoadData()
}
)
}) })
} }
/** /**
* 调用加载数据接口,可在调用前对query进行处理 * 调用加载数据接口,可在调用前对query进行处理
* [异步,必要] * [异步,必要]
* @param {*} params * @param {*} params
* @param {*} query * @param {*} query
* @returns * @returns
*/ */
loadData = async (params, query) => { loadData = async (params, query) => {
query = { query = {
...query, ...query,
sysEmpParam: { sysEmpParam: {
orgId: this.selectId orgId: this.selectId,
} },
} }
const { data } = await apiAction.page({ const { data } = await apiAction.page({
@@ -105,7 +126,7 @@ export default class index extends Component {
/** /**
* 树节点选中事件 * 树节点选中事件
* [必要] * [必要]
* @param {*} id * @param {*} id
*/ */
onSelectTree(id) { onSelectTree(id) {
this.selectId = id this.selectId = id
@@ -114,15 +135,15 @@ export default class index extends Component {
/** /**
* 绑定字典数据 * 绑定字典数据
* @param {*} code * @param {*} code
* @param {*} name * @param {*} name
* @returns * @returns
*/ */
bindCodeValue(code, name) { bindCodeValue(code, name) {
name = toCamelCase(name) name = toCamelCase(name)
const codes = this.state.codes[name] const codes = this.state.codes[name]
if (codes) { if (codes) {
const c = codes.find((p) => p.code == code) const c = codes.find(p => p.code == code)
if (c) { if (c) {
return c.value return c.value
} }
@@ -132,21 +153,21 @@ export default class index extends Component {
/** /**
* 打开新增/编辑弹窗 * 打开新增/编辑弹窗
* @param {*} modal * @param {*} modal
* @param {*} record * @param {*} record
*/ */
onOpen(modal, record) { onOpen(modal, record) {
modal.current.open({ modal.current.open({
orgId: this.selectId, orgId: this.selectId,
record record,
}) })
} }
/** /**
* 对表格上的操作进行统一处理 * 对表格上的操作进行统一处理
* [异步] * [异步]
* @param {*} action * @param {*} action
* @param {*} successMessage * @param {*} successMessage
*/ */
async onAction(action, successMessage) { async onAction(action, successMessage) {
this.list.current.onLoading() this.list.current.onLoading()
@@ -161,13 +182,10 @@ export default class index extends Component {
/** /**
* 删除 * 删除
* @param {*} record * @param {*} record
*/ */
onDelete(record) { onDelete(record) {
this.onAction( this.onAction(apiAction.delete(record), '删除成功')
apiAction.delete(record),
'删除成功'
)
} }
//#region 自定义方法 //#region 自定义方法
@@ -175,25 +193,51 @@ export default class index extends Component {
return ( return (
<List.Item <List.Item
key={record.id} key={record.id}
actions={ actions={[
[ <Auth auth="sysUser:edit">
<Auth auth="sysUser:edit"> <a onClick={() => this.onOpen(this.editForm, record)}>编辑</a>
<a onClick={() => this.onOpen(this.editForm, record)}>编辑</a> </Auth>,
</Auth>, <Auth auth="sysOrg:delete">
<Auth auth="sysOrg:delete"> <Popconfirm
<Popconfirm placement="topRight"
placement="topRight" title="是否确认删除"
title="是否确认删除" onConfirm={() => this.onDelete(record)}
onConfirm={() => this.onDelete(record)} >
> <a>删除</a>
<a>删除</a> </Popconfirm>
</Popconfirm> </Auth>,
</Auth>, <Auth aut="sysUser:resetPwd">
<Auth aut="sysUser:resetPwd"> <a onClick={() => this.onResetPassword(record)}>重置密码</a>
<a onClick={() => this.onResetPassword(record)}>重置密码</a> </Auth>,
</Auth> <Auth auth={{ sysRole: [['grantRole'], ['grantData']] }}>
] <Dropdown
} placement="bottomRight"
overlay={
<Menu>
<Auth auth="sysRole:grantRole">
<Menu.Item>
<a onClick={() => this.onOpen(this.roleForm, record)}>
授权角色
</a>
</Menu.Item>
</Auth>
<Auth auth="sysRole:grantData">
<Menu.Item>
<a onClick={() => this.onOpen(this.dataForm, record)}>
授权额外数据
</a>
</Menu.Item>
</Auth>
</Menu>
}
>
<a className="ant-dropdown-link">
授权
<AntIcon type="down" />
</a>
</Dropdown>
</Auth>,
]}
> >
<List.Item.Meta <List.Item.Meta
avatar={ avatar={
@@ -209,7 +253,9 @@ export default class index extends Component {
description={record.account} description={record.account}
/> />
<Descriptions className="flex-1" column={2}> <Descriptions className="flex-1" column={2}>
<Descriptions.Item label="性别">{this.bindCodeValue(record.sex, 'sex')}</Descriptions.Item> <Descriptions.Item label="性别">
{this.bindCodeValue(record.sex, 'sex')}
</Descriptions.Item>
<Descriptions.Item label="手机">{record.phone || '未设置'}</Descriptions.Item> <Descriptions.Item label="手机">{record.phone || '未设置'}</Descriptions.Item>
<Descriptions.Item label="邮箱">{record.email || '未设置'}</Descriptions.Item> <Descriptions.Item label="邮箱">{record.email || '未设置'}</Descriptions.Item>
</Descriptions> </Descriptions>
@@ -228,21 +274,14 @@ export default class index extends Component {
</div> </div>
</List.Item> </List.Item>
) )
} }
onSetUserStatus(record, checked) { onSetUserStatus(record, checked) {
this.onAction( this.onAction(apiAction.changeStatus({ id: record.id, status: +!checked }), '设置成功')
apiAction.changeStatus({ id: record.id, status: +!checked }),
'设置成功'
)
} }
onResetPassword(record) { onResetPassword(record) {
this.onAction( this.onAction(apiAction.resetPwd(record), '重置成功')
apiAction.resetPwd(record),
'重置成功'
)
} }
//#endregion //#endregion
@@ -251,7 +290,7 @@ export default class index extends Component {
<QueryTreeLayout <QueryTreeLayout
loadData={this.loadTreeData} loadData={this.loadTreeData}
defaultExpanded={true} defaultExpanded={true}
onSelect={(key) => this.onSelectTree(key)} onSelect={key => this.onSelectTree(key)}
> >
<Container mode="fluid"> <Container mode="fluid">
<Card bordered={false}> <Card bordered={false}>
@@ -273,14 +312,13 @@ export default class index extends Component {
placeholder="请选择状态" placeholder="请选择状态"
className="w-200" className="w-200"
> >
{ {this.state.codes.commonStatus.map(item => {
this.state.codes.commonStatus.map(item => { return (
return <Select.Option <Select.Option key={item.code} item={item.code}>
key={item.code} {item.value}
item={item.code} </Select.Option>
>{item.value}</Select.Option> )
}) })}
}
</Select> </Select>
</Form.Item> </Form.Item>
</Auth> </Auth>
@@ -289,9 +327,11 @@ export default class index extends Component {
<Button <Button
icon={<AntIcon type="plus" />} icon={<AntIcon type="plus" />}
onClick={() => this.onOpen(this.addForm)} onClick={() => this.onOpen(this.addForm)}
>新增{name}</Button> >
新增{name}
</Button>
} }
renderItem={(record) => this.renderItem(record)} renderItem={record => this.renderItem(record)}
/> />
</Card> </Card>
</Container> </Container>
@@ -313,6 +353,24 @@ export default class index extends Component {
> >
<FormBody mode="edit" /> <FormBody mode="edit" />
</ModalForm> </ModalForm>
<ModalForm
title="角色授权"
action={apiAction.grantRole}
ref={this.roleForm}
onSuccess={() => this.list.current.onReloadData()}
>
<RoleForm />
</ModalForm>
<ModalForm
title="数据授权"
action={apiAction.grantData}
ref={this.dataForm}
onSuccess={() => this.list.current.onReloadData()}
>
<DataForm />
</ModalForm>
</QueryTreeLayout> </QueryTreeLayout>
) )
} }

View File

@@ -0,0 +1,99 @@
import React, { Component } from 'react'
import { Form, Spin, Select } from 'antd'
import { AntIcon } from 'components'
import { cloneDeep } from 'lodash'
import { api } from 'common/api'
export default class role extends Component {
state = {
// 加载状态
loading: true,
options: {
roleData: [],
},
roles: [],
}
// 表单实例
form = React.createRef()
// 初始化数据
record = {}
/**
* mount后回调
*/
componentDidMount() {
this.props.created && this.props.created(this)
}
async fillData(params) {
this.record = cloneDeep(params.record)
//#region 从后端转换成前段所需格式
const roleData = await this.loadRoleData()
const roles = await this.loadRole(this.record.id)
this.setState({
options: {
roleData,
},
roles,
})
this.form.current.setFieldsValue({
id: this.record.id,
grantRoleIdList: roles,
})
this.setState({
loading: false,
})
}
/**
* 获取数据
* 可以对postData进行数据结构调整
* [异步,必要]
* @returns
*/
async getData() {
const form = this.form.current
const valid = await form.validateFields()
if (valid) {
const postData = form.getFieldsValue()
if (this.record) {
postData.id = this.record.id
}
//#region 从前段转换后端所需格式
//#endregion
return postData
}
}
async loadRoleData() {
const { data } = await api.getRolePage()
return data.items
}
async loadRole(id) {
const { data } = await api.sysUserOwnRole({ id })
return data
}
render() {
return (
<Form ref={this.form} className="yo-form">
<Spin spinning={this.state.loading} indicator={<AntIcon type="loading" />}>
<div className="yo-form-group">
<Form.Item label="请选择角色" name="grantRoleIdList">
<Select mode="multiple" placeholder="请选择角色">
{this.state.options.roleData.map(item => {
return (
<Select.Option key={item.id} value={item.id}>
{item.name}
</Select.Option>
)
})}
</Select>
</Form.Item>
</div>
</Spin>
</Form>
)
}
}