import React, { useEffect, useState } from 'react'; import { Modal, Input, Row, Col, Spin, message } from 'antd'; import type { ModalProps } from 'antd'; import { request } from '@umijs/max'; interface JobTitle { id: number; label: string; children?: JobTitle[]; } export interface JobTitleSelectorProps extends Omit { open: boolean; value?: {id:number, label:string}; onOk: (job: {id:number, label:string})=>void; onCancel: ()=>void; } const JobTitleSelector: React.FC = ({ open, onOk, onCancel, value }) => { const [loading, setLoading] = useState(false); const [data, setData] = useState([]); const [search, setSearch] = useState(''); const [filtered, setFiltered] = useState([]); // 筛选后数据 const [selectedCat, setSelectedCat] = useState(null); // 左列选中一级 const [showSubId, setShowSubId] = useState(null); // 右列当前展开二级ID const [selected, setSelected] = useState<{id:number, label:string}|null>(value||null); useEffect(()=>{ if(open){ setLoading(true); request('/api/app/common/jobTitle/treeselect').then(res=>{ setData(res.data||[]); setFiltered(res.data||[]); setSelectedCat(null); setShowSubId(null); setSelected(value||null); setSearch(''); }).catch(()=>message.error('加载岗位数据失败')).finally(()=>setLoading(false)); } },[open]); // 搜索时过滤全部三级,依然保持原树结构 useEffect(()=>{ if(search&&search.length>0){ // 返回新的树,只在三级岗位匹配关键词的二/一级保留 function filterTree(nodes:JobTitle[]):JobTitle[]{ return nodes.map(cat=>{ // cat: 一级 if(!cat.children)return null; const subFiltered=cat.children.map(sub=>{ if(!sub.children)return null; const jobs=sub.children.filter(j=>j.label.includes(search)); if(jobs.length>0){ return {...sub,children:jobs}; } return null; }).filter(Boolean) as JobTitle[]; if(subFiltered.length>0)return {...cat,children:subFiltered}; return null; }).filter(Boolean) as JobTitle[]; } setFiltered(filterTree(data)); setSelectedCat(null); setShowSubId(null); }else{ setFiltered(data); } },[search,data]); // 左列,一级点击切换 const handleCat = (cat:JobTitle) => { setSelectedCat(cat); setShowSubId(null); }; // 右列,点二级分类 const handleSub = (sub:JobTitle) => { setShowSubId(sub.id===showSubId?null:sub.id); }; // 右列,选三级岗位 const handleJob = (job:JobTitle) => { setSelected({id:job.id,label:job.label}); }; const handleOk = () => { if(selected){ onOk(selected); } else { message.warning('请选择岗位'); } }; // 获取当前分类下所有二级 const curSubs = selectedCat?.children || []; // 搜索时过滤所有二级岗位的分组,全局(不再依赖selectedCat) const getGlobalSearchGroups = ()=>{ if (!search) return []; const groups: {cat:JobTitle, sub: JobTitle, jobs: JobTitle[]}[] = []; data.forEach(cat=>{ cat.children?.forEach(sub=>{ if(sub.children){ const jobs=sub.children.filter(j=>j.label.includes(search)); if(jobs.length>0)groups.push({cat,sub,jobs}); } }); }); return groups; }; return ( setSearch(e.target.value)} style={{marginBottom:10,width:280}} />
{/* 左侧一级分类 */}
{filtered.map(cat=>(
handleCat(cat)} >{cat.label}
))}
{/* 右侧内容区优化 */}
{(search) ? ( (()=>{ const groups = getGlobalSearchGroups(); return groups.length===0?
无相关岗位
: groups.map(({cat,sub,jobs})=>(
{cat.label} / {sub.label}
{jobs.map(job=>(
handleJob(job)} >{job.label}
))}
)); })() ) : ( !selectedCat?
请先选择左侧所属行业类别
:
{curSubs.length===0?
暂无子分类
:
{curSubs.map(sub=>(
sub.children&&handleSub(sub)} > {sub.label} {sub.children && ( {showSubId===sub.id?'-':'+'} )}
{/* 只在当前展开的二级下 横向显示三级 */} {showSubId===sub.id&&sub.children&&(
{sub.children.map(job=>(
handleJob(job)} >{job.label}
))}
)}
))}
}
)}
); }; export default JobTitleSelector;