flat: 合并

This commit is contained in:
史典卓
2025-04-23 15:47:46 +08:00
8 changed files with 784 additions and 858 deletions

View File

@@ -1,64 +1,77 @@
html, html,
body, body,
#root { #root {
height: 100%; height: 100%;
margin: 0; margin: 0;
padding: 0; padding: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial,
'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol',
'Noto Color Emoji'; 'Noto Color Emoji';
} }
.colorWeak { .colorWeak {
filter: invert(80%); filter: invert(80%);
} }
.ant-layout { .ant-layout {
min-height: 100vh !important; min-height: 100vh !important;
} }
.ant-pro-sider.ant-layout-sider.ant-pro-sider-fixed { .ant-pro-sider.ant-layout-sider.ant-pro-sider-fixed {
left: unset; left: unset;
} }
.ant-table-row { .ant-table-cell .ant-table-row-expand-icon {
&-level-1 .ant-table-cell:first-child { vertical-align: middle;
padding-left: 24px !important; margin-right: 8px;
} }
&-level-2 .ant-table-cell:first-child { .ant-table-row {
padding-left: 48px !important; &-level-0 .ant-table-cell:first-child {
} padding-left: 16px !important;
// 可根据需要添加更多层级 }
} &-level-1 .ant-table-cell:first-child {
canvas { padding-left: 40px !important;
display: block; }
} &-level-2 .ant-table-cell:first-child {
padding-left: 64px !important;
body { }
text-rendering: optimizeLegibility; }
-webkit-font-smoothing: antialiased; .ant-table-row .ant-table-cell:first-child {
-moz-osx-font-smoothing: grayscale; display: flex;
} align-items: center;
}
ul, .ant-table-row-level-2 .ant-table-row-expand-icon {
ol { display: none;
list-style: none; }
} canvas {
display: block;
@media (max-width: 768px) { }
.ant-table {
width: 100%; body {
overflow-x: auto; text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
&-thead > tr, -moz-osx-font-smoothing: grayscale;
&-tbody > tr { }
> th,
> td { ul,
white-space: pre; ol {
list-style: none;
> span { }
display: block;
} @media (max-width: 768px) {
} .ant-table {
} width: 100%;
} overflow-x: auto;
}
&-thead > tr,
&-tbody > tr {
> th,
> td {
white-space: pre;
> span {
display: block;
}
}
}
}
}

View File

@@ -1,189 +1,190 @@
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
import { import {
ModalForm, ModalForm,
ProForm, ProForm,
ProFormDigit, ProFormDigit,
ProFormRadio, ProFormRadio,
ProFormTreeSelect, ProFormTreeSelect,
ProFormText, ProFormText,
ProDescriptions, ProDescriptions,
} from '@ant-design/pro-components'; } from '@ant-design/pro-components';
import { Form } from 'antd'; import { Form } from 'antd';
import { DictValueEnumObj } from '@/components/DictTag'; import { DictValueEnumObj } from '@/components/DictTag';
import { FormattedMessage } from '@@/exports'; import { FormattedMessage } from '@@/exports';
import { getCmsIndustryTreeList } from '@/services/classify/industry'; // 修改导入为 getCmsIndustryTreeList import { getCmsIndustryTreeList } from '@/services/classify/industry'; // 修改导入为 getCmsIndustryTreeList
interface IndustryDetail { interface IndustryDetail {
id?: number; id?: number;
industryName?: string; industryName?: string;
orderNum?: number; orderNum?: number;
status?: string; status?: string;
parentId?: number; parentId?: number;
parentName?: string; parentName?: string;
} }
export type ListFormProps = { export type ListFormProps = {
onCancel: (flag?: boolean, formVars?: unknown) => void; onCancel: (flag?: boolean, formVars?: unknown) => void;
onSubmit: (values: any) => Promise<void>; onSubmit: (values: any) => Promise<void>;
open: boolean; open: boolean;
values?: Partial<IndustryDetail>; values?: Partial<IndustryDetail>;
industryStatusEnum: DictValueEnumObj; industryStatusEnum: DictValueEnumObj;
mode?: 'view' | 'edit' | 'create'; mode?: 'view' | 'edit' | 'create';
}; };
const listEdit: React.FC<ListFormProps> = (props) => { const listEdit: React.FC<ListFormProps> = (props) => {
const [form] = Form.useForm(); const [form] = Form.useForm<IndustryDetail>();
const { industryStatusEnum, mode = props.values ? 'edit' : 'create', values } = props; const { industryStatusEnum, mode = props.values ? 'edit' : 'create', values } = props;
useEffect(() => { useEffect(() => {
form.resetFields(); form.resetFields();
if (values) { if (values) {
form.setFieldsValue({ form.setFieldsValue({
...values, ...values,
parentId: values?.parentId ?? 0 parentId: values?.parentId ?? 0
}); });
} }
}, [form, values?.id]); }, [form, values?.id]);
const getSafeDetailData = (data?: Partial<IndustryDetail>): IndustryDetail => { const getSafeDetailData = (data?: Partial<IndustryDetail>): IndustryDetail => {
return { return {
id: data?.id ?? 0, id: data?.id ?? 0,
industryName: data?.industryName ?? '', industryName: data?.industryName ?? '',
orderNum: data?.orderNum ?? 0, orderNum: data?.orderNum ?? 0,
parentId: data?.parentId ?? 0, parentId: data?.parentId ?? 0,
parentName: data?.parentName ?? '顶级节点', parentName: data?.parentName ?? '顶级节点',
status: data?.status ?? '0', status: data?.status ?? '0',
}; };
}; };
const handleCancel = () => { const handleCancel = () => {
props.onCancel(); props.onCancel();
form.resetFields(); form.resetFields();
}; };
const handleFinish = async (values: Record<string, any>) => { const handleFinish = async (values: Record<string, any>) => {
const submitValues = { const submitValues = {
...values, ...values,
parentId: values.parentId === 0 ? undefined : values.parentId parentId: values.parentId === 0 ? undefined : values.parentId
}; };
props.onSubmit(submitValues); props.onSubmit(submitValues);
}; };
// 获取行业树数据 // 获取行业树数据
const fetchIndustryTree = async () => { const fetchIndustryTree = async () => {
const res = await getCmsIndustryTreeList(); const res = await getCmsIndustryTreeList();
return [ return [
{ {
id: 0, id: 0,
label: '顶级节点', label: '顶级节点',
value: 0, value: 0,
children: res.data || [] children: res.data || []
} }
]; ];
}; };
if (mode === 'view') { if (mode === 'view') {
return ( return (
<ModalForm <ModalForm
title="行业详情" title="行业详情"
open={props.open} open={props.open}
width={800} width={800}
modalProps={{ modalProps={{
destroyOnClose: true, destroyOnClose: true,
onCancel: () => handleCancel(), onCancel: () => handleCancel(),
footer: null, footer: null,
}} }}
submitter={false} submitter={false}
> >
<ProDescriptions<IndustryDetail> <ProDescriptions<IndustryDetail>
column={1} column={1}
dataSource={getSafeDetailData(values)} dataSource={getSafeDetailData(values)}
loading={!values} loading={!values}
> >
<ProDescriptions.Item label="行业ID" dataIndex="id" /> <ProDescriptions.Item label="行业ID" dataIndex="id" />
<ProDescriptions.Item label="行业名称" dataIndex="industryName" /> <ProDescriptions.Item label="行业名称" dataIndex="industryName" />
<ProDescriptions.Item label="显示顺序" dataIndex="orderNum" /> <ProDescriptions.Item label="显示顺序" dataIndex="orderNum" />
<ProDescriptions.Item <ProDescriptions.Item
label="父行业" label="父行业"
dataIndex="parentName" dataIndex="parentName"
renderText={(text, record) => record.parentId === 0 ? '顶级节点' : text} renderText={(text, record) => record.parentId === 0 ? '顶级节点' : text}
/> />
<ProDescriptions.Item <ProDescriptions.Item
label="行业状态" label="行业状态"
dataIndex="status" dataIndex="status"
valueEnum={industryStatusEnum} valueEnum={industryStatusEnum}
/> />
</ProDescriptions> </ProDescriptions>
</ModalForm> </ModalForm>
); );
} }
return ( return (
<ModalForm <ModalForm
title={`${values ? '编辑' : '新增'}行业`} title={`${values ? '编辑' : '新增'}行业`}
form={form} form={form}
autoFocusFirstInput autoFocusFirstInput
open={props.open} open={props.open}
modalProps={{ modalProps={{
destroyOnClose: true, destroyOnClose: true,
onCancel: () => handleCancel(), onCancel: () => handleCancel(),
}} }}
submitTimeout={2000} submitTimeout={2000}
onFinish={handleFinish} onFinish={handleFinish}
> >
<ProFormDigit name="id" disabled hidden={true} /> <ProFormDigit name="id" disabled hidden={true} />
<ProForm.Group> <ProForm.Group>
<ProFormText <ProFormText
width="md" width="md"
name="industryName" name="industryName"
label="行业名称" label="行业名称"
placeholder="请输入行业名称" placeholder="请输入行业名称"
rules={[{ required: true, message: '请输入行业名称' }]} rules={[{ required: true, message: '请输入行业名称' }]}
/> />
<ProFormDigit <ProFormDigit
label="显示顺序" label="显示顺序"
name="orderNum" name="orderNum"
width="md" width="md"
min={0} min={0}
placeholder="请输入显示顺序" placeholder="请输入显示顺序"
rules={[{ required: true, message: '请输入显示顺序' }]} rules={[{ required: true, message: '请输入显示顺序' }]}
/> />
</ProForm.Group> </ProForm.Group>
<ProForm.Group> <ProForm.Group>
<ProFormTreeSelect <ProFormTreeSelect
name="parentId" name="parentId"
label="父行业" label="父行业"
placeholder="请选择父行业" placeholder="请选择父行业"
allowClear allowClear
width="md" width="md"
request={fetchIndustryTree} request={fetchIndustryTree}
fieldProps={{ fieldProps={{
treeDefaultExpandAll: true, virtual:true,
showSearch: true, treeDefaultExpandAll: true,
filterTreeNode: true, showSearch: true,
fieldNames: { filterTreeNode: true,
label: 'label', fieldNames: {
value: 'id', label: 'label',
children: 'children', value: 'id',
}, children: 'children',
dropdownStyle: { },
maxHeight: 400, dropdownStyle: {
overflow: 'auto', maxHeight: 400,
}, overflow: 'auto',
}} },
rules={[{ required: true, message: '请选择父行业' }]} }}
/> rules={[{ required: true, message: '请选择父行业' }]}
<ProFormRadio.Group />
valueEnum={industryStatusEnum} <ProFormRadio.Group
name="status" valueEnum={industryStatusEnum}
label="行业状态" name="status"
width="md" label="行业状态"
initialValue="0" width="md"
rules={[{ required: true, message: '请选择行业状态' }]} initialValue="0"
/> rules={[{ required: true, message: '请选择行业状态' }]}
</ProForm.Group> />
</ModalForm> </ProForm.Group>
); </ModalForm>
}; );
};
export default listEdit; export default listEdit;

View File

@@ -1,159 +1,159 @@
import React,{ useEffect,useState } from 'react'; import React,{ useEffect,useState } from 'react';
import { import {
ModalForm, ModalForm,
ProForm, ProForm,
ProFormDigit, ProFormDigit,
ProFormText, ProFormText,
ProFormTextArea, ProFormTextArea,
ProFormTreeSelect, ProFormTreeSelect,
ProFormSelect ProFormSelect
} from '@ant-design/pro-components'; } from '@ant-design/pro-components';
import { Form } from 'antd'; import { Form } from 'antd';
import { getCmsJobTitleList } from '@/services/classify/jobs'; import { getCmsJobTitleList } from '@/services/classify/jobs';
import { getDictValueEnum } from '@/services/system/dict'; import { getDictValueEnum } from '@/services/system/dict';
// tree // tree
type JobListParams = API.ClassifyJobs.Params; type JobListParams = API.ClassifyJobs.Params;
export type ListFormProps = { export type ListFormProps = {
onCancel: (flag?: boolean, formVals?: unknown) => void; onCancel: (flag?: boolean, formVals?: unknown) => void;
onSubmit: (values: any) => Promise<void>; onSubmit: (values: any) => Promise<void>;
open: boolean; open: boolean;
values?: Partial<API.ClassifyJobs.Job>; values?: Partial<API.ClassifyJobs.Jobs>;
// jobGroupOptions: DictOptionType[]; // jobGroupOptions: DictOptionType[];
// statusOptions: DictValueEnumObj; // statusOptions: DictValueEnumObj;
}; };
const listEdit: React.FC<ListFormProps> = (props) => { const listEdit: React.FC<ListFormProps> = (props) => {
const [form] = Form.useForm(); const [form] = Form.useForm();
const [treeData, setTreeData] = useState<API.ClassifyJobs.Job[]>([]); const [treeData, setTreeData] = useState<API.ClassifyJobs.Jobs[]>([]);
const [statusOptions, setStatusOptions] = useState<Record<string, any>>({}); const [statusOptions, setStatusOptions] = useState<Record<string, any>>({});
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const buildTree = (data: API.ClassifyJobs.Job[], parentId: number = 0): API.ClassifyJobs.Job[] => { const buildTree = (data: API.ClassifyJobs.Jobs[], parentId: number = 0): API.ClassifyJobs.Jobs[] => {
return data return data
.filter(item => item.parentId === parentId) .filter(item => item.parentId === parentId)
.map(item => ({ .map(item => ({
...item, ...item,
children: buildTree(data, item.jobId), children: buildTree(data, item.jobId),
})); }));
}; };
useEffect(() => { useEffect(() => {
const fetchData = async () => { const fetchData = async () => {
const res = await getCmsJobTitleList({ const res = await getCmsJobTitleList({
tree: false, tree: false,
// 明确传递所有必要参数 // 明确传递所有必要参数
pageSize: 1000, // 确保获取全部数据 pageSize: 1000, // 确保获取全部数据
current: 1 current: 1
} as JobListParams); } as JobListParams);
setLoading(true); setLoading(true);
try { try {
// 获取状态枚举 // 获取状态枚举
const statusData = await getDictValueEnum('sys_jobs_status', true); const statusData = await getDictValueEnum('sys_jobs_status', true);
setStatusOptions(statusData); setStatusOptions(statusData);
// 获取岗位数据 // 获取岗位数据
const res = await getCmsJobTitleList({ tree: false } as JobListParams); const res = await getCmsJobTitleList({ tree: false } as JobListParams);
console.log('原始数据:', res.rows); console.log('原始数据:', res.rows);
const treeData = buildTree(res.rows || []); const treeData = buildTree(res.rows || []);
console.log('转换后的树形数据:', treeData); console.log('转换后的树形数据:', treeData);
setTreeData(treeData); setTreeData(treeData);
// 设置表单初始值 // 设置表单初始值
if (props.values) { if (props.values) {
form.setFieldsValue({ form.setFieldsValue({
...props.values, ...props.values,
parentId: props.values.parentId || undefined, parentId: props.values.parentId || undefined,
}); });
} }
} catch (error) { } catch (error) {
console.error('数据加载失败:', error); console.error('数据加载失败:', error);
} finally { } finally {
setLoading(false); setLoading(false);
} }
}; };
fetchData(); fetchData();
}, []); }, []);
const handleCancel = () => { const handleCancel = () => {
props.onCancel(); props.onCancel();
form.resetFields(); form.resetFields();
}; };
const handleFinish = async (values: Record<string, any>) => { const handleFinish = async (values: Record<string, any>) => {
await props.onSubmit(values); await props.onSubmit(values);
}; };
return ( return (
<ModalForm <ModalForm
title={`${props.values ? '编辑' : '新增'}企业`} title={`${props.values ? '编辑' : '新增'}企业`}
form={form} form={form}
autoFocusFirstInput autoFocusFirstInput
open={props.open} open={props.open}
width={600} width={600}
modalProps={{ modalProps={{
destroyOnClose: true, destroyOnClose: true,
onCancel: () => handleCancel(), onCancel: () => handleCancel(),
}} }}
submitTimeout={2000} submitTimeout={2000}
onFinish={handleFinish} onFinish={handleFinish}
> >
<ProFormDigit label="InputNumber" name="jobId" disabled hidden={true} /> <ProFormDigit label="InputNumber" name="jobId" disabled hidden={true} />
{/* 新增:父级岗位选择 */} {/* 新增:父级岗位选择 */}
<ProFormTreeSelect <ProFormTreeSelect
name="parentId" name="parentId"
label="父级岗位" label="父级岗位"
width="md" width="md"
placeholder="请选择父级岗位" placeholder="请选择父级岗位"
allowClear allowClear
fieldProps={{ fieldProps={{
treeData, treeData,
fieldNames: { label: 'jobName', value: 'jobId', children: 'children' }, fieldNames: { label: 'jobName', value: 'jobId', children: 'children' },
treeDefaultExpandAll: true, treeDefaultExpandAll: true,
showSearch: true, showSearch: true,
variant:'outlined', variant:'outlined',
dropdownStyle: { maxHeight: 400, overflow: 'auto' }, dropdownStyle: { maxHeight: 400, overflow: 'auto' },
filterTreeNode: (input, option) => filterTreeNode: (input, option) =>
String(option?.title ?? '').toLowerCase().includes(input.toLowerCase()) String(option?.title ?? '').toLowerCase().includes(input.toLowerCase())
}} }}
/> />
<ProForm.Group> <ProForm.Group>
<ProFormText width="md" name="jobname" label="单位名称" placeholder="请输入单位名称" /> <ProFormText width="md" name="jobname" label="单位名称" placeholder="请输入单位名称" />
<ProFormDigit <ProFormDigit
width="md" width="md"
name="orderNum" name="orderNum"
label="显示顺序" label="显示顺序"
placeholder="请输入显示顺序" placeholder="请输入显示顺序"
min={0} min={0}
fieldProps={{ precision: 0 }} fieldProps={{ precision: 0 }}
rules={[{ required: true, message: '请输入显示顺序' }]} rules={[{ required: true, message: '请输入显示顺序' }]}
/> />
</ProForm.Group> </ProForm.Group>
<ProFormSelect <ProFormSelect
name="status" name="status"
label="状态" label="状态"
width="md" width="md"
valueEnum={statusOptions} valueEnum={statusOptions}
placeholder="请选择状态" placeholder="请选择状态"
/> />
<ProForm.Group> <ProForm.Group>
<ProFormText width="md" name="code" label="信用代码" placeholder="请输入信用代码" /> <ProFormText width="md" name="code" label="信用代码" placeholder="请输入信用代码" />
<ProFormText width="md" name="industry" label="主要行业" placeholder="请输入主要行业" /> <ProFormText width="md" name="industry" label="主要行业" placeholder="请输入主要行业" />
</ProForm.Group> </ProForm.Group>
<ProForm.Group> <ProForm.Group>
<ProFormTextArea width="xl" name="location" label="单位地点" placeholder="请输入单位地点" /> <ProFormTextArea width="xl" name="location" label="单位地点" placeholder="请输入单位地点" />
</ProForm.Group> </ProForm.Group>
</ModalForm> </ModalForm>
); );
}; };
export default listEdit; export default listEdit;

View File

@@ -9,34 +9,6 @@ import { exportCmsJobTitleList, getCmsJobTitleList } from '@/services/classify/j
import { getDictValueEnum } from '@/services/system/dict'; import { getDictValueEnum } from '@/services/system/dict';
import DictTag from '@/components/DictTag'; import DictTag from '@/components/DictTag';
declare namespace API {
namespace ClassifyJobs {
interface Params {
tree?: boolean;
pageSize?: number;
current?: number;
jobName?: string;
status?: string;
}
interface Jobs {
jobId: number;
parentId: number;
jobName: string;
orderNum?: number;
status?: string;
createTime?: string;
parentName?: string;
children?: Jobs[];
depth?: number; // 添加这行
}
}
}
// params类型
type JobListParams = API.ClassifyJobs.Params & {
tree?: boolean;
};
const handleRemoveOne = async (jobId: string) => { const handleRemoveOne = async (jobId: string) => {
const hide = message.loading('正在删除'); const hide = message.loading('正在删除');
if (!jobId) return true; if (!jobId) return true;
@@ -74,16 +46,14 @@ const buildTree = (
parentId: number = 0, parentId: number = 0,
depth = 0, depth = 0,
): API.ClassifyJobs.Jobs[] => { ): API.ClassifyJobs.Jobs[] => {
return data const children = data
.filter((item) => item.parentId === parentId) .filter((item) => item.parentId === parentId)
.map((item) => { .map((item) => ({
const child = buildTree(data, item.jobId, depth + 1); ...item,
return { depth,
...item, children: buildTree(data, item.jobId, depth + 1),
depth, }));
children: child.length ? child : undefined, return children || [];
};
});
}; };
const ManagementList: React.FC = () => { const ManagementList: React.FC = () => {
@@ -107,13 +77,12 @@ const ManagementList: React.FC = () => {
title: '岗位名称', title: '岗位名称',
dataIndex: 'jobName', dataIndex: 'jobName',
align: 'center', align: 'left',
render: (text, record) => ( render: (text, record) => (
<span <span
style={{ style={{
paddingLeft: `${(record.depth || 0) * 20}px`, display: 'flex',
display: 'inline-block', alignItems: 'center',
width: '100%',
}} }}
> >
{text} {text}
@@ -144,67 +113,22 @@ const ManagementList: React.FC = () => {
return <DictTag enums={jobsStatusEnum} value={record.status} />; return <DictTag enums={jobsStatusEnum} value={record.status} />;
}, },
}, },
// {
// title: '操作',
// hideInSearch: true,
// align: 'center',
// dataIndex: 'jobId',
// width: 300,
// render: (_, record) => [
// <Button
// type="link"
// size="small"
// key="edit"
// icon={<FormOutlined />}
// hidden={!access.hasPerms('system:job:edit')}
// onClick={() => {
// setModalVisible(true);
// setCurrentRow(record);
// }}
// >
// 编辑
// </Button>,
// // <Button
// // type="link"
// // size="small"
// // danger
// // key="delete"
// // icon={<DeleteOutlined />}
// // hidden={!access.hasPerms('system:job:remove')}
// // onClick={async () => {
// // Modal.confirm({
// // title: '删除',
// // content: '确定删除该项吗?',
// // okText: '确认',
// // cancelText: '取消',
// // onOk: async () => {
// // if(record.jobId){
// // const success = await handleRemoveOne(record.jobId.toString());
//
// // if (success && actionRef.current) {
// // actionRef.current.reload();
// // }
// // }
// // },
// // });
// // }}
// // >
// // 删除
// // </Button>,
// ],
// },
]; ];
return ( return (
<Fragment> <Fragment>
<div style={{ width: '100%', float: 'right' }}> <div style={{ width: '100%', float: 'right' }}>
<ProTable<API.ClassifyJobs.Jobs> <ProTable<API.ClassifyJobs.Jobs>
// params 是需要自带的参数
// 这个参数优先级更高,会覆盖查询表单的参数
actionRef={actionRef} actionRef={actionRef}
formRef={formTableRef} formRef={formTableRef}
rowKey="jobId" rowKey="jobId"
key="index" key="index"
columns={columns} columns={columns}
expandable={{
childrenColumnName: 'children',
defaultExpandAllRows: true,
indentSize: 24,
rowExpandable: (record) => Array.isArray(record.children) && record.children.length > 0,
}}
search={{ search={{
labelWidth: 120, labelWidth: 120,
}} }}
@@ -215,7 +139,6 @@ const ManagementList: React.FC = () => {
pageSize: 1000, pageSize: 1000,
}); });
const treeData = buildTree(res.rows); const treeData = buildTree(res.rows);
console.log('完整树形结构:', JSON.stringify(treeData, null, 2));
return { return {
data: treeData, data: treeData,
total: res.total, total: res.total,
@@ -223,12 +146,6 @@ const ManagementList: React.FC = () => {
}; };
}} }}
pagination={false} pagination={false}
expandable={{
childrenColumnName: 'children',
defaultExpandAllRows: true,
indentSize: 30,
rowExpandable: (record) => !!record.children?.length,
}}
toolBarRender={() => [ toolBarRender={() => [
<Button <Button
type="primary" type="primary"

View File

@@ -1,207 +1,207 @@
import { import {
ModalForm, ModalForm,
ProForm, ProForm,
ProFormDigit, ProFormDigit,
ProFormSelect, ProFormSelect,
ProFormText, ProFormText,
ProFormTextArea, ProFormTextArea,
ProDescriptions, ProDescriptions,
} from '@ant-design/pro-components'; } from '@ant-design/pro-components';
import { Form } from 'antd'; import { Form } from 'antd';
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
import { DictValueEnumObj } from '@/components/DictTag'; import { DictValueEnumObj } from '@/components/DictTag';
import { getCmsCompanyList } from '@/services/company/list'; import { getCmsCompanyList } from '@/services/company/list';
export type ListFormProps = { export type ListFormProps = {
onCancel: (flag?: boolean, formVals?: unknown) => void; onCancel: (flag?: boolean, formVals?: unknown) => void;
onSubmit: (values: API.ManagementList.Manage) => Promise<void>; onSubmit: (values: API.ManagementList.Manage) => Promise<void>;
open: boolean; open: boolean;
values?: Partial<API.ManagementList.Manage>; values?: Partial<API.ManagementList.Manage>;
educationEnum: DictValueEnumObj; educationEnum: DictValueEnumObj;
experienceEnum: DictValueEnumObj; experienceEnum: DictValueEnumObj;
areaEnum: DictValueEnumObj; areaEnum: DictValueEnumObj;
mode?: 'view' | 'edit' | 'create'; mode?: 'view' | 'edit' | 'create';
}; };
const waitTime = (time: number = 100) => { const waitTime = (time: number = 100) => {
return new Promise((resolve) => { return new Promise((resolve) => {
setTimeout(() => { setTimeout(() => {
resolve(true); resolve(true);
}, time); }, time);
}); });
}; };
const listEdit: React.FC<ListFormProps> = (props) => { const listEdit: React.FC<ListFormProps> = (props) => {
const [form] = Form.useForm<{ name: string; company: string; companyName: number }>(); const [form] = Form.useForm<API.ManagementList.Manage>();
const { educationEnum, experienceEnum, areaEnum } = props; const { educationEnum, experienceEnum, areaEnum } = props;
const { mode = props.values ? 'edit' : 'create' } = props; const { mode = props.values ? 'edit' : 'create' } = props;
useEffect(() => { useEffect(() => {
form.resetFields(); if(props.open){
if (props.values) { form.resetFields();
form.setFieldsValue({ if (props.values) {
...props.values, form.setFieldsValue({
jobLocationAreaCode: String(props.values.jobLocationAreaCode || ''), ...props.values,
}); jobLocationAreaCode: String(props.values.jobLocationAreaCode || ''),
} });
}, [form, props.values?.jobID]); }
}
const handleCancel = () => { }, [form, props.values?.jobId,props.open]);
props.onCancel();
form.resetFields(); const handleCancel = () => {
}; props.onCancel();
form.resetFields();
const handleFinish = async (values: Record<string, any>) => { };
props.onSubmit(values as API.ManagementList.Manage);
}; const handleFinish = async (values: Record<string, any>) => {
props.onSubmit(values as API.ManagementList.Manage);
const handleChange = (_: string, value: any) => { };
form.setFieldValue('companyName', value.label);
}; const handleChange = (_: string, value: any) => {
if (mode === 'view') { form.setFieldValue('companyName', value.label);
return ( };
<ModalForm if (mode === 'view') {
title="岗位详情" return (
open={props.open} <ModalForm
width={800} title="岗位详情"
modalProps={{ open={props.open}
destroyOnClose: true, width={800}
onCancel: () => handleCancel(), modalProps={{
footer: null, destroyOnClose: true,
}} onCancel: () => handleCancel(),
submitter={false} footer: null,
> }}
<ProDescriptions<API.ManagementList.Manage> submitter={false}
column={2} >
dataSource={props.values || {}} <ProDescriptions<API.ManagementList.Manage>
> column={2}
<ProDescriptions.Item dataIndex="jobTitle" label="岗位名称" /> dataSource={props.values || {}}
<ProDescriptions.Item dataIndex="companyName" label="招聘公司" /> >
<ProDescriptions.Item dataIndex="minSalary" label="最低薪资(元/月)" /> <ProDescriptions.Item dataIndex="jobTitle" label="岗位名称" />
<ProDescriptions.Item dataIndex="maxSalary" label="最高薪资(元/月)" /> <ProDescriptions.Item dataIndex="companyName" label="招聘公司" />
<ProDescriptions.Item <ProDescriptions.Item dataIndex="minSalary" label="最低薪资(元/月)" />
dataIndex="education" <ProDescriptions.Item dataIndex="maxSalary" label="最高薪资(元/月)" />
label="学历要求" <ProDescriptions.Item
valueEnum={educationEnum} dataIndex="education"
/> label="学历要求"
<ProDescriptions.Item valueEnum={educationEnum}
dataIndex="experience" />
label="工作经验" <ProDescriptions.Item
valueEnum={experienceEnum} dataIndex="experience"
/> label="工作经验"
<ProDescriptions.Item valueEnum={experienceEnum}
dataIndex="jobLocationAreaCode" />
label="工作区县" <ProDescriptions.Item
valueEnum={areaEnum} dataIndex="jobLocationAreaCode"
/> label="工作区县"
<ProDescriptions.Item dataIndex="vacancies" label="招聘人数" /> valueEnum={areaEnum}
<ProDescriptions.Item dataIndex="jobLocation" label="工作地点" /> />
<ProDescriptions.Item <ProDescriptions.Item dataIndex="vacancies" label="招聘人数" />
dataIndex="description" <ProDescriptions.Item dataIndex="jobLocation" label="工作地点" />
label="岗位描述" <ProDescriptions.Item
span={2} // 跨两列显示 dataIndex="description"
/> label="岗位描述"
</ProDescriptions> span={2} // 跨两列显示
</ModalForm> />
); </ProDescriptions>
} </ModalForm>
return ( );
<ModalForm<{ }
name: string; return (
company: string; <ModalForm<API.ManagementList.Manage>
}>
title={mode === 'edit' ? '编辑岗位' : '新建岗位'} title={mode === 'edit' ? '编辑岗位' : '新建岗位'}
form={form} form={form}
autoFocusFirstInput autoFocusFirstInput
open={props.open} open={props.open}
modalProps={{ modalProps={{
destroyOnClose: true, destroyOnClose: true,
onCancel: () => handleCancel(), onCancel: () => handleCancel(),
}} }}
submitTimeout={2000} submitTimeout={2000}
onFinish={handleFinish} onFinish={handleFinish}
> >
<ProForm.Group> <ProForm.Group>
<ProFormText width="md" hidden name="jobId" /> <ProFormText width="md" hidden name="jobId" />
<ProFormText width="md" hidden name="companyName" /> <ProFormText width="md" hidden name="companyName" />
<ProFormText width="md" name="jobTitle" label="岗位名称" placeholder="请输入岗位名称" /> <ProFormText width="md" name="jobTitle" label="岗位名称" placeholder="请输入岗位名称" />
<ProFormSelect <ProFormSelect
showSearch showSearch
width="md" width="md"
name="companyId" name="companyId"
onChange={handleChange} onChange={handleChange}
request={async ({ keyWords }) => { request={async ({ keyWords }) => {
let resData = await getCmsCompanyList({ name: keyWords }); let resData = await getCmsCompanyList({ name: keyWords });
return resData.rows.map((item) => ({ label: item.name, value: item.companyId })); return resData.rows.map((item) => ({ label: item.name, value: item.companyId }));
}} }}
placeholder="请输入公司名称选择公司" placeholder="请输入公司名称选择公司"
rules={[{ required: true, message: '请输入公司名称选择公司!' }]} rules={[{ required: true, message: '请输入公司名称选择公司!' }]}
label="招聘会公司" label="招聘会公司"
/> />
</ProForm.Group> </ProForm.Group>
<ProForm.Group> <ProForm.Group>
<ProFormDigit <ProFormDigit
name="minSalary" name="minSalary"
width="md" width="md"
min={0} min={0}
label="最小薪资(元/月)" label="最小薪资(元/月)"
placeholder="请输入最小薪资(元)" placeholder="请输入最小薪资(元)"
/> />
<ProFormDigit <ProFormDigit
name="maxSalary" name="maxSalary"
width="md" width="md"
min={0} min={0}
label="最大薪资(元/月)" label="最大薪资(元/月)"
placeholder="请输入最大薪资(元)" placeholder="请输入最大薪资(元)"
/> />
</ProForm.Group> </ProForm.Group>
<ProForm.Group> <ProForm.Group>
<ProFormSelect <ProFormSelect
width="md" width="md"
name="education" name="education"
label={'学历要求'} label={'学历要求'}
valueEnum={educationEnum} valueEnum={educationEnum}
placeholder="请选择学历要求" placeholder="请选择学历要求"
rules={[{ required: true, message: '请选择学历要求!' }]} rules={[{ required: true, message: '请选择学历要求!' }]}
/> />
<ProFormSelect <ProFormSelect
width="md" width="md"
name="experience" name="experience"
label={'工作经验'} label={'工作经验'}
valueEnum={experienceEnum} valueEnum={experienceEnum}
placeholder="请选择岗位" placeholder="请选择岗位"
rules={[{ required: true, message: '请选择工作经验!' }]} rules={[{ required: true, message: '请选择工作经验!' }]}
/> />
</ProForm.Group> </ProForm.Group>
<ProForm.Group> <ProForm.Group>
<ProFormSelect <ProFormSelect
width="md" width="md"
name="jobLocationAreaCode" name="jobLocationAreaCode"
label={'工作区县'} label={'工作区县'}
valueEnum={areaEnum} valueEnum={areaEnum}
placeholder="请选择区县" placeholder="请选择区县"
rules={[{ required: true, message: '请选择区县!' }]} rules={[{ required: true, message: '请选择区县!' }]}
/> />
<ProFormDigit <ProFormDigit
label="招聘人数" label="招聘人数"
name="vacancies" name="vacancies"
width="md" width="md"
min={0} min={0}
placeholder="请输入招聘人数" placeholder="请输入招聘人数"
/> />
</ProForm.Group> </ProForm.Group>
<ProForm.Group> <ProForm.Group>
<ProFormText width="lg" name="jobLocation" label="工作地点" placeholder="请输入工作地点" /> <ProFormText width="lg" name="jobLocation" label="工作地点" placeholder="请输入工作地点" />
</ProForm.Group> </ProForm.Group>
<ProForm.Group> <ProForm.Group>
<ProFormTextArea <ProFormTextArea
width="lg" width="lg"
name="description" name="description"
label="岗位描述" label="岗位描述"
placeholder="请输入岗位描述" placeholder="请输入岗位描述"
/> />
</ProForm.Group> </ProForm.Group>
</ModalForm> </ModalForm>
); );
}; };
export default listEdit; export default listEdit;

View File

@@ -1,72 +1,72 @@
declare namespace API.ManagementList { declare namespace API.ManagementList {
export interface Manage { export interface Manage {
applyNum: number; applyNum?: number;
companyId: number; companyId?: number;
companyName: string; companyName?: string;
education: string; education?: string;
experience: string; experience?: string;
isApply: number; isApply?: number;
isCollection: number; isCollection?: number;
isHot: number; isHot?: number;
jobId: number; jobId?: number;
jobLocation: string; jobLocation?: string;
jobLocationAreaCode: number; jobLocationAreaCode?: string;
jobTitle: string; jobTitle?: string;
latitude: number; latitude?: number;
longitude: number; longitude?: number;
maxSalary: number; maxSalary?: number;
minSalary: number; minSalary?: number;
postingDate: string; postingDate?: string;
vacancies: number; vacancies?: number;
view: number; view?: number;
release: number; release?: number;
isPublish: number; isPublish?: number;
} }
export interface AddParams { export interface AddParams {
applyNum?: number; applyNum?: number;
companyId?: number; companyId?: number;
companyName?: string; companyName?: string;
education?: string; education?: string;
experience?: string; experience?: string;
isApply?: number; isApply?: number;
isCollection?: number; isCollection?: number;
isHot?: number; isHot?: number;
jobId?: number; jobId?: number;
jobLocation?: string; jobLocation?: string;
jobLocationAreaCode?: number; jobLocationAreaCode?: string;
jobTitle?: string; jobTitle?: string;
latitude?: number; latitude?: number;
longitude?: number; longitude?: number;
maxSalary?: number; maxSalary?: number;
minSalary?: number; minSalary?: number;
postingDate?: string; postingDate?: string;
vacancies?: number; vacancies?: number;
view?: number; view?: number;
release?: number; release?: number;
isPublish?: number; isPublish?: number;
} }
export interface ListParams { export interface ListParams {
createTime?: string; createTime?: string;
updateTime?: string; updateTime?: string;
remark?: string; remark?: string;
pageSize?: number; pageSize?: number;
current?: number; current?: number;
} }
export interface ManageIdResult { export interface ManageIdResult {
code: number; code: number;
msg: string; msg: string;
data: Manage; data: Manage;
rows: Array<any>; rows: Array<any>;
total: number; total: number;
} }
export interface ManagePageResult { export interface ManagePageResult {
code: number; code: number;
msg: string; msg: string;
total: number; total: number;
rows: Array<Manage>; rows: Array<Manage>;
} }
} }

View File

@@ -1,26 +1,33 @@
declare namespace API.ClassifyJobs { declare namespace API.ClassifyJobs {
export interface Result { export interface Result {
total: number; total: number;
rows: Jobs[]; rows: Jobs[];
code: number; code: number;
msg: string; msg: string;
} }
export interface Jobs { export interface Jobs {
[x: string]: number; createTime?: string;
createTime?: any; jobId: number;
jobId: number; parentId: number;
parentId: number; jobName: string;
jobName: string; orderNum: number;
orderNum: number; status: string;
status: string; children?:Jobs[];
} depth?: number;
parentName?: string;
export interface Params { }
jobId?: number; export interface JobTreeNode extends Jobs {
parentId?: number; children: JobTreeNode[];
jobName?: string; depth: number;
orderNum?: number; }
status?: string;
} export interface Params {
} jobId?: number;
parentId?: number;
jobName?: string;
orderNum?: number;
status?: string;
tree?:boolean;
}
}

74
src/typings.d.ts vendored
View File

@@ -1,44 +1,32 @@
declare module 'slash2'; declare module 'slash2';
declare module '*.css'; declare module '*.css';
declare module '*.less'; declare module '*.less';
declare module '*.scss'; declare module '*.scss';
declare module '*.sass'; declare module '*.sass';
declare module '*.svg'; declare module '*.svg';
declare module '*.png'; declare module '*.png';
declare module '*.jpg'; declare module '*.jpg';
declare module '*.jpeg'; declare module '*.jpeg';
declare module '*.gif'; declare module '*.gif';
declare module '*.bmp'; declare module '*.bmp';
declare module '*.tiff'; declare module '*.tiff';
declare module 'omit.js'; declare module 'omit.js';
declare module 'numeral'; declare module 'numeral';
declare module '@antv/data-set'; declare module '@antv/data-set';
declare module 'mockjs'; declare module 'mockjs';
declare module 'react-fittext'; declare module 'react-fittext';
declare module 'bizcharts-plugin-slider'; declare module 'bizcharts-plugin-slider';
declare const REACT_APP_ENV: 'test' | 'dev' | 'pre' | false; declare const REACT_APP_ENV: 'test' | 'dev' | 'pre' | false;
declare namespace API { declare namespace API {
namespace ClassifyJobs { namespace ClassifyJobs {
interface Params { interface Params {
tree?: boolean; tree?: boolean;
pageSize?: number; pageSize?: number;
current?: number; current?: number;
jobName?: string; jobName?: string;
status?: string; status?: string;
[key: string]: any; // 允许其他未定义属性 [key: string]: any; // 允许其他未定义属性
} }
}
// 表格和表单使用的职业数据
interface Job {
jobId: number;
parentId: number;
jobName: string;
orderNum?: number;
status?: string;
createTime?: string;
parentName?: string;
children?: Job[];
}
}
} }