提交 e28fea6f authored 作者: 钟是志's avatar 钟是志

28974 辅导员考核相关需求,有疑问联系我

上级 df7cd9cf
/**
* 钟是志
* 2022年10月12日
* 禅道 http://scjoyedu.eicp.net:88/zentao/bug-view-28974.html
* 选辅导员,教师,学生的通用组件
* api 文档 https://console-docs.apipost.cn/preview/caa25e097e7386d0/a2d8620d944c56b5
* */
import React, { useState, useEffect } from 'react';
import styles from './styles/styles.less';
import { Modal, Button, Input, Checkbox, message, Icon, Tree, Spin, Tooltip } from 'antd';
import ButtonDiy from '@/baseComponent/ButtonDiy';
import { formatTreeData, colorTranslate, getApis } from './publicFunctions';
import { getInfo as requestData } from '@/highOrderComponent/Service';
import lowCodeProps from './lowCodeProps';
export default function SelectPerson(props) {
const [show, setShow] = useState(false);
const propsDiy = window.smartFormSelectPersonComponent?.lowCodeProps || lowCodeProps();
const apis = getApis(propsDiy.searchType);
const [authInstitutionInfo, setAuthInstitutionInfo] = useState(null); // 楼栋信息
const [searchKey, setSearchKey] = useState(''); // 搜索框的内容
const [searchResult, setSearchResult] = useState([]); // 搜索到的内容
const [detailList, setDetailList] = useState([]); // 第三列显示的列表
const [sgUsers, setSelectUsers] = useState([]); // 选中的item
const [sgUserIds, setSgUserIds] = useState([]); // 选中的businessKey
const [checkedList, setCheckedList] = useState([]); // 树节点中选中的复选框
const [jqpp, setJqpp] = useState(false); // 是否精确匹配
function changeShow() {
setShow(!show);
setCheckedList([]);
setSgUserIds([]);
// setSelectUsers([]);
setSearchKey('');
setSearchResult([]);
setDetailList([]);
}
useEffect(() => {
window.smartFormSelectPersonComponent = {
changeShow,
setSelectUsers,
lowCodeProps: lowCodeProps(),
callback: (selectUsers) => {
console.log(selectUsers);
},
};
}, []);
// 第二栏树形数据
const getTreeList = () => {
requestData({}, apis.findTree).then(res => {
if (res) {
res = formatTreeData(res);
setAuthInstitutionInfo(res);
}
});
};
//根据关键字搜索
const search = () => {
if (searchKey === '') {
setSearchResult([]);
} else {
if(searchKey.length < 2){
message.warning('请至少输入2个字符');
return false;
}
requestData(
{
keyword: searchKey,
isExact: jqpp,
},
apis.search,
).then(res => {
if (res) {
setSearchResult(res);
}
});
}
};
//清空搜索条件
const clear = () => {
setSearchKey('');
setSearchResult([]);
};
//根据id进行搜索
const searchById = (selectedKeys, e) => {
const { businessKey, selectType } = e.node.props;
let bKey = businessKey;
requestData(
{
businessKey: bKey,
selectType,
},
apis.findList,
).then(res => {
if (res) {
setDetailList(res);
}
});
};
//选中的人
const selectUser = user => {
setSelectUsers([...sgUsers, user]);
setSgUserIds([...sgUserIds, user.businessKey]);
};
//删除选中的人
const deleteSg = (x, index, e) => {
// 阻止事件冒泡
e.stopPropagation();
console.log(sgUsers);
let sgNew = [...sgUsers];
console.log(x);
debugger;
sgNew = sgNew.filter(g => {
return x.businessKey !== g.businessKey;
});
setSelectUsers(sgNew);
setSgUserIds(
sgUserIds.filter(g => {
return x.businessKey !== g;
}),
);
setCheckedList(checkedList.filter((g) => {
return x.businessKey !== g.businessKey && !g.businessKey.startsWith(x.businessKey);
}));
};
// 确认按钮
const auth = () => {
const data = {
businessKey: [...sgUserIds, ...checkedList.map(g => g.businessKey)],
};
if (!data.businessKey.length) {
message.warning(propsDiy.getResultProps.emptySelectMessage);
return false;
}
message.info(propsDiy.getResultProps.message);
requestData(data, apis.getData).then(res => {
if (res) {
message.success('操作成功');
if(window.smartFormSelectPersonComponent.callback){
window.smartFormSelectPersonComponent.callback(res);
}
changeShow();
// props.getData();
}
});
};
const changeJqpp = e => {
setJqpp(e.target.checked);
};
useEffect(() => {
if (show) {
getTreeList();
}
}, [show]);
const changeTreeCheck = (checkedKeys, e) => {
const keys = e.checkedNodes.map(g => {
const {
businessKey,
businessMemo,
businessName,
noCheckNum,
preCheckInNum,
selectType,
level,
bedNum,
isSelect,
checkInNum,
womanNoCheckNum,
manNoCheckNum,
} = g.props;
return {
womanNoCheckNum,
manNoCheckNum,
businessKey,
businessMemo,
businessName,
noCheckNum,
preCheckInNum,
selectType,
level,
bedNum,
isSelect,
checkInNum,
};
});
setCheckedList(keys);
};
const distinctArr = () => {
let arr = checkedList.concat(sgUsers);
let map = new Map();
for (let item of arr) {
map.set(item.businessKey, item);
}
arr = [...map.values()];
arr.sort((a, b) => { // 排序解决 多层子级的问题。
if(a.businessKey && b.businessKey){
return a.businessKey.length - b.businessKey.length;
}
return 0;
});
const distnctBusinessKey = arr.reduce(function(response, current, index) {
// 删除子级 key 保证数据唯一性
let add = true;
for (let item of response) {
if (current.businessKey.startsWith(item.businessKey)) {
add = false;
}
}
if (add) {
response.push(current);
return response;
}
return response;
}, []);
return distnctBusinessKey;
};
const distinctA = distinctArr();
return (
<>
{show && (
<Modal
className={styles.distribution}
visible={true}
width={1300}
onOk={auth}
maskClosable={false}
onCancel={changeShow}
{...propsDiy.ModalProps}
>
<div className={styles.modalContent}>
<div className={styles.one} style={{ border: 'none' }}>
<div>
<Input
{...propsDiy.firstSearchProps.inputProps}
value={searchKey}
onChange={e => setSearchKey(e.target.value)}
/>
<div className={styles.options}>
<Button className={styles.search} onClick={search}>
搜索
</Button>
<Button className={styles.clear} onClick={clear}>
清空
</Button>
</div>
<div>
<div className={styles.search_option}>搜索选项</div>
<Checkbox onChange={changeJqpp} checked={jqpp}>
精确匹配
</Checkbox>
</div>
<div className={styles.result}>
<div>{propsDiy.firstSearchProps.searchResultTitle}</div>
<div className={styles.search}>
{searchResult.length > 0 ? (
<div className={styles.search_result}>
{searchResult
?.filter(g => {
return g.isSelect;
})
.map(x => {
return (
<div
key={x.businessKey}
onClick={
sgUserIds.includes(x.businessKey) || !x.isSelect
? null
: () => selectUser(x)
}
>
<span style={{ color: sgUserIds.includes(x.businessKey) && 'red' }}>
{x.businessName}
</span>
</div>
);
})}
</div>
) : (
<div className={styles.search_no_result}>无搜索结果</div>
)}
</div>
</div>
</div>
</div>
<div className={styles.one}>
<div className={styles.one_title}>{propsDiy.secondTreeProps.title}</div>
{authInstitutionInfo && Array.isArray(authInstitutionInfo) ? (
<Tree
treeData={authInstitutionInfo}
checkable={true}
onSelect={searchById}
className={styles.treeDiv}
defaultExpandedKeys={['0000']}
checkedKeys={checkedList.map(g => g.businessKey)}
onCheck={changeTreeCheck}
/>
) : (
<div className={styles.no_result}>
<Spin spinning={true} tip={propsDiy.secondTreeProps.loadingTreeDataMessage} size="large" />
</div>
)}
</div>
<div className={styles.one}>
<div className={styles.one_title}>
{propsDiy.thirdDetailListProps.title}
</div>
<div className={styles.list_content}>
{detailList.length > 0 ? (
<div className={styles.search_result}>
{detailList?.filter(g => {
return g.isSelect;
}).map(x => {
return (
<div
key={x.businessKey}
onClick={sgUserIds.includes(x.businessKey) ? null : () => selectUser(x)}
>
<span
style={
!x.isSelect
? {
cursor: 'not-allowed',
fontWeight: 'normal',
}
: {
color: sgUserIds.includes(x.businessKey) && 'red',
}
}
>
{x.businessName}
</span>
</div>
);
})}
</div>
) : (
<div className={styles.no_result}>{propsDiy.thirdDetailListProps.emptyMessage}</div>
)}
</div>
</div>
<div className={styles.one}>
<div className={styles.one_title}>{propsDiy.fourRangeProps.title}</div>
<div className={styles.list_content}>
{distinctA.length ? (
<div className={styles.search_result}>
{distinctA.map((x, index) => {
return (
<div
key={x.businessKey}
className={styles.selectSg}
style={{
backgroundColor: colorTranslate(x),
}}
>
<div className={styles.oneSelectedInfo}>
<Icon
type="delete"
style={{ marginRight: '5px' }}
onClick={e => deleteSg(x, index, e)}
/>
<Tooltip title={x.businessName}>
{x.businessName}
</Tooltip>
</div>
</div>
);
})}
</div>
) : (
<div className={styles.no_result}>{propsDiy.fourRangeProps.emptyMessage}</div>
)}
</div>
</div>
</div>
</Modal>
)}
</>
);
}
export default function lowCodeProps(info) {
return {
searchType: 'instructorSearch', // teacherSearch || studentSearch || instructorSearch
ModalProps: { // 弹窗的属性
title: '选择辅导员',
},
firstSearchProps: { // 最左侧搜索栏的属性
inputProps: {
placeholder: '输入辅导员姓名/工号搜索',
},
searchResultTitle: '搜索结果',
},
secondTreeProps: { // 树形
title: '部门',
loadingTreeDataMessage: '正在加载数据',
},
thirdDetailListProps: { // 第三栏
title: '详细辅导员列表',
emptyMessage: '暂无详细辅导员列表数据',
},
fourRangeProps: { // 第四栏
title: '所选择的辅导员范围',
emptyMessage: '暂无选中的辅导员',
},
getResultProps: {
emptySelectMessage: '请至少选择一个辅导员',
message: '正在查询中,请耐心等待',
},
};
}
/**
* 使用方法
return {
before: [
{
children: "选择辅导员", type: "primary", onClick: () => {
if (window.smartFormSelectPersonComponent) {
// window.smartFormSelectPersonComponent.lowCodeProps =
// {
// searchType: 'instructorSearch', // teacherSearch || studentSearch || instructorSearch
// ModalProps: { // 弹窗的属性
// title: '选择辅导员',
// },
// firstSearchProps: { // 最左侧搜索栏的属性
// inputProps: {
// placeholder: '输入辅导员姓名/工号搜索',
// },
// searchResultTitle: '搜索结果',
// },
// secondTreeProps: { // 树形
// title: '部门',
// loadingTreeDataMessage: '正在加载数据',
// },
// thirdDetailListProps: { // 第三栏
// title: '详细辅导员列表',
// emptyMessage: '暂无详细辅导员列表数据',
// },
// fourRangeProps: { // 第四栏
// title: '所选择的辅导员范围',
// emptyMessage: '暂无选中的辅导员',
// },
// getResultProps: {
// emptySelectMessage: '请至少选择一个辅导员',
// message: '正在查询中,请耐心等待',
// },
// };
window.smartFormSelectPersonComponent.setSelectUsers([{ // 设置已经选中的用户
businessKey: "71-1300",
businessName: '钟是志',
isSelect: true,
}]);
window.smartFormSelectPersonComponent.callback = (selectUsers) => { // 回调函数
console.log(selectUsers);
};
window.smartFormSelectPersonComponent.changeShow(); // 打开弹窗
}
}
},
]
}
** 使用方法
* */
import styles from './styles/styles.less';
import { Tooltip } from 'antd';
import React from 'react';
const formatTreeData = (treeData = [], res = []) => {
for (let item of treeData) {
item.title = (
<>
<Tooltip title={item.businessMemo}>
<span>{item.businessName}</span>
</Tooltip>
</>
);
item.key = item.businessKey || '0000';
item.checkable = true;
item.selectable = true;
if (!item.isSelect) {
item.selectable = false;
}
// if (!item.isSelect) {
// item.checkable = false;
// item.disabled = true;
// } else {
// item.checkable = true;
// }
// item.selectable = item.selectType === 'floor';
if (item.children && item.children.length) {
item.children = formatTreeData(item.children, []);
} else {
item.isLeaf = true;
}
}
return treeData;
};
const colorTranslate = (item) => {
const colors = {
1: '#6164C1',
2: 'rgb(202, 198, 46)',
3: '#BE0AC1',
};
if (item && item.businessKey) {
return colors[item.businessKey.split('-').length];
}
return colors[item.level] || colors['2'];
};
export function getApis(searchType) {
const apiUrls = {
// https://console-docs.apipost.cn/preview/caa25e097e7386d0/a2d8620d944c56b5?target_id=fe79cb0e-f0db-49ec-bed9-92f4a830bf75
instructorSearch: {
// 查询辅导员
search: '/instructorSearch/search',
findTree: '/instructorSearch/findTree',
findList: '/instructorSearch/findList',
getData: '/instructorSearch/getData',
getDataCacheKey: '/instructorSearch/getDataCacheKey',
readCacheData: '/instructorSearch/readCacheData',
},
teacherSearch: {
// 查询教师
search: '/teacherSearch/search',
findTree: '/teacherSearch/findTree',
findList: '/teacherSearch/findList',
getData: '/teacherSearch/getData',
getDataCacheKey: '/teacherSearch/getDataCacheKey',
readCacheData: '/teacherSearch/readCacheData',
},
studentSearch: {
// 查询学生
search: '/studentSearch/search',
findTree: '/studentSearch/findTree',
findList: '/studentSearch/findList',
getData: '/studentSearch/getData',
getDataCacheKey: '/studentSearch/getDataCacheKey',
readCacheData: '/studentSearch/readCacheData',
},
};
return apiUrls[searchType] || apiUrls.studentSearch;
}
export { formatTreeData, colorTranslate };
@color1: #d43d52;
@color2: #2196F3;
.basicTitle{
background: #fff;
padding: 5px;
}
.man{
color: @color2;
}
.woman{
color: @color1;
}
.bg-green{
background: #4daf61;
padding: 5px 10px;
color: white;
}
@import "./basicTitle.less";
.btn-warning {
color: white;
background-color: #F2B776;
border-color: #F2B776;
}
.btn-success {
color: white;
background-color: #6FC080;
border-color: #6FC080;
margin-right: 3px;
}
.modalTitle {
text-align: center;
}
.numbers {
display: grid;
grid-template-columns: repeat(3, 300px);
margin: 0 auto;
justify-items: center;
align-items: center;
width: 300px;
padding: 10px;
div {
span {
color: red;
}
}
}
.modalContent {
display: grid;
grid-template-columns: 3fr 3fr 3fr 2fr;
column-gap: 10px;
height: 60vh;
.one {
border: 1px solid #e4e4e4;
overflow-y: auto;
.options {
display: flex;
justify-content: space-between;
margin: 16px 0;
.search {
flex: 1;
color: #fff;
background: #6164C1;
border-radius: 5px;
margin-right: 10px;
}
.clear {
flex: 1;
color: #fff;
background: rgb(163, 47, 47);
border-radius: 5px;
}
}
.search_option {
margin-bottom: 6px;
}
.result {
margin-top: 20px;
.search {
border: 1px solid #e4e4e4;
height: auto;
min-height: ~'calc(60vh - 185px)';
overflow-y: auto;
cursor: pointer;
.search_no_result {
height: 100%;
display: flex;
align-items: center;
justify-content: center;
font-size: 20px;
color: #c3c3c3;
}
}
}
.college_name {
height: 30px;
line-height: 30px;
padding-left: 20px;
cursor: pointer;
}
.search_result {
> div {
height: 32px;
padding: 0 16px;
display: flex;
justify-content: space-between;
align-items: center;
font-weight: 900;
& span:last-child {
background-color: #6164C1;
padding: 0 5px;
color: #fff;
border-radius: 20px;
font-weight: 100;
}
}
.selectSg {
width: 96%;
height: 30px;
margin: 10px auto;
line-height: 30px;
padding-left: 10px;
background-color: rgb(202, 198, 46);
color: #fff;
}
}
.search_result_list {
height: 32px;
padding: 0 16px;
line-height: 32px;
font-weight: 900;
.dormCode {
margin-left: 24px;
}
& span:last-child {
background-color: #6164C1;
padding: 0 5px;
color: #fff;
border-radius: 20px;
}
}
.one_title {
height: 30px;
line-height: 30px;
background-color: #F5F7FA;
padding-left: 10px;
border-bottom: 1px solid #e4e4e4;
}
.list_content {
height: 56vh;
overflow-y: auto;
cursor: pointer;
}
.no_result {
display: flex;
align-items: center;
justify-content: center;
font-size: 20px;
color: #c3c3c3;
// height: calc(60vh - 32px);
height: 56vh;
}
}
}
.distribution {
:global {
.ant-btn-round {
border-radius: 0;
border: none;
background-color: grey;
color: #fff;
}
.ant-btn-primary {
background-color: skyblue !important;
}
}
}
@color1: #d43d52;
@color2: #2196F3;
.man {
color: @color2;
}
.woman {
color: @color1;
}
.treeDiv {
:global {
.ant-tree-node-content-wrapper {
width: 85%;
}
}
}
.bgPurple {
background-color: #6164C1;
padding: 0 5px;
color: #fff;
border-radius: 20px;
font-weight: 100;
}
.oneSelectedInfo {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
......@@ -3,6 +3,7 @@ import ZdyTable from '@/webPublic/one_stop_public/Table';
import styles from './index.less';
import { fetchTemplateByCode, fetchTableItem } from '@/webPublic/Services';
import { isJSON } from '@/webPublic/zyd_public/utils/utils';
import SelectPerson from '@/webPublic/FormInsertDiy/ExportComponent/SelectPerson/Index';
export default function RenderForm({
get = 'web',
......@@ -44,6 +45,7 @@ export default function RenderForm({
init={undefined}
{...content}
/>
<SelectPerson />
</div>
);
}
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论