Files
shz-admin/src/pages/Mobileusers/Rencai/index.tsx
francis-fh ac9254994a
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
路由设置
2026-07-23 13:35:29 +08:00

252 lines
7.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React, { Fragment, useEffect, useRef, useState } from 'react';
import { useAccess, useNavigate } from '@umijs/max';
import { Button, FormInstance, message, Tag } from 'antd';
import { ActionType, ProColumns, ProTable } from '@ant-design/pro-components';
import { StarFilled, FileTextOutlined, SendOutlined } from '@ant-design/icons';
import { getDictValueEnum } from '@/services/system/dict';
import DictTag from '@/components/DictTag';
import { delHrTalentCollect, getHrTalentCollectList } from '@/services/mobileusers/list';
import InterviewInvite from '@/pages/Management/List/ResumeRecommend/InterviewInvite';
function TalentCollectList() {
const access = useAccess();
const navigate = useNavigate();
const formTableRef = useRef<FormInstance>();
const actionRef = useRef<ActionType>();
const [educationEnum, setEducationEnum] = useState<any>({});
const [areaEnum, setAreaEnum] = useState<any>({});
const [sexEnum, setSexEnum] = useState<any>({});
const [inviteVisible, setInviteVisible] = useState<boolean>(false);
const [currentRow, setCurrentRow] = useState<API.TalentCollect.ListRow>();
useEffect(() => {
getDictValueEnum('education', false, true).then((data) => setEducationEnum(data));
getDictValueEnum('area', false, true).then((data) => setAreaEnum(data));
getDictValueEnum('sys_user_sex', false).then((data) => setSexEnum(data));
}, []);
// 取消收藏接口路径参数为收藏记录主键id
const handleCancelCollect = async (record: API.TalentCollect.ListRow) => {
if (!record.id) return;
try {
const res = await delHrTalentCollect(String(record.id));
if (res.code === 200) {
message.success('已取消收藏');
actionRef.current?.reload();
} else {
message.error(res.msg || '取消收藏失败');
}
} catch (error: any) {
message.error(error?.response?.data?.msg || error?.message || '取消收藏失败');
}
};
const intentionLevelMap: Record<string, { text: string; color: string }> = {
'1': { text: '高意向', color: 'red' },
'2': { text: '中等意向', color: 'blue' },
'3': { text: '低意向', color: 'default' },
};
const sourceTypeMap: Record<string, string> = {
'1': '简历搜索',
'2': '投递记录',
'3': '邀约面试',
'4': '手动录入',
};
const columns: ProColumns<API.TalentCollect.ListRow>[] = [
{
title: '用户名',
dataIndex: 'name',
valueType: 'text',
align: 'center',
},
{
title: '联系方式',
dataIndex: 'phone',
valueType: 'text',
align: 'center',
},
{
title: '意向等级',
dataIndex: 'intentionLevel',
valueType: 'select',
align: 'center',
valueEnum: {
'1': '高意向',
'2': '中等意向',
'3': '低意向',
},
render: (_, record) => {
const info = intentionLevelMap[record.intentionLevel || ''];
if (!info) return '-';
return <Tag color={info.color}>{info.text}</Tag>;
},
},
{
title: '人才标签',
dataIndex: 'collectTags',
valueType: 'text',
align: 'center',
render: (_, record) => {
if (!record.collectTags) return '-';
const tags = record.collectTags.split(',').filter(Boolean);
return (
<>
{tags.map((tag) => (
<Tag key={tag} color="blue">
{tag.trim()}
</Tag>
))}
</>
);
},
},
{
title: '收藏来源',
dataIndex: 'sourceType',
valueType: 'select',
align: 'center',
valueEnum: {
'1': '简历搜索',
'2': '投递记录',
'3': '邀约面试',
'4': '手动录入',
},
render: (_, record) => sourceTypeMap[record.sourceType || ''] || '-',
},
{
title: '学历',
dataIndex: 'education',
valueType: 'select',
align: 'center',
valueEnum: educationEnum,
render: (_, record) => {
return <DictTag enums={educationEnum} value={record.education} />;
},
},
{
title: '区域',
dataIndex: 'area',
valueType: 'select',
align: 'center',
valueEnum: areaEnum,
render: (_, record) => {
return <DictTag enums={areaEnum} value={record.area} />;
},
},
{
title: '性别',
dataIndex: 'sex',
valueType: 'select',
align: 'center',
valueEnum: sexEnum,
render: (_, record) => {
return <DictTag enums={sexEnum} value={record.sex} />;
},
},
{
title: '收藏时间',
dataIndex: 'createTime',
valueType: 'dateTime',
align: 'center',
hideInSearch: true,
},
{
title: '操作',
hideInSearch: true,
align: 'center',
dataIndex: 'userId',
width: 280,
render: (_, record) => [
<Button
type="link"
size="small"
key="resume"
icon={<FileTextOutlined />}
onClick={() => navigate(`/usermgmt/appuser/resume/${record.userId}?readOnly=1`)}
>
</Button>,
<Button
type="link"
size="small"
key="invite-interview"
icon={<SendOutlined />}
hidden={!access.hasPerms('cms:interview:add')}
onClick={() => {
setCurrentRow(record);
setInviteVisible(true);
}}
>
</Button>,
<Button
type="link"
size="small"
key="cancel-collect"
icon={<StarFilled style={{ color: '#faad14' }} />}
hidden={!access.hasPerms('cms:hrTalentCollect:remove')}
onClick={() => handleCancelCollect(record)}
>
</Button>,
],
},
];
return (
<Fragment>
<div style={{ width: '100%', float: 'right' }}>
<ProTable<API.TalentCollect.ListRow>
search={{ labelWidth: 'auto' }}
actionRef={actionRef}
formRef={formTableRef}
rowKey="id"
key="talentCollect"
columns={columns}
request={(params) => {
const { current, pageSize, ...searchParams } = params;
const filteredParams: Record<string, any> = {};
Object.keys(searchParams).forEach((key) => {
const val = (searchParams as any)[key];
if (val !== undefined && val !== null && val !== '') {
filteredParams[key] = val;
}
});
return getHrTalentCollectList({
pageNum: current,
pageSize,
...filteredParams,
}).then((res: any) => {
const result = {
data: res.rows,
total: res.total,
success: true,
};
return result;
});
}}
/>
<InterviewInvite
open={inviteVisible}
userId={currentRow?.userId}
userName={currentRow?.name}
companyId={currentRow?.companyId}
onClose={(needRefresh) => {
setInviteVisible(false);
setCurrentRow(undefined);
if (needRefresh) {
actionRef.current?.reload();
}
}}
/>
</div>
</Fragment>
);
}
export default TalentCollectList;