简历是否被查看功能开发
This commit is contained in:
42670
package-lock.json
generated
42670
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -94,6 +94,7 @@ const getStatusColor = (status?: string): string => {
|
|||||||
const statusMap: Record<string, string> = {
|
const statusMap: Record<string, string> = {
|
||||||
'已投递': 'blue',
|
'已投递': 'blue',
|
||||||
'已查看': 'green',
|
'已查看': 'green',
|
||||||
|
'未查看': 'orange',
|
||||||
'已通过': 'success',
|
'已通过': 'success',
|
||||||
'已拒绝': 'red',
|
'已拒绝': 'red',
|
||||||
'已面试': 'orange',
|
'已面试': 'orange',
|
||||||
@@ -101,6 +102,25 @@ const getStatusColor = (status?: string): string => {
|
|||||||
return statusMap[status] || 'blue';
|
return statusMap[status] || 'blue';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 根据 isView 获取状态文本和颜色
|
||||||
|
const getViewStatus = (job: API.ApplicationJob): { text: string; color: string } => {
|
||||||
|
// 优先使用已有的 status/statusText
|
||||||
|
if (job.status || job.statusText) {
|
||||||
|
return {
|
||||||
|
text: job.status || job.statusText || '已投递',
|
||||||
|
color: getStatusColor(job.status || job.statusText),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// 根据 isView 判断
|
||||||
|
if (job.isView === '1') {
|
||||||
|
return { text: '简历已被查看', color: 'green' };
|
||||||
|
}
|
||||||
|
if (job.isView === '0') {
|
||||||
|
return { text: '简历未被查看', color: 'orange' };
|
||||||
|
}
|
||||||
|
return { text: '已投递', color: 'blue' };
|
||||||
|
};
|
||||||
|
|
||||||
const ApplicationsPage: React.FC = () => {
|
const ApplicationsPage: React.FC = () => {
|
||||||
const [applications, setApplications] = useState<API.ApplicationJob[]>([]);
|
const [applications, setApplications] = useState<API.ApplicationJob[]>([]);
|
||||||
const [loading, setLoading] = useState<boolean>(false);
|
const [loading, setLoading] = useState<boolean>(false);
|
||||||
@@ -223,8 +243,8 @@ const ApplicationsPage: React.FC = () => {
|
|||||||
</Col>
|
</Col>
|
||||||
<Col span={6}>
|
<Col span={6}>
|
||||||
<div className="job-status">
|
<div className="job-status">
|
||||||
<Tag color={getStatusColor(job.status || job.statusText)}>
|
<Tag color={getViewStatus(job).color}>
|
||||||
{job.status || job.statusText || '已投递'}
|
{getViewStatus(job).text}
|
||||||
</Tag>
|
</Tag>
|
||||||
</div>
|
</div>
|
||||||
</Col>
|
</Col>
|
||||||
|
|||||||
@@ -7,12 +7,13 @@ import {
|
|||||||
ProFormTextArea,
|
ProFormTextArea,
|
||||||
ProDescriptions,
|
ProDescriptions,
|
||||||
} from '@ant-design/pro-components';
|
} from '@ant-design/pro-components';
|
||||||
import { Form, Button, Input } from 'antd';
|
import { Form, Button, Input, TreeSelect } from 'antd';
|
||||||
import { PlusOutlined, MinusCircleOutlined } from '@ant-design/icons';
|
import { PlusOutlined, MinusCircleOutlined } from '@ant-design/icons';
|
||||||
import React, { useEffect, useRef, useState } from 'react';
|
import React, { useEffect, useRef, useState } from 'react';
|
||||||
import { DictValueEnumObj } from '@/components/DictTag';
|
import { DictValueEnumObj } from '@/components/DictTag';
|
||||||
import { getCmsCompanyList } from '@/services/company/list';
|
import { getCmsCompanyList } from '@/services/company/list';
|
||||||
import { getCmsJobDetail } from '@/services/Management/list';
|
import { getCmsJobDetail } from '@/services/Management/list';
|
||||||
|
import { getJobTitleTreeSelect } from '@/services/common/jobTitle';
|
||||||
|
|
||||||
export type ListFormProps = {
|
export type ListFormProps = {
|
||||||
onCancel: (flag?: boolean, formVals?: unknown) => void;
|
onCancel: (flag?: boolean, formVals?: unknown) => void;
|
||||||
@@ -39,6 +40,7 @@ const listEdit: React.FC<ListFormProps> = (props) => {
|
|||||||
const companyNameMap = useRef<Record<number, string>>({});
|
const companyNameMap = useRef<Record<number, string>>({});
|
||||||
const [jobDetail, setJobDetail] = useState<API.ManagementList.Manage | null>(null);
|
const [jobDetail, setJobDetail] = useState<API.ManagementList.Manage | null>(null);
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
|
const [jobCategoryTreeData, setJobCategoryTreeData] = useState<any[]>([]);
|
||||||
const { educationEnum, experienceEnum, areaEnum, jobTypeEnum } = props;
|
const { educationEnum, experienceEnum, areaEnum, jobTypeEnum } = props;
|
||||||
const { mode = props.values ? 'edit' : 'create' } = props;
|
const { mode = props.values ? 'edit' : 'create' } = props;
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -50,6 +52,10 @@ const listEdit: React.FC<ListFormProps> = (props) => {
|
|||||||
jobLocationAreaCode: String(props.values.jobLocationAreaCode || ''),
|
jobLocationAreaCode: String(props.values.jobLocationAreaCode || ''),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
// 加载岗位标签树数据
|
||||||
|
getJobTitleTreeSelect().then((res) => {
|
||||||
|
setJobCategoryTreeData(res.data || []);
|
||||||
|
}).catch(() => {});
|
||||||
}
|
}
|
||||||
}, [form, props.values?.jobId,props.open]);
|
}, [form, props.values?.jobId,props.open]);
|
||||||
|
|
||||||
@@ -110,6 +116,7 @@ const listEdit: React.FC<ListFormProps> = (props) => {
|
|||||||
contactPersonPhone: item.contactPersonPhone,
|
contactPersonPhone: item.contactPersonPhone,
|
||||||
position: item.position,
|
position: item.position,
|
||||||
})),
|
})),
|
||||||
|
jobCategory: values.jobCategory,
|
||||||
};
|
};
|
||||||
if (mode === 'edit' && values.jobId) {
|
if (mode === 'edit' && values.jobId) {
|
||||||
payload.jobId = values.jobId;
|
payload.jobId = values.jobId;
|
||||||
@@ -161,6 +168,7 @@ const listEdit: React.FC<ListFormProps> = (props) => {
|
|||||||
label="岗位类型"
|
label="岗位类型"
|
||||||
valueEnum={jobTypeEnum}
|
valueEnum={jobTypeEnum}
|
||||||
/>
|
/>
|
||||||
|
<ProDescriptions.Item dataIndex="jobCategory" label="岗位标签" />
|
||||||
<ProDescriptions.Item
|
<ProDescriptions.Item
|
||||||
dataIndex="description"
|
dataIndex="description"
|
||||||
label="岗位描述"
|
label="岗位描述"
|
||||||
@@ -390,6 +398,21 @@ const listEdit: React.FC<ListFormProps> = (props) => {
|
|||||||
placeholder="请选择类型"
|
placeholder="请选择类型"
|
||||||
rules={[{ required: true, message: '请选择类型!' }]}
|
rules={[{ required: true, message: '请选择类型!' }]}
|
||||||
/>
|
/>
|
||||||
|
<ProForm.Item name="jobCategory" label="岗位标签" rules={[{ required: true, message: '请选择岗位标签!' }]}>
|
||||||
|
<TreeSelect
|
||||||
|
showSearch
|
||||||
|
allowClear
|
||||||
|
treeData={jobCategoryTreeData}
|
||||||
|
fieldNames={{ label: 'label', value: 'id', children: 'children' }}
|
||||||
|
filterTreeNode={(inputValue, treeNode) => {
|
||||||
|
if (!inputValue) return true;
|
||||||
|
const title = String(treeNode.title ?? treeNode.label ?? '');
|
||||||
|
return title.toLowerCase().includes(inputValue.toLowerCase());
|
||||||
|
}}
|
||||||
|
placeholder="请搜索或选择岗位标签"
|
||||||
|
style={{ width: '100%' }}
|
||||||
|
/>
|
||||||
|
</ProForm.Item>
|
||||||
<ProFormText width="md" name="jobLocation" label="工作地点" placeholder="请输入工作地点" />
|
<ProFormText width="md" name="jobLocation" label="工作地点" placeholder="请输入工作地点" />
|
||||||
|
|
||||||
<ProFormTextArea
|
<ProFormTextArea
|
||||||
|
|||||||
@@ -239,6 +239,13 @@ function ManagementList() {
|
|||||||
align: 'center',
|
align: 'center',
|
||||||
hideInSearch: true,
|
hideInSearch: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: '岗位标签',
|
||||||
|
dataIndex: 'jobCategory',
|
||||||
|
valueType: 'text',
|
||||||
|
align: 'center',
|
||||||
|
hideInSearch: true,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: '岗位来源',
|
title: '岗位来源',
|
||||||
dataIndex: 'jobType',
|
dataIndex: 'jobType',
|
||||||
|
|||||||
@@ -68,6 +68,9 @@ function ManagementList() {
|
|||||||
});
|
});
|
||||||
if (resData.code === 200) {
|
if (resData.code === 200) {
|
||||||
message.success('修改成功');
|
message.success('修改成功');
|
||||||
|
// 先更新本地数据,保证 UI 即时响应且排序不跳变
|
||||||
|
record.hire = record.hire === '0' ? '2' : '0';
|
||||||
|
// 再从服务端同步数据,确保数据一致性
|
||||||
if (actionRef.current) {
|
if (actionRef.current) {
|
||||||
actionRef.current.reload();
|
actionRef.current.reload();
|
||||||
}
|
}
|
||||||
@@ -81,6 +84,12 @@ function ManagementList() {
|
|||||||
valueType: 'text',
|
valueType: 'text',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: '联系方式',
|
||||||
|
dataIndex: 'phone',
|
||||||
|
valueType: 'text',
|
||||||
|
align: 'center',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: '职位名称',
|
title: '职位名称',
|
||||||
dataIndex: 'jobName',
|
dataIndex: 'jobName',
|
||||||
@@ -102,8 +111,11 @@ function ManagementList() {
|
|||||||
{
|
{
|
||||||
title: '出生日期',
|
title: '出生日期',
|
||||||
dataIndex: 'birthDate',
|
dataIndex: 'birthDate',
|
||||||
valueType: 'text',
|
valueType: 'date',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
|
fieldProps: {
|
||||||
|
format: 'YYYY-MM-DD',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '学历要求',
|
title: '学历要求',
|
||||||
@@ -181,17 +193,33 @@ function ManagementList() {
|
|||||||
rowKey="applyId"
|
rowKey="applyId"
|
||||||
key="index"
|
key="index"
|
||||||
columns={columns}
|
columns={columns}
|
||||||
request={(params) =>
|
request={(params) => {
|
||||||
getCmsAppUserList({ ...params } as API.MobileUser.ListParams).then((res) => {
|
const { current, pageSize, ...searchParams } = params;
|
||||||
console.log(params);
|
// 过滤空值,避免空字符串干扰后端查询
|
||||||
|
const filteredParams: Record<string, any> = {};
|
||||||
|
Object.keys(searchParams).forEach((key) => {
|
||||||
|
const val = searchParams[key];
|
||||||
|
if (val !== undefined && val !== null && val !== '') {
|
||||||
|
filteredParams[key] = val;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return getCmsAppUserList({
|
||||||
|
pageNum: current,
|
||||||
|
pageSize,
|
||||||
|
...filteredParams,
|
||||||
|
// 服务端稳定排序:按申请时间倒序(a = job_apply 表)
|
||||||
|
orderByColumn: 'a.create_time',
|
||||||
|
isAsc: 'desc',
|
||||||
|
} as API.MobileUser.ListParams).then((res) => {
|
||||||
|
console.log('searchParams:', filteredParams, 'total:', res.total);
|
||||||
const result = {
|
const result = {
|
||||||
data: res.rows,
|
data: res.rows,
|
||||||
total: res.total,
|
total: res.total,
|
||||||
success: true,
|
success: true,
|
||||||
};
|
};
|
||||||
return result;
|
return result;
|
||||||
})
|
});
|
||||||
}
|
}}
|
||||||
toolBarRender={() => [
|
toolBarRender={() => [
|
||||||
<Button
|
<Button
|
||||||
type="primary"
|
type="primary"
|
||||||
|
|||||||
2
src/types/Management/list.d.ts
vendored
2
src/types/Management/list.d.ts
vendored
@@ -30,6 +30,7 @@ declare namespace API.ManagementList {
|
|||||||
jobType?: string;
|
jobType?: string;
|
||||||
jobContactList?: ContactPerson[];
|
jobContactList?: ContactPerson[];
|
||||||
createTime?: string;
|
createTime?: string;
|
||||||
|
jobCategory?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AddParams {
|
export interface AddParams {
|
||||||
@@ -56,6 +57,7 @@ declare namespace API.ManagementList {
|
|||||||
isPublish?: number;
|
isPublish?: number;
|
||||||
jobType?: string;
|
jobType?: string;
|
||||||
jobContactList?: ContactPerson[];
|
jobContactList?: ContactPerson[];
|
||||||
|
jobCategory?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ListParams {
|
export interface ListParams {
|
||||||
|
|||||||
1
src/types/jobportal/user.d.ts
vendored
1
src/types/jobportal/user.d.ts
vendored
@@ -109,6 +109,7 @@ declare namespace API {
|
|||||||
vacancies?: number;
|
vacancies?: number;
|
||||||
view?: number;
|
view?: number;
|
||||||
companyCardId?: number;
|
companyCardId?: number;
|
||||||
|
isView?: string; // 简历是否被查看:0-未查看,1-已查看
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MessageListResult {
|
export interface MessageListResult {
|
||||||
|
|||||||
2
src/types/mobileusers/list.d.ts
vendored
2
src/types/mobileusers/list.d.ts
vendored
@@ -41,5 +41,7 @@ declare namespace API.MobileUser {
|
|||||||
birthDate?: string;
|
birthDate?: string;
|
||||||
education?: string;
|
education?: string;
|
||||||
politicalAffiliation?: string;
|
politicalAffiliation?: string;
|
||||||
|
phone?: string;
|
||||||
|
jobName?: string;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user