@@ -24,10 +24,16 @@ export default [ | |||
access: 'talenthome' | |||
}, | |||
{ | |||
name: '搜索·职位·企业', | |||
path: '/talent/search', | |||
component: './Talent/Search', | |||
access: 'talentsearch' | |||
name: '搜索·职位', | |||
path: '/talent/search/job', | |||
component: './Talent/Search/Job', | |||
access: 'talentsearchjob' | |||
}, | |||
{ | |||
name: '搜索·企业', | |||
path: '/talent/search/company', | |||
component: './Talent/Search/Company', | |||
access: 'talentsearchcompany' | |||
}, | |||
{ | |||
name: '招聘会', |
@@ -8,6 +8,6 @@ | |||
</head> | |||
<body> | |||
<div id="root"></div> | |||
<script src="/umi.ebceb906.js"></script> | |||
<script src="/umi.85104365.js"></script> | |||
</body> | |||
</html> |
@@ -33,7 +33,8 @@ export default () => { | |||
permissions = { | |||
talent: true, | |||
talenthome: true, | |||
talentsearch: true, | |||
talentsearchjob: true, | |||
talentsearchcompany: true, | |||
talentfair: true, | |||
talentinformation: true, | |||
talentdownload: true, |
@@ -0,0 +1,133 @@ | |||
import { useState, useEffect, useRef } from 'react'; | |||
import { Link } from '@umijs/max'; | |||
import { ProList, ProConfigProvider, ProFormCaptcha, ProFormCheckbox, ProFormText, setAlpha, ProForm, ProFormDependency } from '@ant-design/pro-components'; | |||
import { PhoneOutlined, MailOutlined, EnvironmentOutlined, ArrowRightOutlined, FireOutlined, StarOutlined, PayCircleOutlined } from '@ant-design/icons'; | |||
import { Space, Tabs, Avatar, Row, Col, Image, message, Card, ConfigProvider, Affix, Tag, Tooltip, Pagination, Flex, Descriptions, Button, Divider } from 'antd'; | |||
import { Imageprefix } from '@/constants/index' | |||
import { PostCompanySearch } from '@/services/apis/company'; | |||
import { GetAdvertscheduleList } from '@/services/apis/advertschedule'; | |||
import EmptyResult from '@/components/Common/EmptyResult' | |||
import CommonJob from '@/components/Common/Job' | |||
interface SearchJobProps { | |||
getTotal: (value: number) => void, | |||
searchParams: any, | |||
} | |||
const SearchJob: React.FC<SearchJobProps> = ({ searchParams, getTotal }: any) => { | |||
const [list, setList] = useState<object[]>([]) | |||
const [advertscheduleList, setAdvertscheduleList] = useState<object[]>([]) | |||
useEffect(() => { | |||
GetAdvertscheduleList({ page: 1, pagesize: 4, code: 'wzsylbt' }).then(res => { | |||
setAdvertscheduleList(res.data.advertschedules) | |||
}) | |||
}, []); | |||
useEffect(() => { | |||
PostCompanySearch(searchParams).then(res => { | |||
setList(res.data.jobs) | |||
getTotal(res.data.total) | |||
}) | |||
}, [searchParams]); | |||
return ( | |||
<> | |||
<ConfigProvider theme={{ | |||
token: { | |||
colorPrimary: '#19be6e', | |||
}, components: { | |||
List: { | |||
headerBg: '#ffffff', | |||
} | |||
}, | |||
}}> | |||
<Row gutter={[16, 16]}> | |||
<Col span={18}> | |||
{ | |||
list.length > 0 && list.map((item: any, index: number) => ( | |||
<> | |||
<CommonJob item={item}></CommonJob> | |||
</> | |||
)) | |||
} | |||
{ | |||
!list || list.length == 0 && <EmptyResult description="没有找到符合条件的职位" /> | |||
} | |||
</Col> | |||
<Col span={6}> | |||
{ | |||
advertscheduleList && advertscheduleList.length && advertscheduleList.map((item, index) => ( | |||
<div style={{ borderRadius: 8, marginBottom: 20 }}> | |||
<div style={{ | |||
width: '100%', | |||
position: 'relative', | |||
paddingTop: '56.25%', /* 16:9 的比例 */ | |||
overflow: 'hidden' | |||
}}> | |||
<Link to={{ pathname: item.target_url }} target='_blank'> | |||
<img src={Imageprefix + item.image_url} style={{ | |||
position: 'absolute', | |||
top: 0, | |||
left: 0, | |||
width: '100%', | |||
height: '100%', | |||
borderRadius: 8 | |||
}} /> | |||
</Link> | |||
</div> | |||
</div> | |||
)) | |||
} | |||
</Col> | |||
</Row> | |||
{/* <Flex justify='center' align='center' style={{ margin: '40px 0' }}> | |||
<Pagination | |||
hideOnSinglePage | |||
total={total} | |||
showTotal={(total) => `总共${total}条`} | |||
current={page} | |||
pageSize={pageSize} | |||
pageSizeOptions={['12', '24', '36']} | |||
onChange={(page, pageSize) => { | |||
setPage(page) | |||
setPageSize(pageSize) | |||
GetJobseekerRecommendJob({ page: page, pagesize: pageSize, sortby: 'desc' }).then((res: any) => { | |||
setList(res.data.jobs ? res.data.jobs : [{}, {}]) | |||
setTotal(res.data.total) | |||
}) | |||
}} | |||
/> | |||
</Flex> */} | |||
</ConfigProvider> | |||
</> | |||
); | |||
}; | |||
export default SearchJob; | |||
@@ -0,0 +1,590 @@ | |||
import { useState, useEffect, useRef, Children } from 'react'; | |||
import { Segmented, ConfigProvider, Flex, Space, Select, Input, Tag, Tabs, Row, Col, Descriptions, InputNumber, Cascader, Popconfirm, Button, Divider, Typography } from 'antd'; | |||
import { SearchOutlined, CloseOutlined, EnvironmentOutlined, CaretUpOutlined, MenuOutlined, DownOutlined, UpOutlined } from '@ant-design/icons'; | |||
import { LoginForm, ProFormCaptcha, ProFormText, ProFormDependency, PageContainer } from '@ant-design/pro-components'; | |||
import { useModel, useSearchParams, connect, Link } from 'umi'; | |||
const cascaderfieldNames = { label: 'name', value: 'id', children: 'children' }; | |||
interface SearchFilterProps { | |||
getSearchParams: (value: any) => void, | |||
keyword: any | |||
} | |||
const SearchFilter: React.FC<SearchFilterProps> = ({ dispatch, dictModel, getSearchParams, keyword }: any) => { | |||
const [showSearch, setShowSearch] = useState<boolean>(false); | |||
const [openMore, setOpenMore] = useState<boolean>(false); | |||
const [keywordName, setKeywordName] = useState<string>(keyword ? keyword : ''); | |||
const [searchJobParams, setSearchJobParams] = useState<object>({ | |||
keyword: keyword ? keyword : '', | |||
"location": 0, | |||
"probation": 0, | |||
"famous": 0, | |||
"industry": 0, | |||
"nature": 0, | |||
"scale": 0, | |||
"page": 1, | |||
"pagesize": 18, | |||
"sort": "id", | |||
"sortby": "desc" | |||
}); | |||
const isFirstRender = useRef(true); | |||
useEffect(() => { | |||
dispatch({ type: 'dictModel/getList', payload: { code: 2009, type: 'setAreaList' } }) | |||
dispatch({ type: 'dictModel/getList', payload: { code: "2009000100030002", type: 'setXiaolanzhenList' } }) | |||
dispatch({ type: 'dictModel/getList', payload: { code: "200900010003", type: 'setZhongshanList' } }) | |||
dispatch({ type: 'dictModel/getList', payload: { code: 2027, type: 'setIndustryPostList' } }) | |||
dispatch({ type: 'dictModel/getList', payload: { code: 2002, type: 'setNatureList' } }) | |||
dispatch({ type: 'dictModel/getList', payload: { code: 2003, type: 'setScaleList' } }) | |||
}, []) | |||
useEffect(() => { | |||
dictModel.natureList.unshift({ id: 0, name: '不限', checked: true }); | |||
}, [dictModel.natureList]) | |||
useEffect(() => { | |||
dictModel.scaleList.unshift({ id: 0, name: '不限', checked: true }); | |||
}, [dictModel.scaleList]) | |||
// 地区 | |||
const xiaolanzhenHasUnlimited = dictModel.xiaolanzhenList.some(item => item.name === '不限'); | |||
const xiaolanzhenHasXiaolan = dictModel.xiaolanzhenList.some(item => item.name === '小榄镇'); | |||
if (!xiaolanzhenHasXiaolan) { | |||
dictModel.xiaolanzhenList.unshift({ id: 100004, name: '小榄镇', checked: false }); | |||
} | |||
if (!xiaolanzhenHasUnlimited) { | |||
dictModel.xiaolanzhenList.unshift({ id: 0, name: '不限', checked: true }); | |||
} | |||
const zhongshanHasXiaolan = dictModel.zhongshanList.some(item => item.name === '中山市'); | |||
if (!zhongshanHasXiaolan) { | |||
dictModel.zhongshanList.unshift({ id: 1000037, name: '中山市', checked: false }); | |||
dictModel.zhongshanList = dictModel.zhongshanList.filter(item => item.id !== 100004); | |||
} | |||
const [areaName, setAreaName] = useState<string>(''); | |||
const [areaItem, setAreaItem] = useState(null) | |||
const cityChange = (item, idx) => { | |||
dictModel.xiaolanzhenList.forEach((i) => { | |||
i.checked = i.value === item.value; | |||
}); | |||
dictModel.zhongshanList.forEach((i) => { | |||
i.checked = i.value === item.value; | |||
}); | |||
if (item.id == 0) { | |||
dictModel.xiaolanzhenList.forEach((i) => { | |||
i.checked = i.id === item.id; | |||
}); | |||
dictModel.zhongshanList.forEach((i) => { | |||
i.checked = i.id === item.id; | |||
}); | |||
} | |||
if (item.id == 100004) { | |||
dictModel.xiaolanzhenList.forEach((i) => { | |||
i.checked = i.id === item.id; | |||
}); | |||
dictModel.zhongshanList.forEach((i) => { | |||
i.checked = i.id === item.id; | |||
}); | |||
} else { | |||
if (dictModel.xiaolanzhenList.some(i => i.id === item.id)) { | |||
dictModel.xiaolanzhenList.forEach((i) => { | |||
i.checked = i.id === item.id; | |||
}); | |||
} | |||
} | |||
if (item.id == 1000037) { | |||
dictModel.xiaolanzhenList.forEach((i) => { | |||
i.checked = i.id === item.id; | |||
}); | |||
dictModel.zhongshanList.forEach((i) => { | |||
i.checked = i.id === item.id; | |||
}); | |||
} else { | |||
if (dictModel.zhongshanList.some(i => i.id === item.id)) { | |||
dictModel.zhongshanList.forEach((i) => { | |||
i.checked = i.id === item.id; | |||
}); | |||
} | |||
} | |||
setAreaName(item.name) | |||
isFirstRender.current = false; | |||
} | |||
const searchCityChange = (item, idx) => { | |||
if (item.id == 0) { | |||
setSearchJobParams(prevState => ({ | |||
...prevState, | |||
location: 0 | |||
})); | |||
} | |||
if (item.id == 100004) { | |||
setSearchJobParams(prevState => ({ | |||
...prevState, | |||
location: item.id | |||
})); | |||
} else { | |||
if (dictModel.xiaolanzhenList.some(i => i.id === item.id)) { | |||
setSearchJobParams(prevState => ({ | |||
...prevState, | |||
location: item.id | |||
})); | |||
} | |||
} | |||
if (item.id == 1000037) { | |||
setSearchJobParams(prevState => ({ | |||
...prevState, | |||
location: item.id | |||
})); | |||
} else { | |||
if (dictModel.zhongshanList.some(i => i.id === item.id)) { | |||
setSearchJobParams(prevState => ({ | |||
...prevState, | |||
location: item.id | |||
})); | |||
} | |||
} | |||
} | |||
// 行业 | |||
const [industryTags, setIndustryTags] = useState<string[]>([]); | |||
const [industryItem, setIndustryItem] = useState<object>(null); | |||
const industryChange = (tag: object, checked: boolean) => { | |||
setIndustryItem(tag); | |||
const nextSelectedTags = checked | |||
? [tag.name] | |||
: industryTags.filter((t) => t !== tag.name); | |||
setIndustryTags(nextSelectedTags); | |||
}; | |||
// 企业规模 | |||
const [natureTags, setNatureTags] = useState<string[]>(['不限']); | |||
const [natureItem, setNatureItem] = useState<object>(null); | |||
const natureChange = (tag: object, checked: boolean) => { | |||
setNatureItem(tag); | |||
const nextSelectedTags = checked | |||
? [tag.name] | |||
: natureTags.filter((t) => t !== tag.name); | |||
setNatureTags(nextSelectedTags); | |||
setSearchJobParams(prevState => ({ | |||
...prevState, | |||
nature: tag.id | |||
})); | |||
}; | |||
// 规模 | |||
const [scaleTags, setScaleTags] = useState<string[]>(['不限']); | |||
const [scaleItem, setScaleItem] = useState<object>(null); | |||
const scaleChange = (tag: object, checked: boolean) => { | |||
setScaleItem(tag); | |||
const nextSelectedTags = checked | |||
? [tag.name] | |||
: scaleTags.filter((t) => t !== tag.name); | |||
setScaleTags(nextSelectedTags); | |||
setSearchJobParams(prevState => ({ | |||
...prevState, | |||
scale: tag.id | |||
})); | |||
}; | |||
// 见习基地 | |||
const [probationTags, setProbationTags] = useState<string[]>(['不限']); | |||
const [probationItem, setProbationItem] = useState<object>(null); | |||
const probationChange = (tag: object, checked: boolean) => { | |||
setProbationItem(tag); | |||
const nextSelectedTags = checked | |||
? [tag.name] | |||
: probationTags.filter((t) => t !== tag.name); | |||
setProbationTags(nextSelectedTags); | |||
setSearchJobParams(prevState => ({ | |||
...prevState, | |||
urgent: tag.id | |||
})); | |||
}; | |||
// 知名企业 | |||
const [famousTags, setFamousTags] = useState<string[]>(['不限']); | |||
const [famousItem, setFamousItem] = useState<object>(null); | |||
const famousChange = (tag: object, checked: boolean) => { | |||
setFamousItem(tag); | |||
const nextSelectedTags = checked | |||
? [tag.name] | |||
: famousTags.filter((t) => t !== tag.name); | |||
setFamousTags(nextSelectedTags); | |||
setSearchJobParams(prevState => ({ | |||
...prevState, | |||
urgent: tag.id | |||
})); | |||
}; | |||
useEffect(() => { | |||
setSearchJobParams(prevState => ({ | |||
...prevState, | |||
keyword: keywordName | |||
})); | |||
}, [keywordName]); | |||
useEffect(() => { | |||
getSearchParams(searchJobParams) | |||
}, [searchJobParams]) | |||
return ( | |||
<> | |||
<ConfigProvider | |||
theme={{ | |||
components: { | |||
Segmented: { | |||
colorText: '#19be6e' | |||
}, | |||
Button: { | |||
colorText: '' | |||
}, | |||
Tabs: { | |||
verticalItemPadding: '0 24px' | |||
} | |||
} | |||
}} | |||
> | |||
<Space direction='vertical' size={20} style={{ width: '100%' }}> | |||
<Flex justify='center' align='center'> | |||
<Space.Compact style={{ width: '80%' }}> | |||
<Input | |||
size='large' | |||
prefix={<SearchOutlined style={{ color: '#19be6e' }} />} | |||
placeholder="请输入关键词" | |||
allowClear | |||
value={keywordName} | |||
onBlur={(e) => { | |||
setKeywordName(e.target.value) | |||
}} | |||
onClear={() => { | |||
setKeywordName('') | |||
}} | |||
// defaultValue={searchParams.keyword} | |||
/> | |||
<Button size='large' type='primary' style={{ width: 200 }} onClick={() => { | |||
setKeywordName(searchJobParams.keyword) | |||
}}>搜索</Button> | |||
</Space.Compact> | |||
</Flex> | |||
{/* 筛选 */} | |||
<Space direction='vertical' style={{ background: '#ffffff', padding: 20, borderRadius: 4 }}> | |||
<Descriptions> | |||
<Descriptions.Item span={24} label="见习基地"> | |||
<Flex gap={4} wrap align="center"> | |||
{dictModel.probationList.map((item, index) => ( | |||
<Tag.CheckableTag | |||
key={item.id} | |||
checked={probationTags.includes(item.name)} | |||
onChange={(checked) => { | |||
probationChange(item, checked) | |||
}} | |||
> | |||
{item.name} | |||
</Tag.CheckableTag> | |||
))} | |||
</Flex> | |||
</Descriptions.Item> | |||
<Descriptions.Item span={24} label="知名企业"> | |||
<Flex gap={4} wrap align="center"> | |||
{dictModel.famousList.map((item, index) => ( | |||
<Tag.CheckableTag | |||
key={item.id} | |||
checked={famousTags.includes(item.name)} | |||
onChange={(checked) => { | |||
famousChange(item, checked) | |||
}} | |||
> | |||
{item.name} | |||
</Tag.CheckableTag> | |||
))} | |||
</Flex> | |||
</Descriptions.Item> | |||
{/* 企业性质 */} | |||
<Descriptions.Item span={24} label="企业性质"> | |||
<Flex gap={4} wrap align="center"> | |||
{dictModel.natureList.map((item, index) => ( | |||
<Tag.CheckableTag | |||
key={item.id} | |||
checked={natureTags.includes(item.name)} | |||
onChange={(checked) => { | |||
natureChange(item, checked) | |||
}} | |||
> | |||
{item.name} | |||
</Tag.CheckableTag> | |||
))} | |||
</Flex> | |||
</Descriptions.Item> | |||
{/* 企业规模 */} | |||
<Descriptions.Item span={24} label="企业规模"> | |||
<Flex gap={4} wrap align="center"> | |||
{dictModel.scaleList.map((item, index) => ( | |||
<Tag.CheckableTag | |||
key={item.id} | |||
checked={scaleTags.includes(item.name)} | |||
onChange={(checked) => { | |||
scaleChange(item, checked) | |||
}} | |||
> | |||
{item.name} | |||
</Tag.CheckableTag> | |||
))} | |||
</Flex> | |||
</Descriptions.Item> | |||
{/* 地区选择 */} | |||
<Descriptions.Item span={24} label="地区选择"> | |||
<Space direction='vertical' size='small' style={{ maxWidth: 800, minWidth: 600 }}> | |||
<Flex wrap style={{ width: '100%' }}> | |||
{ | |||
dictModel.xiaolanzhenList.map((item, index) => ( | |||
<Tag.CheckableTag | |||
checked={item.checked} | |||
onChange={() => { | |||
cityChange(item, index) | |||
setAreaItem({ item: item, index: index }) | |||
searchCityChange(areaItem.item, areaItem.index) | |||
}} | |||
> | |||
{item.name} | |||
</Tag.CheckableTag> | |||
)) | |||
} | |||
</Flex> | |||
<Flex wrap style={{ width: '100%' }}> | |||
{ | |||
dictModel.zhongshanList.map((item, index) => ( | |||
<Tag.CheckableTag | |||
checked={item.checked} | |||
onChange={() => { | |||
cityChange(item, index) | |||
setAreaItem({ item: item, index: index }) | |||
searchCityChange(areaItem.item, areaItem.index) | |||
}} | |||
> | |||
{item.name} | |||
</Tag.CheckableTag> | |||
)) | |||
} | |||
</Flex> | |||
<Cascader style={{ width: '50%' }} placeholder="请选择地区" options={dictModel.areaList} fieldNames={cascaderfieldNames} /> | |||
</Space> | |||
</Descriptions.Item> | |||
{/* 地区选择 */} | |||
<Descriptions.Item span={24} label="更多选择"> | |||
<Space> | |||
<Popconfirm | |||
showCancel={false} | |||
placement="right" | |||
title='行业' | |||
icon={null} | |||
description={<> | |||
{/* 行业 */} | |||
<Space direction='vertical' size='small' style={{ maxWidth: 800, minWidth: 600, height: '600px' }}> | |||
<Tabs | |||
size='small' | |||
style={{ maxWidth: 800, minWidth: 600, height: '600px' }} | |||
tabPosition='left' | |||
items={dictModel.industryPostList.map((item, index) => { | |||
return { | |||
key: item.id, | |||
label: item.name, | |||
children: (<> | |||
<Space direction='vertical' style={{ height: '600px', overflow: 'auto' }}> | |||
{ | |||
item.children.map((childrenItem, childrenIndex) => ( | |||
<> | |||
<Tag.CheckableTag | |||
key={childrenItem.id} | |||
checked={industryTags.includes(childrenItem.name)} | |||
onChange={(checked) => { | |||
childrenItem.industry = item.id; | |||
childrenItem.industry2 = childrenItem.id; | |||
setIndustryItem(childrenItem) | |||
industryChange(childrenItem, checked) | |||
}} | |||
style={{ | |||
display: 'flex', | |||
alignItems: 'center', | |||
justifyContent: 'center', | |||
width: 300, | |||
padding: '8px 0', | |||
background: industryTags.includes(childrenItem.name) ? '#19be6e' : '#edfff3', | |||
color: industryTags.includes(childrenItem.name) ? '#f0f0f0' : '#000000', | |||
}} | |||
> | |||
<Space> | |||
{childrenItem.name} | |||
</Space> | |||
</Tag.CheckableTag> | |||
</> | |||
)) | |||
} | |||
</Space> | |||
</>) | |||
} | |||
})} | |||
/> | |||
{/* <Cascader.Panel style={{border: 'none'}} options={dictModel.industryPostList} fieldNames={cascaderfieldNames} /> */} | |||
</Space> | |||
</> | |||
} | |||
okText="搜索" | |||
onConfirm={() => { | |||
setSearchJobParams(prevState => ({ | |||
...prevState, | |||
industry: industryItem.industry, | |||
industry2: industryItem.industry2, | |||
})); | |||
}} | |||
> | |||
<Button size='small'>行业选择</Button> | |||
</Popconfirm> | |||
</Space> | |||
</Descriptions.Item> | |||
</Descriptions> | |||
<Flex justify='space-between' align='center'> | |||
<Space> | |||
<div style={{ width: 60 }}>已选择:</div> | |||
<Row gutter={[10, 10]} > | |||
{keywordName && <Col> | |||
<Tag closeIcon color="#4FBE70" onClose={() => { | |||
setKeywordName('') | |||
setSearchJobParams(prevState => ({ | |||
...prevState, | |||
keyword: '' | |||
})); | |||
}} | |||
>{keywordName}</Tag> | |||
</Col>} | |||
{probationItem && <Col> <Tag closeIcon color="#4FBE70" onClose={() => { | |||
setProbationItem(null) | |||
setSearchJobParams(prevState => ({ | |||
...prevState, | |||
probation: 0 | |||
})); | |||
}}>{probationItem.name}</Tag></Col>} | |||
{famousItem && <Col> <Tag closeIcon color="#4FBE70" onClose={() => { | |||
setFamousItem(null) | |||
setSearchJobParams(prevState => ({ | |||
...prevState, | |||
famous: 0 | |||
})); | |||
}}>{famousItem.name}</Tag></Col>} | |||
{areaName && <Col> <Tag closeIcon color="#4FBE70" onClose={() => { | |||
setAreaName('') | |||
setSearchJobParams(prevState => ({ | |||
...prevState, | |||
province: 0, | |||
city: 0, | |||
district: 0, | |||
street: 0 | |||
})); | |||
}}>{areaName}</Tag></Col>} | |||
{industryItem && <Col> <Tag closeIcon color="#4FBE70" onClose={() => { | |||
setIndustryItem(null) | |||
setSearchJobParams(prevState => ({ | |||
...prevState, | |||
industry: 0, | |||
industry2: 0, | |||
})); | |||
}}>{industryItem.name}</Tag></Col>} | |||
{natureItem && <Col> <Tag closeIcon color="#4FBE70" onClose={() => { | |||
setNatureItem(null); setNatureTags(['不限']) | |||
setSearchJobParams(prevState => ({ | |||
...prevState, | |||
nature: 0 | |||
})); | |||
}}>{natureItem.name}</Tag></Col>} | |||
{scaleItem && <Col> <Tag closeIcon color="#4FBE70" onClose={() => { | |||
setScaleItem(null); setScaleTags(['不限']) | |||
setSearchJobParams(prevState => ({ | |||
...prevState, | |||
scale: 0 | |||
})); | |||
}}>{scaleItem.name}</Tag></Col>} | |||
</Row> | |||
</Space> | |||
<Button size="small" onClick={() => { | |||
setKeywordName('') | |||
setAreaName('') | |||
setIndustryItem(null) | |||
setNatureItem(null) | |||
setScaleItem(null) | |||
setNatureTags(['不限']); | |||
setScaleTags(['不限']); | |||
setSearchJobParams({ | |||
"keyword": "", | |||
"location": 0, | |||
"probation": 0, | |||
"famous": 0, | |||
"industry": 0, | |||
"nature": 0, | |||
"scale": 0, | |||
"page": 1, | |||
"pagesize": 18, | |||
"sort": "id", | |||
"sortby": "desc" | |||
}); | |||
}} > | |||
清空筛选 | |||
</Button> | |||
</Flex> | |||
</Space> | |||
</Space> | |||
</ConfigProvider> | |||
</> | |||
) | |||
} | |||
export default connect(({ dictModel, openModel }: any) => ({ | |||
dictModel | |||
}))(SearchFilter); |
@@ -27,6 +27,36 @@ const naturelist = [{ | |||
checked: false | |||
}] | |||
const probationlist = [{ | |||
name: '不限', | |||
value: '0', | |||
checked: true | |||
}, { | |||
name: '是', | |||
value: 1, | |||
checked: false | |||
}, { | |||
name: '否', | |||
value: 2, | |||
checked: false | |||
}] | |||
const famouslist = [{ | |||
name: '不限', | |||
value: '0', | |||
checked: true | |||
}, { | |||
name: '是', | |||
value: 1, | |||
checked: false | |||
}, { | |||
name: '否', | |||
value: 2, | |||
checked: false | |||
}] | |||
export default { | |||
state: { | |||
@@ -83,7 +113,9 @@ export default { | |||
name: '女', | |||
value: '女', | |||
checked: false | |||
}] // 性别要求 | |||
}] ,// 性别要求 | |||
probationList: probationlist, | |||
famousList: famouslist | |||
}, | |||
reducers: { | |||
setXiaolanzhenList(state: any, { payload }: any) { |
@@ -103,7 +103,7 @@ const HomePage: React.FC = ({ dispatch, dictModel }: any) => { | |||
setKeywordName(e.target.value) | |||
}} | |||
/> | |||
<Link to={{ pathname: `/talent/search?keyword=${keywordName}` }}> | |||
<Link to={{ pathname: `/talent/search/job?keyword=${keywordName}` }}> | |||
<Button size='large' type='primary' style={{ width: 200 }}>搜索</Button> | |||
</Link> | |||
</Space.Compact> | |||
@@ -111,25 +111,25 @@ const HomePage: React.FC = ({ dispatch, dictModel }: any) => { | |||
<Flex justify='center' align='center'> | |||
<Space size={30} style={{ width: '70%' }}> | |||
<Link to={{ pathname: `/talent/search?keyword=客服` }} style={{ color: 'gray' }}> | |||
<Link to={{ pathname: `/talent/search/job?keyword=客服` }} style={{ color: 'gray' }}> | |||
客服 | |||
</Link> | |||
<Link to={{ pathname: `/talent/search?keyword=会计` }} style={{ color: 'gray' }}> | |||
<Link to={{ pathname: `/talent/search/job?keyword=会计` }} style={{ color: 'gray' }}> | |||
会计 | |||
</Link> | |||
<Link to={{ pathname: `/talent/search?keyword=销售` }} style={{ color: 'gray' }}> | |||
<Link to={{ pathname: `/talent/search/job?keyword=销售` }} style={{ color: 'gray' }}> | |||
销售 | |||
</Link> | |||
<Link to={{ pathname: `/talent/search?keyword=策划` }} style={{ color: 'gray' }}> | |||
<Link to={{ pathname: `/talent/search/job?keyword=策划` }} style={{ color: 'gray' }}> | |||
策划 | |||
</Link> | |||
<Link to={{ pathname: `/talent/search?keyword=外贸` }} style={{ color: 'gray' }}> | |||
<Link to={{ pathname: `/talent/search/job?keyword=外贸` }} style={{ color: 'gray' }}> | |||
外贸 | |||
</Link> | |||
<Link to={{ pathname: `/talent/search?keyword=文员` }} style={{ color: 'gray' }}> | |||
<Link to={{ pathname: `/talent/search/job?keyword=文员` }} style={{ color: 'gray' }}> | |||
文员 | |||
</Link> | |||
<Link to={{ pathname: `/talent/search?keyword=行政` }} style={{ color: 'gray' }}> | |||
<Link to={{ pathname: `/talent/search/job?keyword=行政` }} style={{ color: 'gray' }}> | |||
行政 | |||
</Link> | |||
</Space> |
@@ -0,0 +1,177 @@ | |||
import { useState, useEffect, useRef } from 'react'; | |||
import { ProList, PageContainer } from '@ant-design/pro-components'; | |||
import { ConfigProvider, Button, Flex, Input, Space, Image, Select, Row, Col, Pagination, Tag, Card, Divider, Typography, Anchor } from 'antd'; | |||
import { SearchOutlined, LikeOutlined, ArrowRightOutlined, StarOutlined } from '@ant-design/icons'; | |||
import { useModel, connect, history, Link, useSearchParams } from 'umi'; | |||
import SearchFilter from '@/components/Talent/Search/Filter/Company'; | |||
import SearchJob from '@/components/Talent/Search/Company/index'; | |||
import { Imageprefix } from '@/constants/index' | |||
import { PostCompanySearch } from '@/services/apis/company'; | |||
import { GetAdvertscheduleList } from '@/services/apis/advertschedule'; | |||
import EmptyResult from '@/components/Common/EmptyResult' | |||
import CommonJob from '@/components/Common/Job' | |||
const HomePage: React.FC = () => { | |||
const [searchParams, setSearchParams] = useSearchParams(); | |||
const [list, setList] = useState<object[]>([]) | |||
const [advertscheduleList, setAdvertscheduleList] = useState<object[]>([]) | |||
const [search, setSearch] = useState<object | null>(null) | |||
const [total, setTotal] = useState<number>(0) | |||
const [page, setPage] = useState<number>(1) | |||
const [pagesize, setPageSize] = useState<number>(7) | |||
useEffect(() => { | |||
GetAdvertscheduleList({ page: 1, pagesize: 4, code: 'wzsylbt' }).then(res => { | |||
setAdvertscheduleList(res.data.advertschedules) | |||
}) | |||
}, []); | |||
// useEffect(() => { | |||
// PostJobSearch({ | |||
// page: 1, | |||
// pagesize: 12, | |||
// sort: 'updated_at', | |||
// sortby: 'desc' | |||
// }).then(res => { | |||
// setList(res.data.jobs) | |||
// getTotal(res.data.total) | |||
// }) | |||
// }, []); | |||
const getSearchParams = async (value) => { | |||
setPage(value.page) | |||
setPageSize(value.pagesize) | |||
if (value.keyword) { | |||
setSearchParams({ keyword: value.keyword }) | |||
} else { | |||
setSearchParams({ keyword: '' }) | |||
} | |||
let res = await PostCompanySearch(value ? value : { | |||
page: 1, | |||
pagesize: 18, | |||
sort: 'updated_at', | |||
sortby: 'desc', | |||
}) | |||
setList(res.data.list) | |||
getTotal(res.data.total) | |||
} | |||
const getTotal = (value) => { | |||
setTotal(value) | |||
} | |||
return ( | |||
<> | |||
<ConfigProvider | |||
theme={{ | |||
token: { | |||
colorPrimary: '#19be6e', | |||
}, | |||
components: { | |||
Button: { | |||
colorText: '#19be6e' | |||
} | |||
} | |||
}} | |||
> | |||
<Space direction='vertical' size={30} style={{ minHeight: '800px' }}> | |||
<SearchFilter getSearchParams={getSearchParams} keyword={searchParams.get('keyword') ? searchParams.get('keyword') : ''}></SearchFilter> | |||
<Row gutter={[16, 16]}> | |||
<Col span={18}> | |||
<Row gutter={[16, 16]}> | |||
{ | |||
list && list.length > 0 && list.map((item: any, index: number) => ( | |||
<> | |||
<Col span={8}> | |||
<Link to={{ pathname: `/talent/company/detail?id=${item.id}` }} target="_blank" style={{ width: '100%' }}> | |||
<Space direction='vertical' size={10} align='center' style={{ width: '100%', paddingTop: 20, paddingBottom: 20, background: '#ffffff', borderRadius: 8 }}> | |||
<Image src={item.photo ? `${Imageprefix}${item.photo}` : '/images/logo.jpg'} preview={false} width={'140px'} height={'78px'} style={{ borderRadius: '8px' }}></Image> | |||
<Typography.Title level={5} style={{ width: '100%', padding: '0 10px' }} | |||
> | |||
{item.full_name} | |||
</Typography.Title> | |||
<Flex justify='flex-end' align='center' style={{ fontSize: 14, color: '#999' }}> | |||
{item.company_nature ? <>{item.company_nature}</> : <>性质不限</>} | |||
{item.industry_text ? <><Divider type='vertical' /> {item.industry_text} </> : <><Divider type='vertical' />行业不限</>} | |||
{item.company_scale ? <><Divider type='vertical' /> {item.company_scale} </> : <><Divider type='vertical' />规模不限</>} | |||
</Flex> | |||
</Space> | |||
</Link> | |||
</Col> | |||
</> | |||
)) | |||
} | |||
</Row> | |||
{ | |||
!list || list.length == 0 && <EmptyResult description="没有找到符合条件的企业" /> | |||
} | |||
<Flex justify='center' align='center' style={{ margin: '40px 0' }}> | |||
<Pagination | |||
hideOnSinglePage | |||
total={total} | |||
showTotal={(total) => `总共${total}条`} | |||
current={page} | |||
pageSize={pagesize} | |||
pageSizeOptions={['12', '24', '36']} | |||
onChange={(page, pageSize) => { | |||
setPage(page) | |||
setPageSize(pageSize) | |||
}} | |||
/> | |||
</Flex> | |||
</Col> | |||
<Col span={6}> | |||
{ | |||
advertscheduleList && advertscheduleList.length && advertscheduleList.map((item, index) => ( | |||
<div style={{ borderRadius: 8, marginBottom: 20 }}> | |||
<div style={{ | |||
width: '100%', | |||
position: 'relative', | |||
paddingTop: '56.25%', /* 16:9 的比例 */ | |||
overflow: 'hidden' | |||
}}> | |||
<Link to={{ pathname: item.target_url }} target='_blank'> | |||
<img src={Imageprefix + item.image_url} style={{ | |||
position: 'absolute', | |||
top: 0, | |||
left: 0, | |||
width: '100%', | |||
height: '100%', | |||
borderRadius: 8 | |||
}} /> | |||
</Link> | |||
</div> | |||
</div> | |||
)) | |||
} | |||
</Col> | |||
</Row> | |||
</Space> | |||
</ConfigProvider > | |||
</> | |||
); | |||
}; | |||
export default HomePage; |
@@ -0,0 +1,157 @@ | |||
import { useState, useEffect, useRef } from 'react'; | |||
import { ProList, PageContainer } from '@ant-design/pro-components'; | |||
import { ConfigProvider, Button, Flex, Input, Space, Image, Select, Row, Col, Pagination, Tag, Card, Avatar, Typography, Anchor } from 'antd'; | |||
import { SearchOutlined, LikeOutlined, ArrowRightOutlined, StarOutlined } from '@ant-design/icons'; | |||
import { useModel, connect, history, Link, useSearchParams } from 'umi'; | |||
import SearchFilter from '@/components/Talent/Search/Filter/index'; | |||
import SearchJob from '@/components/Talent/Search/Job/index'; | |||
import { Imageprefix } from '@/constants/index' | |||
import { PostJobSearch } from '@/services/apis/post'; | |||
import { GetAdvertscheduleList } from '@/services/apis/advertschedule'; | |||
import EmptyResult from '@/components/Common/EmptyResult' | |||
import CommonJob from '@/components/Common/Job' | |||
const HomePage: React.FC = () => { | |||
const [searchParams, setSearchParams] = useSearchParams(); | |||
const [list, setList] = useState<object[]>([]) | |||
const [advertscheduleList, setAdvertscheduleList] = useState<object[]>([]) | |||
const [search, setSearch] = useState<object | null>(null) | |||
const [total, setTotal] = useState<number>(0) | |||
const [page, setPage] = useState<number>(1) | |||
const [pagesize, setPageSize] = useState<number>(7) | |||
useEffect(() => { | |||
GetAdvertscheduleList({ page: 1, pagesize: 4, code: 'wzsylbt' }).then(res => { | |||
setAdvertscheduleList(res.data.advertschedules) | |||
}) | |||
}, []); | |||
// useEffect(() => { | |||
// PostJobSearch({ | |||
// page: 1, | |||
// pagesize: 12, | |||
// sort: 'updated_at', | |||
// sortby: 'desc' | |||
// }).then(res => { | |||
// setList(res.data.jobs) | |||
// getTotal(res.data.total) | |||
// }) | |||
// }, []); | |||
const getSearchParams = async (value) => { | |||
setPage(value.page) | |||
setPageSize(value.pagesize) | |||
if (value.keyword) { | |||
setSearchParams({ keyword: value.keyword }) | |||
} else { | |||
setSearchParams({ keyword: '' }) | |||
} | |||
let res = await PostJobSearch(value ? value : { | |||
page: 1, | |||
pagesize: 12, | |||
sort: 'updated_at', | |||
sortby: 'desc', | |||
}) | |||
setList(res.data.jobs) | |||
getTotal(res.data.total) | |||
} | |||
const getTotal = (value) => { | |||
setTotal(value) | |||
} | |||
return ( | |||
<> | |||
<ConfigProvider | |||
theme={{ | |||
token: { | |||
colorPrimary: '#19be6e', | |||
}, | |||
components: { | |||
Button: { | |||
colorText: '#19be6e' | |||
} | |||
} | |||
}} | |||
> | |||
<Space direction='vertical' size={30} style={{ minHeight: '800px' }}> | |||
<SearchFilter getSearchParams={getSearchParams} keyword={searchParams.get('keyword') ? searchParams.get('keyword') : ''}></SearchFilter> | |||
<Row gutter={[16, 16]}> | |||
<Col span={18}> | |||
{ | |||
list && list.length > 0 && list.map((item: any, index: number) => ( | |||
<> | |||
<CommonJob item={item}></CommonJob> | |||
</> | |||
)) | |||
} | |||
{ | |||
!list || list.length == 0 && <EmptyResult description="没有找到符合条件的职位" /> | |||
} | |||
<Flex justify='center' align='center' style={{ margin: '40px 0' }}> | |||
<Pagination | |||
hideOnSinglePage | |||
total={total} | |||
showTotal={(total) => `总共${total}条`} | |||
current={page} | |||
pageSize={pagesize} | |||
pageSizeOptions={['12', '24', '36']} | |||
onChange={(page, pageSize) => { | |||
setPage(page) | |||
setPageSize(pageSize) | |||
}} | |||
/> | |||
</Flex> | |||
</Col> | |||
<Col span={6}> | |||
{ | |||
advertscheduleList && advertscheduleList.length && advertscheduleList.map((item, index) => ( | |||
<div style={{ borderRadius: 8, marginBottom: 20 }}> | |||
<div style={{ | |||
width: '100%', | |||
position: 'relative', | |||
paddingTop: '56.25%', /* 16:9 的比例 */ | |||
overflow: 'hidden' | |||
}}> | |||
<Link to={{ pathname: item.target_url }} target='_blank'> | |||
<img src={Imageprefix + item.image_url} style={{ | |||
position: 'absolute', | |||
top: 0, | |||
left: 0, | |||
width: '100%', | |||
height: '100%', | |||
borderRadius: 8 | |||
}} /> | |||
</Link> | |||
</div> | |||
</div> | |||
)) | |||
} | |||
</Col> | |||
</Row> | |||
</Space> | |||
</ConfigProvider > | |||
</> | |||
); | |||
}; | |||
export default HomePage; |
@@ -39,3 +39,7 @@ export const GetCompanyCustomerCodeDetail = GetModel(CompanyUrl.CompanyCustomerC | |||
export const GetCompanyRecruiters = GetModel(CompanyUrl.CompanyRecruiters); // 列表 | |||
export const PostJobseekerResetPwd = PostModel(CompanyUrl.JobseekerResetPwd); | |||
export const PostCompanySearch = PostModel(CompanyUrl.CompanySearch); | |||
@@ -173,7 +173,7 @@ declare namespace Url { | |||
CompanyRecruiters?: string | |||
JobseekerResetPwd?: string // 重置密码 | |||
CompanySearch?: string | |||
} | |||
interface Advertschedule { |
@@ -39,5 +39,10 @@ export const CompanyUrl: Url.Company = { | |||
CompanyRecruiters: web + '/company/recruiters', // 详情 | |||
JobseekerResetPwd: web + '/jobseeker/resetpwd', // 重置密码 | |||
CompanySearch: web + '/company/search', // 重置密码 | |||
} | |||