feat: 新增户外招聘会企业退订功能
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
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:
@@ -0,0 +1,63 @@
|
|||||||
|
import React, { useRef } from 'react';
|
||||||
|
import { ActionType, ProColumns, ProTable } from '@ant-design/pro-components';
|
||||||
|
import { getCompanyUnsubscribes } from '@/services/jobportal/outdoorFairDetail';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
fairId: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
const CompanyUnsubscribeTab: React.FC<Props> = ({ fairId }) => {
|
||||||
|
const actionRef = useRef<ActionType>();
|
||||||
|
|
||||||
|
const columns: ProColumns<API.OutdoorFairDetail.CompanyUnsubscribe>[] = [
|
||||||
|
{
|
||||||
|
title: '企业名称',
|
||||||
|
dataIndex: 'companyName',
|
||||||
|
ellipsis: true,
|
||||||
|
order: 1,
|
||||||
|
},
|
||||||
|
{ title: '联系人', dataIndex: 'contactPerson', width: 120, hideInSearch: true },
|
||||||
|
{ title: '联系电话', dataIndex: 'contactPhone', width: 150, hideInSearch: true },
|
||||||
|
{
|
||||||
|
title: '退订原因',
|
||||||
|
dataIndex: 'reason',
|
||||||
|
ellipsis: true,
|
||||||
|
hideInSearch: true,
|
||||||
|
render: (_, record) => <span title={record.reason}>{record.reason}</span>,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '退订时间',
|
||||||
|
dataIndex: 'unsubscribeTime',
|
||||||
|
valueType: 'dateTime',
|
||||||
|
width: 180,
|
||||||
|
hideInSearch: true,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ProTable<API.OutdoorFairDetail.CompanyUnsubscribe>
|
||||||
|
headerTitle="企业退订记录"
|
||||||
|
actionRef={actionRef}
|
||||||
|
rowKey="id"
|
||||||
|
columns={columns}
|
||||||
|
search={{ labelWidth: 'auto' }}
|
||||||
|
options={false}
|
||||||
|
scroll={{ x: 'max-content' }}
|
||||||
|
pagination={{ pageSize: 10 }}
|
||||||
|
request={async (params) => {
|
||||||
|
const res = await getCompanyUnsubscribes(fairId, {
|
||||||
|
current: params.current,
|
||||||
|
pageSize: params.pageSize,
|
||||||
|
companyName: params.companyName,
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
data: res.rows || [],
|
||||||
|
total: res.total || 0,
|
||||||
|
success: res.code === 200,
|
||||||
|
};
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CompanyUnsubscribeTab;
|
||||||
@@ -9,6 +9,7 @@ import FairInfoTab from './components/FairInfoTab';
|
|||||||
import BoothTab from './components/BoothTab';
|
import BoothTab from './components/BoothTab';
|
||||||
import ParticipatingCompaniesTab from './components/ParticipatingCompaniesTab';
|
import ParticipatingCompaniesTab from './components/ParticipatingCompaniesTab';
|
||||||
import ParticipatingJobsTab from './components/ParticipatingJobsTab';
|
import ParticipatingJobsTab from './components/ParticipatingJobsTab';
|
||||||
|
import CompanyUnsubscribeTab from './components/CompanyUnsubscribeTab';
|
||||||
import AttendeeTab from './components/AttendeeTab';
|
import AttendeeTab from './components/AttendeeTab';
|
||||||
import DeviceTab from './components/DeviceTab';
|
import DeviceTab from './components/DeviceTab';
|
||||||
|
|
||||||
@@ -42,6 +43,7 @@ const OutdoorFairDetail: React.FC = () => {
|
|||||||
const tabItems = [
|
const tabItems = [
|
||||||
{ key: 'fair-info', label: '招聘会管理' },
|
{ key: 'fair-info', label: '招聘会管理' },
|
||||||
{ key: 'participating-companies', label: '参会企业' },
|
{ key: 'participating-companies', label: '参会企业' },
|
||||||
|
{ key: 'company-unsubscribe', label: '企业退订' },
|
||||||
{ key: 'participating-jobs', label: '参会岗位' },
|
{ key: 'participating-jobs', label: '参会岗位' },
|
||||||
{ key: 'attendee', label: '参会人员管理' },
|
{ key: 'attendee', label: '参会人员管理' },
|
||||||
{ key: 'device', label: '设备管理' },
|
{ key: 'device', label: '设备管理' },
|
||||||
@@ -86,6 +88,8 @@ const OutdoorFairDetail: React.FC = () => {
|
|||||||
return <BoothTab fairId={fairId} fairInfo={fairInfo} />;
|
return <BoothTab fairId={fairId} fairInfo={fairInfo} />;
|
||||||
case 'participating-companies':
|
case 'participating-companies':
|
||||||
return <ParticipatingCompaniesTab fairId={fairId} />;
|
return <ParticipatingCompaniesTab fairId={fairId} />;
|
||||||
|
case 'company-unsubscribe':
|
||||||
|
return <CompanyUnsubscribeTab fairId={fairId} />;
|
||||||
case 'participating-jobs':
|
case 'participating-jobs':
|
||||||
return <ParticipatingJobsTab fairId={fairId} />;
|
return <ParticipatingJobsTab fairId={fairId} />;
|
||||||
case 'attendee':
|
case 'attendee':
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
||||||
import { useAccess, history, useModel } from '@umijs/max';
|
import { useAccess, history, useModel } from '@umijs/max';
|
||||||
import { Button, message, Modal, QRCode, Tag, Typography } from 'antd';
|
import { Button, Form, Input, message, Modal, QRCode, Tag, Typography } from 'antd';
|
||||||
import { ActionType, PageContainer, ProColumns, ProTable } from '@ant-design/pro-components';
|
import { ActionType, PageContainer, ProColumns, ProTable } from '@ant-design/pro-components';
|
||||||
import {
|
import {
|
||||||
PlusOutlined,
|
PlusOutlined,
|
||||||
@@ -18,6 +18,7 @@ import {
|
|||||||
deleteOutdoorFair,
|
deleteOutdoorFair,
|
||||||
addOutdoorFairDictOption,
|
addOutdoorFairDictOption,
|
||||||
signupOutdoorFair,
|
signupOutdoorFair,
|
||||||
|
unsubscribeOutdoorFair,
|
||||||
getMyOutdoorFairQrCode,
|
getMyOutdoorFairQrCode,
|
||||||
getOutdoorFairMiniProgramQrCode,
|
getOutdoorFairMiniProgramQrCode,
|
||||||
exportOutdoorFair,
|
exportOutdoorFair,
|
||||||
@@ -63,6 +64,10 @@ const OutdoorFairList: React.FC = () => {
|
|||||||
const [miniProgramQrLoadingFairId, setMiniProgramQrLoadingFairId] = useState<number>();
|
const [miniProgramQrLoadingFairId, setMiniProgramQrLoadingFairId] = useState<number>();
|
||||||
const [rejectReasonModalOpen, setRejectReasonModalOpen] = useState(false);
|
const [rejectReasonModalOpen, setRejectReasonModalOpen] = useState(false);
|
||||||
const [rejectReason, setRejectReason] = useState('');
|
const [rejectReason, setRejectReason] = useState('');
|
||||||
|
const [unsubscribeModalOpen, setUnsubscribeModalOpen] = useState(false);
|
||||||
|
const [unsubscribeFair, setUnsubscribeFair] = useState<OutdoorFairItem | null>(null);
|
||||||
|
const [unsubscribeSubmitting, setUnsubscribeSubmitting] = useState(false);
|
||||||
|
const [unsubscribeForm] = Form.useForm();
|
||||||
const [companyDetailFair, setCompanyDetailFair] = useState<OutdoorFairItem | null>(null);
|
const [companyDetailFair, setCompanyDetailFair] = useState<OutdoorFairItem | null>(null);
|
||||||
const [companyBoothFair, setCompanyBoothFair] = useState<OutdoorFairItem | null>(null);
|
const [companyBoothFair, setCompanyBoothFair] = useState<OutdoorFairItem | null>(null);
|
||||||
const [fairTypeValueEnum, setFairTypeValueEnum] = useState<Record<string, any>>({});
|
const [fairTypeValueEnum, setFairTypeValueEnum] = useState<Record<string, any>>({});
|
||||||
@@ -234,6 +239,39 @@ const OutdoorFairList: React.FC = () => {
|
|||||||
setRejectReasonModalOpen(true);
|
setRejectReasonModalOpen(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const openUnsubscribe = (record: OutdoorFairItem) => {
|
||||||
|
setUnsubscribeFair(record);
|
||||||
|
unsubscribeForm.resetFields();
|
||||||
|
setUnsubscribeModalOpen(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleUnsubscribe = async () => {
|
||||||
|
let values: { reason: string };
|
||||||
|
try {
|
||||||
|
values = await unsubscribeForm.validateFields();
|
||||||
|
} catch {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!unsubscribeFair) return;
|
||||||
|
setUnsubscribeSubmitting(true);
|
||||||
|
try {
|
||||||
|
const res = await unsubscribeOutdoorFair(unsubscribeFair.id, values.reason);
|
||||||
|
if (res.code === 200) {
|
||||||
|
message.success('退订成功');
|
||||||
|
setUnsubscribeModalOpen(false);
|
||||||
|
setUnsubscribeFair(null);
|
||||||
|
unsubscribeForm.resetFields();
|
||||||
|
actionRef.current?.reload();
|
||||||
|
} else {
|
||||||
|
message.error(res.msg || '退订失败');
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
message.error('退订失败,请稍后重试');
|
||||||
|
} finally {
|
||||||
|
setUnsubscribeSubmitting(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const openCompanyDetail = (record: OutdoorFairItem) => {
|
const openCompanyDetail = (record: OutdoorFairItem) => {
|
||||||
setCompanyDetailFair(record);
|
setCompanyDetailFair(record);
|
||||||
};
|
};
|
||||||
@@ -448,6 +486,20 @@ const OutdoorFairList: React.FC = () => {
|
|||||||
查看报名岗位
|
查看报名岗位
|
||||||
</Button>
|
</Button>
|
||||||
) : null,
|
) : null,
|
||||||
|
isEnterprise &&
|
||||||
|
record.signedUp &&
|
||||||
|
record.reviewStatus === '1' &&
|
||||||
|
access.hasPerms('cms:outdoorFair:unsubscribe') ? (
|
||||||
|
<Button
|
||||||
|
key="unsubscribe"
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
danger
|
||||||
|
onClick={() => openUnsubscribe(record)}
|
||||||
|
>
|
||||||
|
退订
|
||||||
|
</Button>
|
||||||
|
) : null,
|
||||||
isEnterprise ? (
|
isEnterprise ? (
|
||||||
<Button
|
<Button
|
||||||
key="companyDetail"
|
key="companyDetail"
|
||||||
@@ -683,6 +735,31 @@ const OutdoorFairList: React.FC = () => {
|
|||||||
{rejectReason}
|
{rejectReason}
|
||||||
</Typography.Paragraph>
|
</Typography.Paragraph>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
<Modal
|
||||||
|
title={unsubscribeFair ? `退订招聘会 — ${unsubscribeFair.title}` : '退订招聘会'}
|
||||||
|
open={unsubscribeModalOpen}
|
||||||
|
destroyOnClose
|
||||||
|
confirmLoading={unsubscribeSubmitting}
|
||||||
|
onOk={handleUnsubscribe}
|
||||||
|
okText="确认退订"
|
||||||
|
cancelText="取消"
|
||||||
|
onCancel={() => {
|
||||||
|
if (unsubscribeSubmitting) return;
|
||||||
|
setUnsubscribeModalOpen(false);
|
||||||
|
setUnsubscribeFair(null);
|
||||||
|
unsubscribeForm.resetFields();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Form form={unsubscribeForm} layout="vertical">
|
||||||
|
<Form.Item
|
||||||
|
name="reason"
|
||||||
|
label="退订原因"
|
||||||
|
rules={[{ required: true, whitespace: true, message: '请填写退订原因' }]}
|
||||||
|
>
|
||||||
|
<Input.TextArea rows={5} maxLength={500} showCount placeholder="请说明退订原因" />
|
||||||
|
</Form.Item>
|
||||||
|
</Form>
|
||||||
|
</Modal>
|
||||||
<CompanyFairDetailModal
|
<CompanyFairDetailModal
|
||||||
fair={companyDetailFair}
|
fair={companyDetailFair}
|
||||||
open={!!companyDetailFair}
|
open={!!companyDetailFair}
|
||||||
|
|||||||
@@ -321,6 +321,17 @@ export async function signupOutdoorFair(fairId: number) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 当前企业退订已审核通过的户外招聘会。 */
|
||||||
|
export async function unsubscribeOutdoorFair(fairId: number, reason: string) {
|
||||||
|
return request<{ code: number; msg?: string }>(
|
||||||
|
`${CMS_OUTDOOR_FAIR_BASE}/${fairId}/company/unsubscribe`,
|
||||||
|
{
|
||||||
|
method: 'POST',
|
||||||
|
data: { reason },
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取当前企业户外招聘会二维码
|
* 获取当前企业户外招聘会二维码
|
||||||
* GET /api/cms/outdoor-fair/{fairId}/company/qrcode
|
* GET /api/cms/outdoor-fair/{fairId}/company/qrcode
|
||||||
|
|||||||
@@ -1027,6 +1027,26 @@ export async function getParticipatingCompanies(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 获取招聘会企业退订记录。 */
|
||||||
|
export async function getCompanyUnsubscribes(
|
||||||
|
fairId: number,
|
||||||
|
params?: {
|
||||||
|
current?: number;
|
||||||
|
pageSize?: number;
|
||||||
|
companyName?: string;
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
return request<{
|
||||||
|
code: number;
|
||||||
|
msg?: string;
|
||||||
|
total: number;
|
||||||
|
rows: API.OutdoorFairDetail.CompanyUnsubscribe[];
|
||||||
|
}>(`/api/cms/outdoor-fair/${fairId}/company-unsubscribes`, {
|
||||||
|
method: 'GET',
|
||||||
|
params,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/** 分页获取招聘会参会岗位,可按企业懒加载。 */
|
/** 分页获取招聘会参会岗位,可按企业懒加载。 */
|
||||||
export async function getParticipatingJobs(
|
export async function getParticipatingJobs(
|
||||||
fairId: number,
|
fairId: number,
|
||||||
|
|||||||
12
src/types/jobfair/outdoorFairDetail.d.ts
vendored
12
src/types/jobfair/outdoorFairDetail.d.ts
vendored
@@ -34,6 +34,18 @@ declare namespace API.OutdoorFairDetail {
|
|||||||
jobList?: PostedJob[];
|
jobList?: PostedJob[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 企业退订记录 */
|
||||||
|
export interface CompanyUnsubscribe {
|
||||||
|
id: number;
|
||||||
|
fairId: number;
|
||||||
|
companyId: number;
|
||||||
|
companyName: string;
|
||||||
|
contactPerson?: string;
|
||||||
|
contactPhone?: string;
|
||||||
|
reason: string;
|
||||||
|
unsubscribeTime: string;
|
||||||
|
}
|
||||||
|
|
||||||
/** 参会企业二维码信息 */
|
/** 参会企业二维码信息 */
|
||||||
export interface CompanyQrCodeInfo {
|
export interface CompanyQrCodeInfo {
|
||||||
fairId: number;
|
fairId: number;
|
||||||
|
|||||||
Reference in New Issue
Block a user