Commit 12e97a4a by yuananting

feat:指派对象弹窗搜索接口联调

parent 0366c5b3
...@@ -2,13 +2,13 @@ ...@@ -2,13 +2,13 @@
* @Author: yuananting * @Author: yuananting
* @Date: 2021-08-05 17:09:36 * @Date: 2021-08-05 17:09:36
* @LastEditors: yuananting * @LastEditors: yuananting
* @LastEditTime: 2021-08-13 19:18:54 * @LastEditTime: 2021-08-16 14:47:51
* @Description: 新建培训任务-选择指派对象 * @Description: 新建培训任务-选择指派对象
* @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
* @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有 * @@Copyrigh: © 2020 杭州杰竞科技有限公司 版权所有
*/ */
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect, useRef } from 'react';
import { Modal, Tree, Tooltip, AutoComplete, Tabs } from 'antd'; import { Modal, Tree, Tooltip, AutoComplete, Tabs, Input, Checkbox } from 'antd';
import User from '@/common/js/user'; import User from '@/common/js/user';
import { DepType } from '@/domains/store-domain/constants'; import { DepType } from '@/domains/store-domain/constants';
import StoreService from '@/domains/store-domain/storeService'; import StoreService from '@/domains/store-domain/storeService';
...@@ -17,22 +17,38 @@ import './ChooseAssignorModal.less'; ...@@ -17,22 +17,38 @@ import './ChooseAssignorModal.less';
const { TabPane } = Tabs; const { TabPane } = Tabs;
const { DirectoryTree } = Tree; const { DirectoryTree } = Tree;
const { Search } = Input;
function ChooseAssignorModal(props) { function ChooseAssignorModal(props) {
const AssignTypeEnum = {
departMentTab: 'SECTION',
postGrouptab: 'POST',
customGroupTab: 'CUSTOM',
};
const [structureData, setStructureData] = useState([]); const [structureData, setStructureData] = useState([]);
const [activeKey, setActiveKey] = useState('departMentTab'); const [activeKey, setActiveKey] = useState('departMentTab');
const [checkedAssignorList, setCheckedAssignorList] = useState(props.currentAssignorList || []); // 勾选的指派对象 const [checkedAssignorList, setCheckedAssignorList] = useState(props.currentAssignorList || []); // 勾选的指派对象
const [checkedAssignorKeys, setCheckedAssignorKeys] = useState(props.currentAssignorList.map((item) => item.checkedId) || []); const [checkedAssignorKeys, setCheckedAssignorKeys] = useState(props.currentAssignorList.map((item) => item.checkedId) || []);
const [completeOptions, setCompleteOption] = useState([]); const [completeOptions, setCompleteOption] = useState([]);
const [searchKey, setSearchKey] = useState('');
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const [queryName, setQueryName] = useState(''); // 搜索框内的值
const queryNameRef = useRef(null);
const timer = useRef(null);
useEffect(() => {
queryNameRef.current = queryName;
setOpen(!!queryName);
clearTimeout(timer.current);
timer.current = setTimeout(() => {
if (!!queryName) return getCompleteOptionData(queryNameRef.current);
setCompleteOption([]);
}, 500);
}, [queryName]);
const AssignTypeEnum = {
departMentTab: 'SECTION',
postGrouptab: 'POST',
customGroupTab: 'CUSTOM',
};
useEffect(() => { useEffect(() => {
setQueryName(''); // 切换tab时搜索置空
setCompleteOption([]);
setStructureData([]);
getStructureData(); getStructureData();
}, [activeKey]); }, [activeKey]);
...@@ -40,7 +56,7 @@ function ChooseAssignorModal(props) { ...@@ -40,7 +56,7 @@ function ChooseAssignorModal(props) {
const params = { const params = {
depType: DepType[activeKey], depType: DepType[activeKey],
enterpriseId: User.getEnterpriseId(), enterpriseId: User.getEnterpriseId(),
source: 0, //0代表来自企培 source: 0, // 0代表来自企培
storeId: User.getStoreId(), storeId: User.getStoreId(),
userId: User.getUserId(), userId: User.getUserId(),
whetherCount: false, whetherCount: false,
...@@ -117,43 +133,52 @@ function ChooseAssignorModal(props) { ...@@ -117,43 +133,52 @@ function ChooseAssignorModal(props) {
} }
function renderTitle(title) { function renderTitle(title) {
return <span>{title}</span>; return <span className='catalog-title'>{title}</span>;
} }
function renderItem(record, type) { function renderItem(record, type) {
return { return {
value: record.userName || record.name, value: record.userName || record.name,
label: ( label: (
<div <Checkbox>
style={{ <div
display: 'flex', className='search-result-item'
justifyContent: 'space-between', style={{
}} display: 'flex',
depId={record.id} justifyContent: 'space-between',
type={type}> }}
{type === 'user' ? ( depId={record.id}
<div> type={type}>
<WWOpenDataCom type='userName' openid={record.userName} /> {type === 'user' ? (
</div> <div className='search-result-item__left'>
) : ( <WWOpenDataCom type='userName' openid={record.userName} />
<div> </div>
<WWOpenDataCom type='departmentName' openid={record.name} /> ) : (
</div> <div className='search-result-item__left'>
)} {activeKey === 'departMentTab' ? <WWOpenDataCom type='departmentName' openid={record.name} /> : <span>{record.name}</span>}
{type === 'user' && </div>
record.postDepNamesList.map((item, index) => { )}
return ( {type === 'user' && (
<span> <div className='search-result-item__right'>
<WWOpenDataCom type='departmentName' openid={item} /> <Tooltip title={<div>{handleDepName(record.depNamesList)}</div>} placement='top' arrowPointAtCenter>
</span> {record.depNamesList.map((item, index) => {
); return (
})} <span>
{type === 'post' && ( <WWOpenDataCom type='departmentName' openid={item} />
<span type='post' openid={record.parentName}> {index < record.depNamesList.length - 1 ? ';' : ''}
{record.parentName} </span>
</span> );
)} })}
</div> </Tooltip>
</div>
)}
{type === 'post' && (
<span type='post' openid={record.parentName}>
{record.parentName}
</span>
)}
</div>
</Checkbox>
), ),
}; };
} }
...@@ -161,7 +186,7 @@ function ChooseAssignorModal(props) { ...@@ -161,7 +186,7 @@ function ChooseAssignorModal(props) {
function getCompleteOptionData(value) { function getCompleteOptionData(value) {
setCompleteOption([]); setCompleteOption([]);
const params = { const params = {
depType: DepType[props.treeType], depType: DepType[activeKey],
queryName: value, queryName: value,
enterpriseId: User.getEnterpriseId(), enterpriseId: User.getEnterpriseId(),
source: 0, //0代表来自企培 source: 0, //0代表来自企培
...@@ -185,7 +210,7 @@ function ChooseAssignorModal(props) { ...@@ -185,7 +210,7 @@ function ChooseAssignorModal(props) {
}); });
} }
if (departmentVOList.length > 0) { if (departmentVOList.length > 0) {
switch (props.treeType) { switch (activeKey) {
case 'departMentTab': case 'departMentTab':
departmentGroupObj.label = renderTitle('部门'); departmentGroupObj.label = renderTitle('部门');
break; break;
...@@ -203,7 +228,7 @@ function ChooseAssignorModal(props) { ...@@ -203,7 +228,7 @@ function ChooseAssignorModal(props) {
}); });
} }
if (subLevelDepartmentVOList.length > 0) { if (subLevelDepartmentVOList.length > 0) {
switch (props.treeType) { switch (activeKey) {
case 'postGrouptab': case 'postGrouptab':
postobj.label = renderTitle('岗位'); postobj.label = renderTitle('岗位');
break; break;
...@@ -220,27 +245,51 @@ function ChooseAssignorModal(props) { ...@@ -220,27 +245,51 @@ function ChooseAssignorModal(props) {
if (Object.keys(userObj).length !== 0) { if (Object.keys(userObj).length !== 0) {
_completeOptions.push(userObj); _completeOptions.push(userObj);
} }
if (Object.keys(departmentGroupObj).length !== 0) {
_completeOptions.push(departmentGroupObj);
}
if (Object.keys(postobj).length !== 0) { if (Object.keys(postobj).length !== 0) {
_completeOptions.push(postobj); _completeOptions.push(postobj);
} }
if (Object.keys(departmentGroupObj).length !== 0) {
_completeOptions.push(departmentGroupObj);
}
setCompleteOption(_completeOptions); setCompleteOption(_completeOptions);
}); });
} }
// 搜索空状态渲染;
function notFoundContentNode() {
return (
<div className='empty-con'>
<img src='https://image.xiaomaiketang.com/xm/wRDrb2pJFb.png' className='empty-img' />
<div className='empty-text'>暂无数据</div>
</div>
);
}
function confirmSearchSelect(value, option) {
const param = {};
setOpen(false);
setQueryName(value);
if (option.label.props.type === 'user') {
param.queryName = value;
} else {
param.id = option.label.props.depId;
}
props.searchUserList(param, activeKey, 1);
}
// 弱提示渲染
function handlePlaceHolder() { function handlePlaceHolder() {
let placeholder = ''; let placeholder = '';
switch (props.treeType) { switch (activeKey) {
case 'departMentTab': case 'departMentTab':
placeholder = '搜索学员姓名、部门'; placeholder = '搜索学员、部门';
break; break;
case 'postGrouptab': case 'postGrouptab':
placeholder = '搜索学员姓名/岗位/岗位组'; placeholder = '搜索学员、岗位、岗位组';
break; break;
case 'customGroupTab': case 'customGroupTab':
placeholder = '搜索学员姓名/自定义分组集合/自定义分组'; placeholder = '搜索学员、分组、分组集合';
break; break;
default: default:
break; break;
...@@ -248,6 +297,17 @@ function ChooseAssignorModal(props) { ...@@ -248,6 +297,17 @@ function ChooseAssignorModal(props) {
return placeholder; return placeholder;
} }
function handleDepName(depArray) {
const depArrayDom = depArray.map((item, index) => {
return (
<span>
<WWOpenDataCom type='departmentName' openid={item} />
</span>
);
});
return depArrayDom;
}
return ( return (
<Modal <Modal
className='choose-assignor-modal' className='choose-assignor-modal'
...@@ -261,16 +321,13 @@ function ChooseAssignorModal(props) { ...@@ -261,16 +321,13 @@ function ChooseAssignorModal(props) {
maskClosable={false}> maskClosable={false}>
<div className='assignor-container'> <div className='assignor-container'>
<div className='left-list'> <div className='left-list'>
{/* <AutoComplete <AutoComplete
dropdownClassName='certain-category-search-dropdown' dropdownClassName='left-search-dropdown'
dropdownMatchSelectWidth={272} dropdownMatchSelectWidth={272}
allowClear allowClear
onChange={(value) => setSearchKey(value)} onChange={(value) => setQueryName(value)}
onSearch={(value) => { notFoundContent={notFoundContentNode()}
getCompleteOptionData(value); value={queryName}
}}
// notFoundContent={notFoundContentNode()}
value={searchKey}
open={open} open={open}
onFocus={() => { onFocus={() => {
setOpen(true); setOpen(true);
...@@ -283,7 +340,9 @@ function ChooseAssignorModal(props) { ...@@ -283,7 +340,9 @@ function ChooseAssignorModal(props) {
}} }}
options={completeOptions} options={completeOptions}
// onSelect={confirmSearchSelect} // onSelect={confirmSearchSelect}
placeholder={handlePlaceHolder()}></AutoComplete> */} placeholder={handlePlaceHolder()}>
<Search style={{ width: 272 }} enterButton={<span className='icon iconfont'>&#xe832;</span>} />
</AutoComplete>
<div className='data-body'> <div className='data-body'>
<Tabs size={'small'} onChange={(key) => setActiveKey(key)}> <Tabs size={'small'} onChange={(key) => setActiveKey(key)}>
<TabPane key='departMentTab' tab='部门'></TabPane> <TabPane key='departMentTab' tab='部门'></TabPane>
......
...@@ -5,8 +5,12 @@ ...@@ -5,8 +5,12 @@
.left-list { .left-list {
width: 50%; width: 50%;
margin-right: 24px; margin-right: 24px;
padding: 0 0 12px 16px; padding: 12px 0 12px 16px;
border: 1px solid #e8e8e8; border: 1px solid #e8e8e8;
.ant-select-auto-complete .ant-select-clear {
font-size: 14px;
right: 15px;
}
.data-body { .data-body {
.ant-tabs-nav { .ant-tabs-nav {
margin: 0 !important; margin: 0 !important;
...@@ -18,7 +22,7 @@ ...@@ -18,7 +22,7 @@
.tree-con { .tree-con {
overflow-y: scroll; overflow-y: scroll;
overflow-x: hidden; overflow-x: hidden;
max-height: 367px; max-height: 323px;
padding-right: 16px; padding-right: 16px;
.ant-tree .ant-tree-treenode { .ant-tree .ant-tree-treenode {
padding: 12px 0 !important; padding: 12px 0 !important;
...@@ -102,3 +106,51 @@ ...@@ -102,3 +106,51 @@
} }
} }
} }
.left-search-dropdown {
.catalog-title {
font-size: 14px;
color: #666;
margin-bottom: 14px;
}
.search-result-item {
padding: 14px 0;
color: #333;
.title-icon {
color: #999;
margin-right: 3px;
}
.search-result-item__left {
font-size: 14px;
}
.search-result-item__right {
font-size: 14px;
width: 84px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
color: #999;
text-align: right;
}
}
.ant-select-dropdown-menu-item-group-title {
color: #666;
font-weight: bold;
}
.ant-select-item-option-grouped {
padding-left: 12px;
}
.ant-select-item-option-content {
padding-left: 24px;
}
.empty-con {
text-align: center;
.empty-img {
width: 150px;
height: 150px;
}
.empty-text {
color: #666;
}
}
}
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