From 4412d752d5db2417f328ccf18984f198d379ef1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=86=AF=E8=BE=89?= Date: Sun, 28 Jun 2026 00:38:38 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=BF=E7=AD=96=E7=AD=9B=E9=80=89=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=E5=BC=80=E5=8F=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/JobPortal/Policy/index.less | 94 +++++++++++++++++++++++ src/pages/JobPortal/Policy/index.tsx | 105 +++++++++++++++++++++++++- src/types/cms/policyInfo.d.ts | 1 + 3 files changed, 199 insertions(+), 1 deletion(-) diff --git a/src/pages/JobPortal/Policy/index.less b/src/pages/JobPortal/Policy/index.less index d8aa99a..8c224eb 100644 --- a/src/pages/JobPortal/Policy/index.less +++ b/src/pages/JobPortal/Policy/index.less @@ -51,8 +51,70 @@ } } + .policy-tag-filter { + display: flex; + align-items: center; + gap: 8px; + margin-bottom: 16px; + padding-bottom: 16px; + border-bottom: 1px solid @jp-border; + + &__label { + flex-shrink: 0; + line-height: 22px; + font-size: 13px; + color: @jp-text-secondary; + font-weight: 500; + } + + &__tags { + display: flex; + flex-wrap: wrap; + gap: 8px; + } + + &__item { + cursor: pointer; + margin: 0; + border-radius: @jp-radius; + transition: all 0.2s; + user-select: none; + + &:hover { + color: @jp-primary; + border-color: @jp-primary; + } + + &--active { + color: #fff !important; + background: @jp-primary !important; + border-color: @jp-primary !important; + } + + &--recommend { + color: #ec4827 !important; + background: #fff5f3 !important; + border-color: rgba(236, 72, 39, 0.25) !important; + font-weight: 500; + + &:hover { + color: #ec4827 !important; + border-color: #ec4827 !important; + } + + &.policy-tag-filter__item--active { + color: #fff !important; + background: #ec4827 !important; + border-color: #ec4827 !important; + } + } + } + } + .policy-list { .policy-item { + display: flex; + align-items: center; padding: 20px 0; cursor: pointer; border-bottom: 1px solid @jp-border; @@ -71,6 +133,38 @@ } } + .policy-item-body { + flex: 1; + min-width: 0; + } + + .policy-download-btn { + display: inline-flex; + align-items: center; + gap: 4px; + flex-shrink: 0; + margin-left: 16px; + padding: 6px 14px; + font-size: 13px; + color: @jp-primary; + background: #fff; + border: 1px solid @jp-primary; + border-radius: @jp-radius; + cursor: pointer; + transition: all 0.2s; + user-select: none; + white-space: nowrap; + + &:hover { + color: #fff; + background: @jp-primary; + } + + &__text { + font-size: 13px; + } + } + .policy-title { margin: 0 0 10px; color: @jp-text-primary; diff --git a/src/pages/JobPortal/Policy/index.tsx b/src/pages/JobPortal/Policy/index.tsx index ba3091c..c7c2ec2 100644 --- a/src/pages/JobPortal/Policy/index.tsx +++ b/src/pages/JobPortal/Policy/index.tsx @@ -14,10 +14,13 @@ import { FileTextOutlined, SearchOutlined, BankOutlined, + DownloadOutlined, } from '@ant-design/icons'; import { history } from '@umijs/max'; import JobPortalHeader from '@/components/JobPortalHeader'; import { getPolicyInfoList } from '@/services/cms/policyInfo'; +import { getDictValueEnum } from '@/services/system/dict'; +import type { DictValueEnumObj } from '@/components/DictTag'; import './index.less'; const { Title, Text } = Typography; @@ -30,6 +33,43 @@ const PolicyListPage: React.FC = () => { const [pageSize] = useState(10); const [searchValue, setSearchValue] = useState(''); const [keyword, setKeyword] = useState(''); + const [selectedPolicyTag, setSelectedPolicyTag] = useState('__recommended__'); + const [userTypeEnum, setUserTypeEnum] = useState({}); + + /** 从 localStorage 读取当前用户的 personnel type */ + const currentUserType = (() => { + try { + const raw = localStorage.getItem('userInfo'); + if (raw) { + const userInfo = JSON.parse(raw); + return userInfo?.userType ? String(userInfo.userType) : ''; + } + } catch { /* ignore */ } + return ''; + })(); + + useEffect(() => { + getDictValueEnum('user_type', false, true).then((data) => { + setUserTypeEnum(data); + // 无用户类型时默认选中「全部」 + if (!currentUserType) { + setSelectedPolicyTag(''); + } + }); + }, []); + + /** 将字典枚举转为标签数组,按 value 排序 */ + const userTypeTags = Object.values(userTypeEnum) + .map((item) => ({ label: item.label, value: item.value })) + .sort((a, b) => Number(a.value) - Number(b.value)); + + /** 将内部标记转为实际 API 参数 */ + const resolvePolicyTag = (tag: string): string | undefined => { + if (tag === '__recommended__') { + return currentUserType || undefined; + } + return tag || undefined; + }; const fetchList = useCallback(async () => { try { @@ -38,6 +78,7 @@ const PolicyListPage: React.FC = () => { pageNum, pageSize, searchValue: keyword || undefined, + policyTag: resolvePolicyTag(selectedPolicyTag), }); if (response?.code === 200) { setList(response.rows || []); @@ -51,7 +92,7 @@ const PolicyListPage: React.FC = () => { } finally { setLoading(false); } - }, [pageNum, pageSize, keyword]); + }, [pageNum, pageSize, keyword, selectedPolicyTag]); useEffect(() => { fetchList(); @@ -62,10 +103,34 @@ const PolicyListPage: React.FC = () => { setKeyword(searchValue.trim()); }; + /** 点击人员类型标签:选中/取消选中 */ + const handleTagClick = (tagValue: string) => { + setPageNum(1); + if (selectedPolicyTag === tagValue) { + setSelectedPolicyTag(''); + } else { + setSelectedPolicyTag(tagValue); + } + }; + const handleItemClick = (item: API.PolicyInfo.PolicyInfoItem) => { history.push(`/job-portal/policy/detail?id=${item.id}`); }; + /** 下载政策附件 */ + const handleDownload = (e: React.MouseEvent, item: API.PolicyInfo.PolicyInfoItem) => { + e.stopPropagation(); + if (!item.fileUrl) return; + const link = document.createElement('a'); + link.href = item.fileUrl; + link.download = item.fileName || ''; + link.target = '_blank'; + link.rel = 'noopener noreferrer'; + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + }; + return (
@@ -95,6 +160,34 @@ const PolicyListPage: React.FC = () => {
+ {userTypeTags.length > 0 && ( +
+ 人员类型: +
+ {currentUserType && ( + handleTagClick('__recommended__')} + > + 推荐 + + )} + {userTypeTags.map((tag) => ( + handleTagClick(tag.value)} + > + {tag.label} + + ))} +
+
+ )} {list.length > 0 ? ( <> { )} + {item.fileUrl && ( + handleDownload(e, item)} + > + + 下载 + + )} )} /> diff --git a/src/types/cms/policyInfo.d.ts b/src/types/cms/policyInfo.d.ts index 9d5ebea..f3b418f 100644 --- a/src/types/cms/policyInfo.d.ts +++ b/src/types/cms/policyInfo.d.ts @@ -49,5 +49,6 @@ declare namespace API.PolicyInfo { pageNum?: number; pageSize?: number; searchValue?: string; + policyTag?: string; } }