政策筛选功能开发
Some checks failed
Node CI / build (14.x, macOS-latest) (push) Has been cancelled
Node CI / build (14.x, ubuntu-latest) (push) Has been cancelled
Node CI / build (14.x, windows-latest) (push) Has been cancelled
Node CI / build (16.x, macOS-latest) (push) Has been cancelled
Node CI / build (16.x, ubuntu-latest) (push) Has been cancelled
Node CI / build (16.x, windows-latest) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
coverage CI / build (push) Has been cancelled
Node pnpm CI / build (16.x, macOS-latest) (push) Has been cancelled
Node pnpm CI / build (16.x, ubuntu-latest) (push) Has been cancelled
Node pnpm CI / build (16.x, windows-latest) (push) Has been cancelled

This commit is contained in:
冯辉
2026-06-28 00:38:38 +08:00
parent d0d2c777d1
commit 4412d752d5
3 changed files with 199 additions and 1 deletions

View File

@@ -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;

View File

@@ -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<string>('__recommended__');
const [userTypeEnum, setUserTypeEnum] = useState<DictValueEnumObj>({});
/** 从 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 (
<div className="policy-page">
<JobPortalHeader showSearch={false} showHotJobs={false} />
@@ -95,6 +160,34 @@ const PolicyListPage: React.FC = () => {
</div>
<Spin spinning={loading}>
{userTypeTags.length > 0 && (
<div className="policy-tag-filter">
<span className="policy-tag-filter__label"></span>
<div className="policy-tag-filter__tags">
{currentUserType && (
<Tag
className={`policy-tag-filter__item policy-tag-filter__item--recommend ${
selectedPolicyTag === '__recommended__' ? 'policy-tag-filter__item--active' : ''
}`}
onClick={() => handleTagClick('__recommended__')}
>
</Tag>
)}
{userTypeTags.map((tag) => (
<Tag
key={tag.value}
className={`policy-tag-filter__item ${
selectedPolicyTag === tag.value ? 'policy-tag-filter__item--active' : ''
}`}
onClick={() => handleTagClick(tag.value)}
>
{tag.label}
</Tag>
))}
</div>
</div>
)}
{list.length > 0 ? (
<>
<List
@@ -126,6 +219,16 @@ const PolicyListPage: React.FC = () => {
)}
</div>
</div>
{item.fileUrl && (
<span
className="policy-download-btn"
title={`下载 ${item.fileName || '附件'}`}
onClick={(e) => handleDownload(e, item)}
>
<DownloadOutlined />
<span className="policy-download-btn__text"></span>
</span>
)}
</List.Item>
)}
/>

View File

@@ -49,5 +49,6 @@ declare namespace API.PolicyInfo {
pageNum?: number;
pageSize?: number;
searchValue?: string;
policyTag?: string;
}
}