Commit 72da5a8f authored by 田翔's avatar 田翔

fix: 人员选择器树形完善,三种形态支持ID存储,部门选择器支持ID存储

parent 0da04954
{
"name": "panda-xform",
"version": "1.6.8",
"description": "1.6.8: 联动逻辑数据调整",
"version": "1.6.9",
"description": "1.6.9: 人员选择器树形完善,三种形态支持ID存储,部门选择器支持ID存储",
"keywords": [
"panda-xform"
],
......
......@@ -38,11 +38,10 @@ export function getStationListByUserID(id, isAll) {
});
}
//人员选择器获取
//人员选择器获取(三种形态)
export function getUserSelector(role, userID) {
return request({
// url: `/PandaWorkFlow/WorkFlow/WorkFlow/GetUserSelector?${role ? 'role=' + role : ''}${userID ? '$userID=' + userID : ''}`,
url: `/PandaWorkFlow/WorkFlow/WorkFlow/GetUserSelector`,
url: `/PandaWorkFlow/WorkFlow/WorkFlow/GetUserSelector?${role ? 'role=' + role : ''}${userID ? '&userID=' + userID : ''}`,
method: 'get',
});
}
......
......@@ -1686,7 +1686,19 @@ const businessWidgets = [
type: 'string',
displayType: 'row',
labelWidth: 80,
// required: "{{formData.interactiveType === '下拉框'}}",
},
isMySite: {
title: '本人站点',
name: '本人站点',
required: true,
default: false,
type: 'boolean',
widget: 'checkbox',
props: {
style: {
paddingLeft: '10px'
}
}
},
groupSetting: {
title: '控件设置',
......@@ -2854,20 +2866,130 @@ const advancedWidgets = [
},
},
},
// {
// text: '手写签名',
// name: '手写签名',
// schema: {
// title: '手写签名',
// name: '手写签名',
// type: 'string',
// widget: 'Signature',
// width: '100%',
// },
// setting: {
// },
// }
{
text: '自动计算',
name: '自动计算',
schema: {
title: '自动计算',
name: '自动计算',
type: 'string',
widget: 'AutoCalculate',
},
setting: {
groupBase: {
title: '基础信息',
type: 'object',
properties: {}
},
$id: {
title: '字段名称',
type: 'string',
widget: 'FieldNames',
required: true,
displayType: 'row',
labelWidth: 80,
},
title: {
title: '标题',
required: true,
type: 'string',
widget: 'htmlInput',
displayType: 'row',
labelWidth: 80,
},
placeholder: {
title: '提示语',
type: 'string',
displayType: 'row',
labelWidth: 80,
// default: '该组件用于自动计算'
},
presetValue: {
title: '默认值',
type: 'number',
widget: 'NumerDefault',
displayType: 'row',
labelWidth: 80,
},
groupSetting: {
title: '控件设置',
type: 'object',
properties: {}
},
required: {
title: '必填',
type: 'boolean',
default: false,
width: '40%',
props: {
style: {
marginLeft: '10px'
}
}
},
disabled: {
title: '只读',
type: 'boolean',
widget: 'checkbox',
default: true,
width: '30%',
},
hidden: {
title: '隐藏',
type: 'boolean',
widget: 'checkbox',
default: false,
width: '30%',
},
description: {
title: '说明',
type: 'string',
displayType: 'row',
labelWidth: 55,
},
// groupStyle: {
// title: '控件样式',
// type: 'object',
// properties: {}
// },
// prefix: {
// title: '前缀',
// type: 'string',
// widget: 'htmlInput',
// displayType: 'row',
// labelWidth: 60,
// },
// formatter: {
// title: '格式化',
// type: 'string',
// displayType: 'row',
// labelWidth: 60,
// widget: 'select',
// enum: ['%', '‰'],
// default: '',
// enumNames: ['%', '‰'],
// props: {
// allowClear: true
// }
// },
width: {
title: '元素宽度',
type: 'string',
widget: 'percentSlider',
},
labelWidth: {
title: '标签宽度',
description: '默认值110',
default: 110,
type: 'number',
widget: 'slider',
max: 400,
props: {
hideNumber: true,
},
},
},
},
]
const settings = [
......
import React, { useState, useContext, forwardRef, useImperativeHandle, createContext } from 'react'
import React, { useMemo, useContext, forwardRef, useImperativeHandle, createContext } from 'react'
import FormRender, { useForm } from 'form-render'
import { ConfigProvider } from 'antd'
import widgets from '../widgets'
......@@ -20,11 +20,16 @@ const XRender = (props, ref) => {
const pandaXform = getPrefixCls()
const form = useForm()
const watch = {
'#': (value) => {
console.log('value', value)
}
}
const watch = useMemo(() => {
console.log('schema', schema)
return {}
}, [schema])
// const watch = {
// '#': (value) => {
// console.log('value', value)
// }
// }
const getValues = async () => {
let { data, errors } = await form.submit()
......
import React from 'react'
import { InputNumber } from 'antd'
const AutoCalculate = () => {
const AutoCalculate = (props) => {
const { value, onChange, schema, addons } = props
const { disabled } = schema
return (
<div></div>
<InputNumber
style={{ width: '100%' }}
disabled={disabled}
>
</InputNumber>
)
}
......
......@@ -3,10 +3,21 @@ import { TreeSelect, message } from 'antd'
import { DownOutlined } from '@ant-design/icons'
import { getDeptList } from '../../../../apis/process'
const getList = (deptList) => {
if (Array.isArray(deptList)) {
deptList.forEach(v => {
v.deptId = v.deptId + ''
getList(v.childDepts)
})
}
return deptList
}
const DeptSelector = (props) => {
const { value, onChange, schema, addons } = props
const { isMultiple, disabled, placeholder, presetValue } = schema
const { isMultiple, disabled, placeholder, presetValue, isStoreID } = schema
const property = isStoreID ? 'deptId' : 'deptName'
const [treeData, setTreeData] = useState([])
const treeChange = (value) => {
......@@ -26,7 +37,7 @@ const DeptSelector = (props) => {
if (addons) {
const { code, data, msg } = await getDeptList()
if (code === 0) {
setTreeData(data)
setTreeData(getList(data))
} else {
message.error(msg)
}
......@@ -41,13 +52,19 @@ const DeptSelector = (props) => {
}
}, [presetValue])
useEffect(() => {
if (isStoreID) {
iconClick()
}
}, [])
return (
<TreeSelect
style={{ width: '100%' }}
disabled={disabled}
multiple={isMultiple}
switcherIcon={<DownOutlined />}
fieldNames={{ label: 'deptName', value: 'deptName', children: 'childDepts' }}
fieldNames={{ label: 'deptName', value: property, children: 'childDepts' }}
treeData={treeData}
onChange={treeChange}
onFocus={iconClick}
......
import React, { useEffect, useMemo, useState } from 'react'
import { Select, Input, message, Modal, Spin, Checkbox, Row, Col, Radio } from 'antd'
import { Input, message, Modal, Spin, Checkbox, Row, Col, Radio } from 'antd'
import { UserAddOutlined } from '@ant-design/icons'
import styles from '../index.less'
import { getMenTreeByRole, getUserListForRole } from '../../../../../apis/process'
import { getUserSelector } from '../../../../../apis/process'
const getUSerName = (groupList, value, isMultiple, property) => {
let users = []
if (Array.isArray(groupList)) {
groupList.forEach(v => {
if (Array.isArray(v.userList)) {
if (isMultiple) {
v.userList.forEach(s => {
if (value.split(',').includes(s[property])) {
users.push(s)
}
})
} else {
users = v.userList.filter(s => s[property] === value)
}
}
})
}
return users.map(v => v.userName).join(',')
}
const UserGroup = (props) => {
const userID = window?.globalConfig?.userInfo?.OID || 1
const { value, onChange, schema, addons } = props
const { disabled, isMultiple, placeholder, presetValue, role, isStoreID } = schema
const { disabled, isMultiple, placeholder, role, isStoreID, isMySite, presetValue } = schema
const property = isStoreID ? 'userID' : 'userName'
const [groupPerson, setGroupPerson] = useState([])
const [visible, setVisible] = useState(false)
const [loading, setLoading] = useState(false)
......@@ -16,13 +37,35 @@ const UserGroup = (props) => {
const [radio, setRadio] = useState(null)
const [search, setSearch] = useState(null)
const groupList = useMemo(() => {
let array = []
if (Array.isArray(groupPerson)) {
groupPerson.forEach(v => {
let userList = []
if (Array.isArray(v.userList)) {
v.userList.forEach(s => {
userList.push({ ...s, userID: s.userID })
})
}
array.push({ ...v, userList })
})
}
return array
}, [groupPerson])
const valueShow = useMemo(() => {
if (value) {
return getUSerName(groupList, value, isMultiple, property)
}
return value
}, [groupList, isMultiple, value, property])
const groupPersonShow = useMemo(() => {
if (search) {
let array = []
groupPerson.forEach(v => {
groupList.forEach(v => {
let userList = []
let noShowParent = !v.ouName.includes(search)
console.log(noShowParent, v.ouName, search)
v.userList.forEach(s => {
let noShow = !s.userName.includes(search)
if (!noShow) {
......@@ -34,12 +77,12 @@ const UserGroup = (props) => {
})
return array
}
return groupPerson
}, [search, groupPerson])
return groupList
}, [search, groupList])
const onOk = () => {
if (addons) {
addons.setValue(addons.dataPath, isMultiple ? check.join(',') : radio)
onChange(isMultiple ? check.join(',') : radio)
}
setVisible(false)
}
......@@ -76,28 +119,32 @@ const UserGroup = (props) => {
const inputFocus = async () => {
if (addons) {
getData()
setVisible(true)
setLoading(true)
const { code, data, msg } = await getUserListForRole({})
if (code === 0) {
if (Array.isArray(data)) {
setGroupPerson(data)
}
} else {
message.error(msg)
}
setLoading(false)
}
}
const getCount = (v) => {
let array = v.userList.filter(s => check.includes(s.userName))
let array = v.userList.filter(s => check.includes(s[property]))
if (Array.isArray(array)) {
return array.length
}
return 0
}
const getData = async () => {
setLoading(true)
const { code, data, msg } = await getUserSelector(role, isMySite ? userID : false)
if (code === 0) {
if (Array.isArray(data.groupList)) {
setGroupPerson(data.groupList)
}
} else {
message.error(msg)
}
setLoading(false)
}
useEffect(() => {
if (isMultiple) {
setCheck(value ? value.split(',') : [])
......@@ -106,11 +153,21 @@ const UserGroup = (props) => {
}
}, [isMultiple, value])
useEffect(() => {
if (isStoreID) {
getData()
}
}, [])
useEffect(() => {
onChange(presetValue)
}, [presetValue])
return (
<div className={styles.personGroup}>
<Input
disabled={disabled}
value={isMultiple ? (value ? value.split(',') : []) : value}
value={valueShow}
placeholder={disabled ? null : placeholder}
onClick={inputFocus}
addonAfter={disabled ? null : <UserAddOutlined style={{ color: 'rgba(0, 0, 0, 0.25)' }} onClick={inputFocus} />}
......@@ -146,7 +203,7 @@ const UserGroup = (props) => {
let checkCount = getCount(v)
let type = getGorupType(v, checkCount)
return (
<div className={styles.groupUser} style={{ display: v.noShow ? 'none' : 'block' }}>
<div key={v.ouid} className={styles.groupUser} style={{ display: v.noShow ? 'none' : 'block' }}>
<div className={styles.groupName} onClick={() => checkGroup(v, type)}>
<span className={styles.groupCheck} type={type}></span>
<span>{v.ouName + `${checkCount}/${v.userList.length}`}</span>
......@@ -157,7 +214,7 @@ const UserGroup = (props) => {
return (
<Col span={8} key={s.userID} style={{ margin: '8px 0', display: s.noShow ? 'none' : 'block' }}>
<Checkbox
value={s.userName}
value={s[property]}
>
<div>{s.userName}</div>
</Checkbox>
......@@ -192,7 +249,7 @@ const UserGroup = (props) => {
return (
<Col span={8} style={{ margin: '8px 0', display: s.noShow ? 'none' : 'block' }} key={s.userID}>
<Radio
value={s.userName}
value={s[property]}
>
<div>{s.userName}</div>
</Radio>
......
import React, { useEffect, useMemo, useState } from 'react'
import { Select, Input, message, Modal, Spin, Checkbox, Row, Col, Radio } from 'antd'
import { UserAddOutlined } from '@ant-design/icons'
import { getMenTreeByRole, getUserListForRole } from '../../../../../apis/process'
import { Select, message } from 'antd'
import { getUserSelector } from '../../../../../apis/process'
const UserSelect = (props) => {
const userID = window?.globalConfig?.userInfo?.OID || 1
const { value, onChange, schema, addons } = props
const { disabled, isMultiple, placeholder, role, isStoreID } = schema
const { disabled, presetValue, isMultiple, placeholder, role, isStoreID, isMySite } = schema
const property = isStoreID ? 'userID' : 'userName'
const [pullDown, setPullDown] = useState([])
const selectFocus = async () => {
if (!role) {
return message.error('请配置机构角色!')
const valueShow = useMemo(() => {
if (value) {
if (isMultiple) {
return value.split(',')
}
}
const { code, data, msg } = await getMenTreeByRole({ userID, role: role })
return value
}, [value, isMultiple])
const selectFocus = async () => {
const { code, data, msg } = await getUserSelector(role, isMySite ? userID : false)
if (code === 0) {
if (data && data.childNodes) {
setPullDown(data.childNodes)
if (data) {
setPullDown(data.dropdownList.map(v => { return { label: v.userName, value: v[property] } }))
} else {
setPullDown([])
}
......@@ -32,19 +38,29 @@ const UserSelect = (props) => {
}
}
useEffect(() => {
onChange(presetValue)
}, [presetValue])
useEffect(() => {
if (isStoreID) {
selectFocus()
}
}, [])
return (
<Select
mode={isMultiple ? 'multiple' : null}
placeholder={disabled ? null : placeholder}
value={isMultiple ? (value ? value.split(',') : []) : value}
value={valueShow}
disabled={disabled}
showArrow={!disabled}
showSearch={true}
style={{ width: '100%' }}
onFocus={selectFocus}
onChange={selectChange}
options={pullDown}
>
{pullDown.map(v => <Select.Option key={v.value} value={v.value}>{v.text}</Select.Option>)}
</Select>
)
......
......@@ -21,7 +21,7 @@ const columns = [
}
]
const getUserList = (treeData, treeKey) => {
const getUserList = (treeData, treeKey, search) => {
let array = []
if (Array.isArray(treeData)) {
treeData.forEach(v => {
......@@ -33,7 +33,7 @@ const getUserList = (treeData, treeKey) => {
array.push(...getUserList(v.children, treeKey))
})
}
return array
return search ? array.filter(v => v.userName.includes(search)) : array
}
const getSelectUser = (treeData, selectKeys, property) => {
......@@ -47,11 +47,6 @@ const getSelectUser = (treeData, selectKeys, property) => {
}
})
}
// if (v.ouCode === treeKey[0]) {
// if (Array.isArray(v.userList)) {
// array.push(...v.userList)
// }
// }
array.push(...getSelectUser(v.children, selectKeys, property))
})
}
......@@ -62,37 +57,63 @@ const UserTree = (props) => {
const userID = window?.globalConfig?.userInfo?.OID || 1
const { value, onChange, schema, addons } = props
const { disabled, isMultiple, placeholder, presetValue, role, isStoreID } = schema
const { disabled, presetValue, isMultiple, placeholder, role, isMySite, isStoreID } = schema
const property = isStoreID ? 'userID' : 'userName'
const [visible, setVisible] = useState(false)
const [treeData, setTreeData] = useState([])
const [treeKey, setTreeKey] = useState([])
const [users, setUsers] = useState([])
const [selectKeys, setSelectKeys] = useState([])
const [search, setSearch] = useState('')
const userList = useMemo(() => {
return getUserList(treeData, treeKey)
}, [treeData, treeKey])
const selectKeys = useMemo(() => {
return value ? value.split(',') : []
}, [value, property])
return getUserList(treeData, treeKey, search)
}, [treeData, treeKey, search])
const selectUser = useMemo(() => {
return getSelectUser(treeData, selectKeys, property)
}, [treeData, selectKeys, property])
const valueShow = useMemo(() => {
if (isStoreID && value) {
return getSelectUser(treeData, value, 'userID').map(v => v.userName)
}
return value
}, [treeData, value, isStoreID])
const inputFocus = async () => {
setVisible(true)
const { code, data, msg } = await getUserSelector()
if (addons) {
setVisible(true)
getData()
}
}
const getData = async () => {
const { code, data, msg } = await getUserSelector(role, isMySite ? userID : false)
if (code === 0) {
setTreeData(data.treeList)
setSelectKeys(value ? value.split(',') : [])
} else {
message.error(msg)
}
}
useEffect(() => {
onChange(presetValue)
}, [presetValue])
useEffect(() => {
if (isStoreID) {
getData()
}
}, [])
const onOk = () => {
onChange(selectUser.map(v => v[property]).join(','))
setVisible(false)
}
const onCancel = () => {
setVisible(false)
}
const treeChange = (value) => {
......@@ -103,7 +124,7 @@ const UserTree = (props) => {
<div className={styles.userTree}>
<Input
disabled={disabled}
value={isMultiple ? (value ? value.split(',') : []) : value}
value={valueShow}
placeholder={disabled ? null : placeholder}
onClick={inputFocus}
addonAfter={disabled ? null : <UserAddOutlined style={{ color: 'rgba(0, 0, 0, 0.25)' }} onClick={inputFocus} />}
......@@ -114,7 +135,7 @@ const UserTree = (props) => {
title='人员选择器'
visible={visible}
bodyStyle={{ height: '600px' }}
onCancel={() => setVisible(false)}
onCancel={onCancel}
onOk={onOk}
getContainer={false}
>
......@@ -125,6 +146,7 @@ const UserTree = (props) => {
<Tree
value={treeKey}
fieldNames={{ title: 'ouName', key: 'ouCode' }}
blockNode
showIcon
defaultExpandAll
defaultSelectedKeys={['0-0-0']}
......@@ -136,7 +158,13 @@ const UserTree = (props) => {
</div>
<div className={styles.right}>
<div className={styles.title}>
<Input.Search placeholder='请输入姓名进行查找' style={{ width: '300px' }} />
<Input.Search
value={search}
allowClear
onChange={e => setSearch(e.target.value)}
placeholder='请输入姓名进行查找'
style={{ width: '300px' }}
/>
</div>
<div className={styles.list}>
<div className={styles.userList}>
......@@ -149,13 +177,17 @@ const UserTree = (props) => {
pagination={false}
bordered
rowSelection={{
type: 'checkbox',
type: isMultiple ? 'checkbox' : 'radio',
selectedRowKeys: selectKeys,
onChange: (select) => {
console.log('select', select)
let array = value ? value.split(',') : []
let users = array.concat(select)
onChange(users.join(','))
if (isMultiple) {
let noSelectUser = userList.filter(v => !select.includes(v[property])).map(v => v[property])
let users = selectKeys.concat(select)
let keys = users.filter(v => !noSelectUser.includes(v))
setSelectKeys(keys)
} else {
setSelectKeys(select)
}
}
}}
scroll={{ y: 180 }}
......@@ -166,10 +198,10 @@ const UserTree = (props) => {
<Table
rowKey={r => r[property]}
rowSelection={{
type: 'checkbox',
type: isMultiple ? 'checkbox' : 'radio',
selectedRowKeys: selectKeys,
onChange: (select) => {
onChange(select.join(','))
setSelectKeys(select)
}
}}
size='small'
......
......@@ -8,14 +8,6 @@ const PersonSelector = (props) => {
const { onChange, schema, addons } = props
const { presetValue, interactiveType } = schema
useEffect(() => {
if (addons) {
addons.setValue(addons.dataPath, presetValue)
} else {
onChange(presetValue)
}
}, [presetValue])
if (interactiveType === '分组模态') {
return <UserGroup {...props} />
} else if (interactiveType === '树形模态') {
......
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