Commit a3d015fe authored by 前端-许佳敏's avatar 前端-许佳敏

用户管理

parent 060069e7
......@@ -29,7 +29,8 @@ export default {
path: '/authConfig/userSystem/userDetail',
name: 'userSystem',
component: '@/pages/authConfig/userSystem/userDetail',
hideInMenu: true
hideInMenu: true,
hidePageHeader: true
},
],
}
\ No newline at end of file
......@@ -7,6 +7,7 @@
"scripts:build-yxc": "node scripts/run http://yxc-web-demo.shushangyun.com/api",
"start": "yarn api && yarn scripts:build && umi dev",
"build": "yarn api && yarn scripts:build && umi build",
"build:yxc": "yarn api && yarn scripts:build-yxc && umi build",
"build:dev": "pm2 start scripts/devServer.js",
"build:analyze": "ANALYZE=1 umi build",
"postinstall": "umi generate tmp",
......
.common_detail_page {
margin: -24px;
// margin: -24px;
.common_header {
display: flex;
......
import React, { useState, ReactText, useImperativeHandle, useEffect, useRef } from 'react'
import { Tree, Space, Tooltip, Button } from 'antd'
import { findItemAndDelete, findTreeKeys } from '@/utils'
import { findItemAndDelete, findTreeKeys, treeReduction, getParentTreeTitles } from '@/utils'
import './index.less'
import deepClone from 'clone'
import { TreeProps } from 'antd/lib/tree'
......@@ -17,6 +17,7 @@ export interface TabTreeActions {
setExpandedKeys: (keys: ReactText[]) => void,
setSelectKey: (key: ReactText) => void
setSelectKeys: (keys: ReactText[]) => void
getParentPath: (id: ReactText) => string
}
export interface toolsRenderProps {
......@@ -63,6 +64,7 @@ export const createTreeActions = () => {
setSelectKey(){},
setSelectKeys(){},
setExpandedKeys(){},
getParentPath(id){return ''},
}
return actions
}
......@@ -163,6 +165,8 @@ const TabTree:React.FC<TabTreeProps> = (props) => {
checkedKeys,
[]
);
console.log(treeReduction(treeData))
useEffect(() => {
if (getMenuSelectData) {
getMenuSelectData().then(res => {
......@@ -193,6 +197,10 @@ const TabTree:React.FC<TabTreeProps> = (props) => {
selfActions.setSelectKey = (key: ReactText) => {
setSelectKey(key)
}
selfActions.getParentPath = (id: ReactText) => {
return getParentTreeTitles(treeData, id)
}
}
const batchSelect = (items: any[]) => {
......
/*
* @Author: LeeJiancong
* @Date: 2020-07-22 09:54:50
* @LastEditors: LeeJiancong
* @LastEditTime: 2020-07-30 19:28:23
*/
/**
* 正则表达式集合
*/
export const PATTERN_MAPS = {
// 8-20位, 大小写字幕 + 数字组合
password: /^(?=.*[a-z])(?=.*[A-Z])[a-zA-Z\d]{8,20}$/,
email: /^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$/,
phone: /^1[3|4|5|6|7|8|9][0-9]{9}$/,
smsCode: /^\d{6}$/,
money:/^\d*(?:\.\d{0,2})?$/,
weight:/^\d*(?:\.\d{0,3})?$/,
}
\ No newline at end of file
......@@ -23,7 +23,7 @@ export function useHttpRequest<T>(api: (params?, config?) => Promise<T>, config?
setLoading(true)
api(params).then((res: any) => {
setData(res.data)
if (config && config.back) {
if (res.code === 1000 && config && config.back) {
setTimeout(() => {
goBack()
}, 1000)
......
......@@ -94,7 +94,7 @@ const UserSystem: React.FC<{}> = () => {
dataIndex: 'option',
align: 'center',
render: (text:any, record:any) => {
return record.state === 0 && (
return record.status === 0 && (
<>
<Popconfirm
title="确定要执行这个操作?"
......
import { ISchema } from '@formily/antd';
import { PATTERN_MAPS } from '@/constants/regExp';
export const UserDetailSchema:ISchema = {
type: 'object',
......@@ -21,6 +22,12 @@ export const UserDetailSchema:ISchema = {
password: {
type: 'password',
title: '登录密码',
"x-rules": [
{
pattern: PATTERN_MAPS.password,
message: '请输入由大小写字母和数字组成的8位密码'
}
],
required: true
},
name: {
......@@ -36,6 +43,12 @@ export const UserDetailSchema:ISchema = {
phone: {
type: 'number',
title: '手机号',
"x-rules": [
{
pattern: PATTERN_MAPS.phone,
message: '请输入正确的手机号'
}
],
required: true
},
idCardNo: {
......@@ -44,13 +57,19 @@ export const UserDetailSchema:ISchema = {
},
email: {
type: 'string',
title: '邮箱'
title: '邮箱',
"x-rules": [
{
pattern: PATTERN_MAPS.email,
message: '请输入正确的邮箱'
}
]
},
jobTitle: {
type: 'string',
title: '职位'
},
orgId: {
orgName: {
type: 'string',
title: '所属组织机构',
required: true,
......@@ -59,6 +78,10 @@ export const UserDetailSchema:ISchema = {
addonAfter: "{{connectCategory}}"
},
},
orgId: {
type: 'string',
visible: false
},
memberRoleIds: {
required: true,
type: 'array:string',
......
import React, { useRef, useState, useEffect } from 'react';
import { Button, Modal, Tag, Row, Col } from 'antd';
import { Form, FormItem, createFormActions } from '@formily/antd'
import { Form, FormItem, createFormActions, FormButtonGroup, Submit } from '@formily/antd'
import { Input } from '@formily/antd-components'
import { PlusOutlined, LinkOutlined } from '@ant-design/icons';
import {StandardTable} from 'god'
......@@ -14,7 +14,10 @@ import { UserDetailSchema } from './schema';
import './index.less'
import ModalTable from '@/components/ModalTable';
import { useRowSelectionTable } from '@/hooks/useRowSelectionTable';
import { findItemAndDelete } from '@/utils';
import { findItemAndDelete, omit } from '@/utils';
import TabTree, { useTreeActions } from '@/components/TabTree';
import { useTreeTabs } from '@/hooks/useTreeTabs';
import { useHttpRequest } from '@/hooks/useHttpRequest';
// 定义选择的行数据的类型
type Item = any
......@@ -26,9 +29,15 @@ const titleRender = (title) => {
return ''
}
const fetchOriginTreeData = async (params?) => { // 平台后台树
const res = await PublicApi.getMemberOrgTree()
return res
}
const userActions = createFormActions()
const AddUser: React.FC<{}> = () => {
const [originVisible, setOriginVisible] = useState(false)
const checkBoxRef = useRef<any[]>([])
const [roleVisible, setRoleVisible] = useState(false)
const [selectedRowKeys, setSelectedRowKeys] = useState<Array<string>>([])
......@@ -36,28 +45,33 @@ const AddUser: React.FC<{}> = () => {
const [formData, setFormData] = useState<any>(null)
const { id, pageStatus } = usePageStatus()
const [roleSelection, roleSelectCtl] = useRowSelectionTable()
const originTreeActions = useTreeActions()
const [originSelectNode, setOriginSelectNode] = useState<any>()
const { data, loading, err, run } = useHttpRequest(id ? PublicApi.postMemberUserUpdate : PublicApi.postMemberUserAdd)
const {
treeData: originTreeData,
} = useTreeTabs({
fetchMenuData: fetchOriginTreeData,
})
useEffect(() => {
if (id) {
// PublicApi.getMiddlegroundUserDetailsById({
// userId: id
// }).then(res => {
// const { data } = res
// setFormData(data)
// setSelectRow(data.roles)
// })
PublicApi.getMemberUserGet({
userId: id
}).then(async res => {
const { data } = res
setFormData(data)
})
}
}, [])
const onFinish = async (values:any) => {
if (values.roles) {
delete values.roles
}
let value = { ...values }
const fn = id ? PublicApi.postMemberUserUpdate : PublicApi.postMemberUserAdd
values.memberRoleIds = values.memberRoleIds.map(v => v.id)
const omitValue = omit(values, ['orgName'])
const params = id ? {
...value,
id: Number(id)
} : value
await fn(params)
...omitValue,
userId: Number(id)
} : omitValue
await run(params)
history.goBack(-1)
};
......@@ -99,19 +113,45 @@ const AddUser: React.FC<{}> = () => {
const handleCloseTag = (removedTag: any) => {
};
const handleOrigin = () => {
setOriginVisible(false)
if(originSelectNode?.id){
userActions.setFieldValue('orgName', originTreeActions.getParentPath(originSelectNode.id))
userActions.setFieldValue('orgId', originSelectNode.id)
}
}
const handleAddRole = () => {
setRoleVisible(true);
}
const connectCategory = <div className='connectBtn' ><LinkOutlined style={{marginRight: 4}}/>关联</div>
const handlePlateformSelect = (key, node) => {
setOriginSelectNode({id: key*1, name: node._title})
}
const openOriginTree = () => {
setOriginVisible(true)
}
const connectCategory = <div className='connectBtn' onClick={openOriginTree}><LinkOutlined style={{marginRight: 4}}/>关联</div>
const addRoles = <Button block onClick={() => setRoleVisible(true)}>添加角色</Button>
return (
<DetailPage title={titleRender(pageStatus)}>
<div className="common-wrapper user-system">
<NiceForm
onSubmit={onFinish}
schema={UserDetailSchema}
initialValues={formData}
actions={userActions}
effects={($, {setFieldState}) => {
$('onFormInit').subscribe(() => {
if (id) {
setFieldState('password', state => {
state.visible = false
})
}
})
}}
expressionScope={{
connectCategory,
addRoles,
......@@ -120,7 +160,12 @@ const AddUser: React.FC<{}> = () => {
roleSelectCtl.setSelectedRowKeys(findItemAndDelete(roleSelectCtl.selectedRowKeys, id))
}
}}
/>
>
<FormButtonGroup offset={6}>
<Button htmlType='submit' type='primary' loading={loading}>提交</Button>
<Button>取消</Button>
</FormButtonGroup>
</NiceForm>
<ModalTable
modalTitle='选择角色'
visible={roleVisible}
......@@ -151,40 +196,25 @@ const AddUser: React.FC<{}> = () => {
}
}
/>
{/* <Modal
title="选择角色"
visible={roleVisible}
onOk={handleSelectOk}
onCancel={handleSelectCancel}
<Modal
title="选择组织机构"
visible={originVisible}
onOk={handleOrigin}
onCancel={() => setOriginVisible(false)}
okText="确认"
cancelText="取消"
getContainer='#root'
// destroyOnClose={true}
>
<StandardTable
columns={columns}
currentRef={ref}
rowSelection={rowSelection}
fetchTableData={(params:any) => fetchUserList(params)}
tableProps={{ rowKey: 'id' }}
formilyProps={{
layouts: {
order: 3
},
ctx: {
schema: {
type: 'object',
properties: {
name: {
type: 'Search',
"x-component-props": {
placeholder: '请输入角色名称'
}
}
}
}
}
}}
<TabTree
fetchData = {params => fetchOriginTreeData(params)}
treeData={originTreeData}
handleSelect={(key, node) => handlePlateformSelect(key, node)}
actions={originTreeActions}
customKey="id"
/>
</Modal> */}
</Modal>
</div>
</DetailPage>
......
......@@ -174,6 +174,41 @@ export const findTreeKeys = (arr: any[], keyword?: string) => {
return results
}
// 树形结构降为一维对象处理
export const treeReduction = (data: any[]) => {
const hashMaps = {}
const selfData: any[] = deepClone(data)
while (selfData.length > 0) {
const useItem = selfData.shift()
// 存在子集
if (useItem.children && useItem.children.length > 0) {
useItem.children = useItem.children.map(v => {
v.parentId = useItem.id
return v
})
selfData.push(...useItem.children)
}
hashMaps[useItem.id] = useItem
}
return hashMaps
}
// 获取某一节点的title路径
export const getParentTreeTitles = (dataSouce, key) => {
const hashMaps = treeReduction(dataSouce)
let targetKey = key
let targetPath = ''
while (targetKey !== '') {
const title = hashMaps[targetKey].title
targetPath = targetPath === '' ? title : `${title}-${targetPath}`
targetKey = hashMaps[targetKey].parentId || ''
}
return targetPath
}
// 数组通过某个key进行去重合并, 并返回一个新数组
export const mergeArrByKey = (preArr: any[], nextArr: any[], target?: string) => {
const mergeArr = preArr.concat(nextArr)
......
......@@ -90,13 +90,12 @@ class ApiRequest {
baseRequest<IRequestSuccess<T>>(url, options).then(res => {
// 登录验证
if (res.code === 1101) {
message.error(res.message)
if (isDev) {
return ;
}
removeAuth()
history.replace('/login')
message.error(res.message)
return false
}
......
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