| @@ -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', // 重置密码 | |||
| } | |||