import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import styles from "./Campus.module.css"; import Banner, { type BannerConfig } from "@/components/Banner"; import Section from "@/components/layout/Section"; import { useStore } from "@/store"; import { SearchOutlined, FilterOutlined, DownOutlined, RightOutlined } from "@ant-design/icons"; import { Empty, Select } from "antd"; import Pagination from "@/components/Pagination"; import { Link } from "react-router-dom"; import { debounce } from "@/utils"; import appApi from "@/api/app"; type JobItem = { id: number; title: string; content: string; labels: string[]; lang: string } export default function JoinCampus() { const appConfig = useStore((s) => s.appConfig); const supportLocales = useStore((s) => s.supportLocales); const locale = useStore((s) => s.locale); const data = appConfig?.join?.campus; const banner = data?.banner; const [searchValue, setSearchValue] = useState(''); // 职业类别 业务领域 所属板块 const [jobType, setJobType] = useState(''); const [jobTypeOptions, setJobTypeOptions] = useState([]); const [businessArea, setBusinessArea] = useState(''); const [businessAreaOptions, setBusinessAreaOptions] = useState([]); const [businessPlate, setBusinessPlate] = useState(''); const [businessPlateOptions, setBusinessPlateOptions] = useState([]); const [page, setPage] = useState(1); const [size] = useState(2 * supportLocales.length); const [total, setTotal] = useState(1000); const [jobList, setJobList] = useState([]); const localJobList = useMemo(() => { return jobList.filter(item => item.lang.toLowerCase() === locale.split('-')[0]); }, [jobList, locale]); // 用 ref 保存最新参数,保证 debounce 使用稳定的函数引用 const paramsRef = useRef({ searchValue, jobType, businessArea, businessPlate, page, size }); paramsRef.current = { searchValue, jobType, businessArea, businessPlate, page, size }; const refreshData = useMemo(() => debounce(() => { const { searchValue: sv, jobType: jt, businessArea: ba, businessPlate: bp, page: p, size: s } = paramsRef.current; appApi.getJobList({ page: p, size: s, sort: "", title: sv, job_type: jt, business_area: ba, business_plate: bp }).then((res) => { const items = res.data.items.map((item: any) => { const { job_type_name, job_area_name, job_unit_name } = item.category; const labels = [job_type_name, job_area_name, job_unit_name]; return { id: item.id, title: item.title, content: item.description, labels, lang: item.lang, }; }); setJobList(items || []); setTotal(res.data.total); }); }, 500), []); const getTypes = useCallback(() => { ['job_type', 'job_area', 'job_unit'].forEach(type => { appApi.getCategoryList(type).then((res) => { const items = res.data.items.map((item:any) => ({ label: item.name, value: item.id })); items.unshift({ label: "全部", value: "" }); if (type === 'job_type') { setJobTypeOptions(items); } else if (type === 'job_area') { setBusinessAreaOptions(items); } else if (type === 'job_unit') { setBusinessPlateOptions(items); } }) }) }, []); useEffect(() => { refreshData(); }, [searchValue, jobType, businessArea, businessPlate, page, size]); useEffect(() => { getTypes(); }, []); const handleReset = useCallback(() => { setSearchValue(''); setJobType(''); setBusinessArea(''); setBusinessPlate(''); setPage(1); }, []); return (
{/* 没有数据时显示 */} {localJobList.length === 0 && (
)} {localJobList.map((item, index) => (
{item.title}
查看详情
{item.labels.map((label, index) => (
 •  {label}
))}
{item.content}
))}
); } type SearchInputProps = { value: string; placeholder: string; onChange: (value: string) => void; onEnter: () => void; } function SearchInput( { value, placeholder, onChange, onEnter }: SearchInputProps) { return (
onChange(e.target.value)} onKeyDown={e => { if (e.key === 'Enter') { onEnter(); } }} />
); } type SelectFormItemProps = { value: string; options: { label: string; value: string }[]; label: string; onChange: (value: string) => void; } function SelectFormItem({ value, options, label, onChange }: SelectFormItemProps) { return (