企业管理

This commit is contained in:
2026-01-21 14:47:35 +08:00
parent a7f5e37aac
commit ab91458199
14 changed files with 385 additions and 261 deletions

View File

@@ -26,6 +26,7 @@
"qs": "^6.14.1",
"react": "^19.2.3",
"react-dom": "^19.2.3",
"react-router-dom": "^6.30.3",
"valtio": "^2.3.0",
"zustand": "^5.0.9"
},

34
pnpm-lock.yaml generated
View File

@@ -29,6 +29,9 @@ importers:
react-dom:
specifier: ^19.2.3
version: 19.2.3(react@19.2.3)
react-router-dom:
specifier: ^6.30.3
version: 6.30.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
valtio:
specifier: ^2.3.0
version: 2.3.0(@types/react@19.2.7)(react@19.2.3)
@@ -736,6 +739,10 @@ packages:
react: '>=16.9.0'
react-dom: '>=16.9.0'
'@remix-run/router@1.23.2':
resolution: {integrity: sha512-Ic6m2U/rMjTkhERIa/0ZtXJP17QUi2CbWE7cqx4J58M8aA3QTfW+2UlQ4psvTX9IO1RfNVhK3pcpdjej7L+t2w==}
engines: {node: '>=14.0.0'}
'@rolldown/binding-android-arm64@1.0.0-beta.53':
resolution: {integrity: sha512-Ok9V8o7o6YfSdTTYA/uHH30r3YtOxLD6G3wih/U9DO0ucBBFq8WPt/DslU53OgfteLRHITZny9N/qCUxMf9kjQ==}
engines: {node: ^20.19.0 || >=22.12.0}
@@ -1301,6 +1308,19 @@ packages:
resolution: {integrity: sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==}
engines: {node: '>=0.10.0'}
react-router-dom@6.30.3:
resolution: {integrity: sha512-pxPcv1AczD4vso7G4Z3TKcvlxK7g7TNt3/FNGMhfqyntocvYKj+GCatfigGDjbLozC4baguJ0ReCigoDJXb0ag==}
engines: {node: '>=14.0.0'}
peerDependencies:
react: '>=16.8'
react-dom: '>=16.8'
react-router@6.30.3:
resolution: {integrity: sha512-XRnlbKMTmktBkjCLE8/XcZFlnHvr2Ltdr1eJX4idL55/9BbORzyZEaIkBFDhFGCEWBBItsVrDxwx3gnisMitdw==}
engines: {node: '>=14.0.0'}
peerDependencies:
react: '>=16.8'
react@19.2.3:
resolution: {integrity: sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==}
engines: {node: '>=0.10.0'}
@@ -2178,6 +2198,8 @@ snapshots:
react: 19.2.3
react-dom: 19.2.3(react@19.2.3)
'@remix-run/router@1.23.2': {}
'@rolldown/binding-android-arm64@1.0.0-beta.53':
optional: true
@@ -2675,6 +2697,18 @@ snapshots:
react-refresh@0.18.0: {}
react-router-dom@6.30.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3):
dependencies:
'@remix-run/router': 1.23.2
react: 19.2.3
react-dom: 19.2.3(react@19.2.3)
react-router: 6.30.3(react@19.2.3)
react-router@6.30.3(react@19.2.3):
dependencies:
'@remix-run/router': 1.23.2
react: 19.2.3
react@19.2.3: {}
require-directory@2.1.1: {}

View File

@@ -0,0 +1,12 @@
/**
* 企业状态
*/
export const stateObj: any = {
1: '正常',
2: '禁用',
};
export const stateOptions = [
{ label: '正常', value: '1' },
{ label: '禁用', value: '2' },
];

View File

@@ -1,9 +1,12 @@
import { createRoot } from 'react-dom/client';
import './index.css';
import { HashRouter } from 'react-router-dom';
import App from './App.tsx';
createRoot(document.getElementById('root')!).render(
// <StrictMode>
<App />,
<HashRouter>
<App />,
</HashRouter>,
// </StrictMode>,
);

View File

@@ -0,0 +1,139 @@
import { Button, DatePicker, Form, Input, notification, Select } from 'antd';
import TextArea from 'antd/lib/input/TextArea';
import dayjs from 'dayjs';
import { stringify } from 'qs';
import type React from 'react';
import { useImperativeHandle, useState } from 'react';
import ModalPlugin from '@/components/ModalPlugin';
import { stateOptions } from '@/configs/usersConfig';
import { CompanyServices } from '@/services/CompanyServices';
import type { IRef } from '@/utils/type';
import { useRequest } from '@/utils/useRequest';
interface IProps extends IRef {
onCallback?: () => void;
}
export type ICompanyEditModalType = {
show: (data?: any) => void;
};
export const CompanyEditModal: React.FC<IProps> = (props) => {
const [open, setOpen] = useState(false);
const [title, setTitle] = useState('');
const [form] = Form.useForm();
const [data, setData] = useState<any>(null);
// 请求成功回调
const success = (res: any) => {
if (res.err_code === 0) {
notification.success({ message: '保存成功' });
props.onCallback?.();
setOpen(false);
form.resetFields(); // 提交成功重置表单
}
};
//const { loading: addLoading, request: addRequest } = useRequest(CompanyServices.add, { onSuccess: success });
const { loading: editLoading, request: editRequest } = useRequest(CompanyServices.edit, { onSuccess: success });
const save = async () => {
try {
const values = await form.validateFields();
const [eff_date, exp_date] = values.date_range || [];
values.eff_date = eff_date?.format('YYYY-MM-DD') || null;
values.exp_date = exp_date?.format('YYYY-MM-DD') || null;
delete values.date_range;
// 编辑场景带上主键
if (data?.company_id) {
values.company_id = data.company_id;
editRequest(stringify(values));
} else {
//addRequest(stringify(values));
}
} catch (error) {
console.log('表单验证未通过', error);
}
};
useImperativeHandle(props.ref, () => ({
show: (data?: any) => {
setTitle(data ? `${data.company_name} 编辑` : '新增');
setOpen(true);
setData(data);
if (data) {
// 编辑场景初始化表单
form.setFieldsValue({
company_name: data.company_name,
company_address: data.company_address,
erp_name: data.erp_name,
date_range: data.eff_date && data.exp_date ? [dayjs(data.eff_date), dayjs(data.exp_date)] : undefined,
company_state: String(data.company_state),
});
} else {
form.resetFields();
}
},
}));
return (
<ModalPlugin
open={open}
onCancel={() => setOpen(false)}
title={title}
footer={[
<Button key='cancel' onClick={() => setOpen(false)}>
</Button>,
<Button key='save' type='primary' loading={editLoading} onClick={save}>
</Button>,
]}
>
<Form form={form} labelCol={{ style: { width: window?.dfConfig?.language === 'zh-cn' ? 80 : 120 } }}>
<Form.Item
label='企业'
name='company_name'
required
rules={[
{ required: true, message: '请输入企业' },
{ min: 2, message: '最少2字符' },
{ max: 20, message: '最多20字符' },
]}
>
<Input allowClear placeholder='请填写企业' maxLength={20} showCount />
</Form.Item>
<Form.Item
label='ERP'
name='erp_name'
rules={[
{ min: 2, message: '最少2字符' },
{ max: 20, message: '最多20字符' },
]}
>
<Input allowClear placeholder='请填写ERP' maxLength={20} showCount />
</Form.Item>
<Form.Item label='地址' name='company_address'>
<Input allowClear placeholder='请填写地址' maxLength={20} showCount />
</Form.Item>
<Form.Item label={'状态'} name='company_state'>
<Select options={stateOptions} placeholder='请选择状态' />
</Form.Item>
<Form.Item label='简介' name='company_desc'>
<TextArea allowClear maxLength={200} showCount />
</Form.Item>
<Form.Item label='有效期' name='date_range'>
<DatePicker.RangePicker style={{ width: '100%' }} format='YYYY-MM-DD' allowClear />
</Form.Item>
</Form>
</ModalPlugin>
);
};

View File

@@ -0,0 +1,62 @@
import { Select } from 'antd';
import type { InputStatus } from 'antd/es/_util/statusUtils';
import type React from 'react';
import { useEffect, useState } from 'react';
import { CompanyServices } from '@/services/CompanyServices';
import { isArray } from '@/utils/common';
import { useRequest } from '@/utils/useRequest';
interface IProps {
status?: InputStatus;
value?: string | number;
onChange?: (value: string | number) => void;
onBlur?: React.FocusEventHandler<HTMLElement> | undefined;
allowClear?: boolean;
}
const CompanySelect: React.FC<IProps> = (props) => {
const [list, setList] = useState<any[]>([]);
const { request } = useRequest(CompanyServices.getCompanyAjaxList, {
onSuccess: (res) => {
const arr: any[] = [];
if (res.err_code == 0 && isArray(res.data)) {
res.data.forEach((item: any) => {
arr.push({
label: item.company_name,
value: item.company_id,
});
});
}
setList(arr);
},
});
useEffect(() => {
request();
}, []);
return (
<Select
status={props.status}
showSearch={{
// 搜索时使用 option.label 属性匹配
optionFilterProp: 'label',
// 下拉排序,可选
filterSort: (optionA, optionB) =>
(optionA?.label ?? '').toLowerCase().localeCompare((optionB?.label ?? '').toLowerCase()),
}}
allowClear={props.allowClear}
//value={props.value}
value={props.value !== undefined && props.value != null && props.value !== '' ? Number(props.value) : undefined}
onChange={(value) => {
props.onChange?.(value);
}}
onBlur={(event) => {
props.onBlur?.(event);
}}
options={list}
popupRender={(menu) => <>{menu}</>}
/>
);
};
export default CompanySelect;

View File

@@ -1,168 +0,0 @@
import { Button, Form, Input, notification, Select } from 'antd';
import TextArea from 'antd/lib/input/TextArea';
import { stringify } from 'qs';
import type React from 'react';
import { useImperativeHandle, useState } from 'react';
import ModalPlugin from '@/components/ModalPlugin';
import { stateOptions, userSexOptions } from '@/configs/usersConfig';
import { UserServices } from '@/services/UserServices';
import type { IRef } from '@/utils/type';
import { useRequest } from '@/utils/useRequest';
interface IProps extends IRef {
onCallback?: () => void;
}
export type IUserEditModalType = {
show: (data?: any) => void;
};
export const UserEditModal: React.FC<IProps> = (props) => {
const [open, setOpen] = useState(false);
const [title, setTitle] = useState('');
const [form] = Form.useForm();
const [data, setData] = useState<any>(null);
// 请求成功回调
const success = (res: any) => {
if (res.err_code === 0) {
notification.success({ message: '保存成功' });
props.onCallback?.();
setOpen(false);
form.resetFields(); // 提交成功重置表单
}
};
const { loading: addLoading, request: addRequest } = useRequest(UserServices.add, { onSuccess: success });
const { loading: editLoading, request: editRequest } = useRequest(UserServices.edit, { onSuccess: success });
const save = async () => {
try {
const values = await form.validateFields();
// 编辑场景带上主键
if (data?.user_id) {
values.user_id = data.user_id;
editRequest(stringify(values));
} else {
addRequest(stringify(values));
}
} catch (error) {
console.log('表单验证未通过', error);
}
};
useImperativeHandle(props.ref, () => ({
show: (data?: any) => {
setTitle(data ? `${data.login_name} 编辑` : '新增');
setOpen(true);
setData(data);
if (data) {
// 编辑场景初始化表单
form.setFieldsValue({
login_name: data.login_name,
user_phone: data.user_phone,
user_mail: data.user_mail,
nick_name: data.nick_name,
password: '', // 密码编辑可选
comments: data.comments,
user_sex: String(data.user_sex),
state: String(data.state),
});
} else {
form.resetFields();
form.setFieldsValue({
user_sex: '1',
state: '1',
});
}
},
}));
return (
<ModalPlugin
open={open}
onCancel={() => setOpen(false)}
title={title}
footer={[
<Button key='cancel' onClick={() => setOpen(false)}>
</Button>,
<Button key='save' type='primary' loading={addLoading || editLoading} onClick={save}>
</Button>,
]}
>
<Form form={form} labelCol={{ style: { width: window?.dfConfig?.language === 'zh-cn' ? 80 : 120 } }}>
<Form.Item
label='用户名'
name='login_name'
required
rules={[
{ required: true, message: '请输入用户名' },
{ min: 2, message: '最少2字符' },
{ max: 20, message: '最多20字符' },
]}
>
<Input allowClear placeholder='请填写用户名' maxLength={20} showCount />
</Form.Item>
<Form.Item
label='昵称'
name='nick_name'
rules={[
{ min: 2, message: '最少2字符' },
{ max: 20, message: '最多20字符' },
]}
>
<Input allowClear placeholder='请填写昵称' maxLength={20} showCount />
</Form.Item>
<Form.Item
label='手机号'
name='user_phone'
required
rules={[
{ required: true, message: '请输入手机号' },
{ pattern: /^1[3-9]\d{9}$/, message: '手机号格式不正确' },
]}
>
<Input allowClear placeholder='请填写手机号' maxLength={11} showCount />
</Form.Item>
<Form.Item label='邮箱' name='user_mail' rules={[{ type: 'email', message: '邮箱格式不正确' }]}>
<Input allowClear placeholder='请填写邮箱' />
</Form.Item>
<Form.Item label='密码' name='password' rules={[{ min: 6, max: 18, message: '密码需6~18位' }]}>
<Input.Password allowClear placeholder={data ? '不修改请留空' : '请填写密码'} />
</Form.Item>
{!data?.user_id && (
<Form.Item
label='企业名'
name='company_name'
rules={[
{ min: 2, message: '最少2字符' },
{ max: 20, message: '最多20字符' },
]}
>
<Input allowClear placeholder='请填写企业名' />
</Form.Item>
)}
<Form.Item label={'性别'} name='user_sex'>
<Select options={userSexOptions} placeholder='请选择性别' />
</Form.Item>
<Form.Item label={'状态'} name='state'>
<Select options={stateOptions} placeholder='请选择状态' />
</Form.Item>
<Form.Item label='备注' name='comments'>
<TextArea allowClear maxLength={200} showCount />
</Form.Item>
</Form>
</ModalPlugin>
);
};

View File

@@ -1,30 +1,28 @@
import { Button, DatePicker, Input, Select } from 'antd';
import { stringify } from 'qs';
import { useEffect, useRef, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { FormItemPlugin, FormPlugin } from '@/components/FormPlugin';
import { GapBox } from '@/components/GapBox';
import PageContainerPlugin from '@/components/PageContainer/PageContainerPlugin';
import { FooterPagination, HeaderPagination } from '@/components/PaginationPlugin';
import { MoreSearchButton, SearchButton } from '@/components/SearchButton';
import { SearchButton } from '@/components/SearchButton';
import type { ColumnsTypeUltra } from '@/components/TableColumnsFilterPlugin';
import { TablePlugin } from '@/components/TablePlugin';
import { staffType } from '@/configs/staffsConfig';
import { stateOptions, userSex, userState } from '@/configs/usersConfig';
import { stateObj, stateOptions } from '@/configs/companyConfig';
import type { IAjaxDataBase, IParamsBase } from '@/interfaces/common';
import { type IUserEditModalType, UserEditModal } from '@/pages/User/List/components/UserEditModal';
import { UserServices } from '@/services/UserServices';
import { CompanyServices } from '@/services/CompanyServices';
import { useAuthStore } from '@/store/AuthStore';
import { tableFixedByPhone, toArray } from '@/utils/common';
import { useRequest } from '@/utils/useRequest';
import { CompanyEditModal, type ICompanyEditModalType } from './components/CompanyEditModal';
interface IAjaxData extends IAjaxDataBase {
data: any[];
}
type IParams = IParamsBase & {
login_name?: string;
nick_name?: string;
user_phone?: string;
state?: number;
company_name?: string;
company_state?: number;
create_dateL?: string;
create_dateU?: string;
};
@@ -35,9 +33,10 @@ const CompanyListForm: React.FC = () => {
const [params, setParams] = useState<IParams>({ curr_page: 1, page_count: 20 });
const [ajaxData, setAjaxData] = useState<IAjaxData>({ count: 0, data: [] });
const [showMoreSearch, setShowMoreSearch] = useState(false);
const UserEditModalRef = useRef<IUserEditModalType>(null);
const CompanyEditModalRef = useRef<ICompanyEditModalType>(null);
const nav = useNavigate();
const { loading: userLoading, request: userRequest } = useRequest(UserServices.getUserList, {
const { loading: userLoading, request: userRequest } = useRequest(CompanyServices.getCompanyList, {
onSuccessCodeZero: (res) => {
setAjaxData({
count: res.count || 0,
@@ -49,43 +48,52 @@ const CompanyListForm: React.FC = () => {
const columns: ColumnsTypeUltra<any> = [
{
title: '操作',
width: 50,
width: 120,
fixed: tableFixedByPhone('left'),
render: (_, item) => (
<GapBox>
<Button
type='primary'
onClick={() => {
UserEditModalRef.current?.show(item);
CompanyEditModalRef.current?.show(item);
}}
>
</Button>
{auth.SF_ERP_USER_EDIT && (
<Button
type='primary'
onClick={() => {
UserEditModalRef.current?.show(item);
}}
>
</Button>
)}
<Button
type='text'
onClick={() => {
//nav(`user/list?company_id=${item.company_id}`);
location.href = `#/user/list?company_id=${item.company_id}`;
}}
>
</Button>
</GapBox>
),
},
{ title: '用户名', dataIndex: 'login_name', width: 120 },
{ title: '企业名称', dataIndex: 'company_name', width: 120 },
{ title: '类型', dataIndex: 'staff_type', width: 60, render: (value) => staffType[value] },
{ title: '昵称', dataIndex: 'nick_name', width: 120 },
{ title: '手机', dataIndex: 'user_phone', width: 120 },
{ title: '性别', dataIndex: 'user_sex', width: 60, render: (value) => userSex[value] },
{ title: '状态', dataIndex: 'state', width: 60, ellipsis: true, render: (value) => userState[value] },
{ title: '企业', dataIndex: 'company_name', width: 80 },
{ title: 'ERP', dataIndex: 'erp_name', width: 80 },
{ title: '状态', dataIndex: 'company_state', width: 60, ellipsis: true, render: (value) => stateObj[value] },
{
title: '备注',
dataIndex: 'comments',
title: '地址',
dataIndex: 'company_address',
width: 300,
},
{
title: '简介',
dataIndex: 'company_desc',
width: 300,
},
{
title: '有效期',
dataIndex: 'eff_date',
width: 190,
render: (_, record) => {
return record.eff_date ? `${record.eff_date || ''}${record.exp_date || ''}` : '';
},
},
{
title: '创建时间',
width: window.dfConfig.isPhone ? 160 : 160,
@@ -109,37 +117,35 @@ const CompanyListForm: React.FC = () => {
return (
<>
<FormPlugin gutter={16}>
<FormItemPlugin label={'用户名'}>
<FormItemPlugin label={'企业'}>
<Input
allowClear
defaultValue={params.login_name}
placeholder='用户名'
defaultValue={params.company_name}
placeholder='企业'
onChange={(e) => {
params.login_name = e.target.value.trim() || undefined;
params.company_name = e.target.value.trim() || undefined;
}}
onPressEnter={() => page(1)}
/>
</FormItemPlugin>
<FormItemPlugin label={'昵称'}>
<Input
<FormItemPlugin label={'状态'}>
<Select
allowClear
defaultValue={params.nick_name}
placeholder='昵称'
onChange={(e) => {
params.nick_name = e.target.value.trim() || undefined;
value={params.company_state}
options={stateOptions}
onChange={(value) => {
params.company_state = value || undefined;
setParams({ ...params });
}}
onPressEnter={() => page(1)}
/>
</FormItemPlugin>
<FormItemPlugin label={'手机号'}>
<Input
allowClear
defaultValue={params.user_phone}
placeholder='手机号'
onChange={(e) => {
params.user_phone = e.target.value.trim() || undefined;
<FormItemPlugin label={'创建日期'}>
<DatePicker.RangePicker
style={{ width: '100%' }}
onChange={(_values, dates) => {
params.create_dateL = dates?.[0] || undefined;
params.create_dateU = dates?.[1] || undefined;
}}
onPressEnter={() => page(1)}
/>
</FormItemPlugin>
@@ -158,24 +164,24 @@ const CompanyListForm: React.FC = () => {
page(1);
}}
/>
<MoreSearchButton
{/* <MoreSearchButton
show={showMoreSearch}
onClick={() => {
setShowMoreSearch((v) => !v);
}}
/>
/> */}
</div>
</FormItemPlugin>
</FormPlugin>
<FormPlugin style={{ display: showMoreSearch ? 'flex' : 'none' }} gutter={16}>
{/* <FormPlugin style={{ display: showMoreSearch ? 'flex' : 'none' }} gutter={16}>
<FormItemPlugin label={'状态'}>
<Select
allowClear
value={params.state}
value={params.company_state}
options={stateOptions}
onChange={(value) => {
params.state = value || undefined;
params.company_state = value || undefined;
setParams({ ...params });
}}
/>
@@ -189,27 +195,15 @@ const CompanyListForm: React.FC = () => {
}}
/>
</FormItemPlugin>
</FormPlugin>
</FormPlugin> */}
<GapBox style={{ marginBottom: 12, justifyContent: 'space-between' }}>
<GapBox>
<Button
type='primary'
onClick={() => {
UserEditModalRef.current?.show();
}}
>
</Button>
</GapBox>
<HeaderPagination
style={{ marginBottom: 0, marginRight: 12 }}
current={params.curr_page}
pageSize={params.page_count}
total={ajaxData.count}
onChange={page}
/>
</GapBox>
<HeaderPagination
style={{ marginBottom: 12, marginRight: 12 }}
current={params.curr_page}
pageSize={params.page_count}
total={ajaxData.count}
onChange={page}
/>
<TablePlugin
loading={userLoading}
@@ -219,7 +213,7 @@ const CompanyListForm: React.FC = () => {
dataSource={ajaxData.data}
columns={columns}
scroll={{ x: true }}
rowKey={'user_id'}
rowKey={'company_id'}
/>
<FooterPagination
@@ -232,7 +226,7 @@ const CompanyListForm: React.FC = () => {
}}
/>
<UserEditModal ref={UserEditModalRef} onCallback={() => page(1)} />
<CompanyEditModal ref={CompanyEditModalRef} onCallback={() => page(1)} />
</>
);
};

View File

@@ -148,7 +148,13 @@ const AdminSysLogForm: React.FC = () => {
<FormItemPlugin label='权限'>
<Select
showSearch
showSearch={{
// 搜索时使用 option.label 属性匹配
optionFilterProp: 'label',
// 下拉排序,可选
filterSort: (optionA, optionB) =>
(optionA?.label ?? '').toLowerCase().localeCompare((optionB?.label ?? '').toLowerCase()),
}}
allowClear
placeholder='请选择权限'
disabled={!params.menu_id}

View File

@@ -229,15 +229,26 @@ export const AdminGrpEditModal: React.FC<IProps> = (props) => {
<Button onClick={expandAll}></Button>
<Button onClick={collapseAll}></Button>
</Space>
<Tree
checkable
checkStrictly={false} // 父子联动
treeData={menuTree}
checkedKeys={checkedKeys}
expandedKeys={expandedKeys}
onExpand={(keys) => setExpandedKeys(keys)}
onCheck={(keys) => setCheckedKeys(keys as React.Key[])}
/>
<div
style={{
maxHeight: 360,
overflow: 'auto',
border: '1px solid #d9d9d9',
borderRadius: 6,
padding: 8,
background: '#fff',
}}
>
<Tree
checkable
checkStrictly={false} // 父子联动
treeData={menuTree}
checkedKeys={checkedKeys}
expandedKeys={expandedKeys}
onExpand={(keys) => setExpandedKeys(keys)}
onCheck={(keys) => setCheckedKeys(keys as React.Key[])}
/>
</div>
</Form.Item>
</Form>
</ModalPlugin>

View File

@@ -38,7 +38,13 @@ const AdminGrpSelect: React.FC<IProps> = (props) => {
return (
<Select
status={props.status}
showSearch
showSearch={{
// 搜索时使用 option.label 属性匹配
optionFilterProp: 'label',
// 下拉排序,可选
filterSort: (optionA, optionB) =>
(optionA?.label ?? '').toLowerCase().localeCompare((optionB?.label ?? '').toLowerCase()),
}}
allowClear={props.allowClear}
value={props.value}
onChange={(value) => {

View File

@@ -38,7 +38,13 @@ const AdminDepSelect: React.FC<IProps> = (props) => {
return (
<Select
status={props.status}
showSearch
showSearch={{
// 搜索时使用 option.label 属性匹配
optionFilterProp: 'label',
// 下拉排序,可选
filterSort: (optionA, optionB) =>
(optionA?.label ?? '').toLowerCase().localeCompare((optionB?.label ?? '').toLowerCase()),
}}
allowClear={props.allowClear}
value={props.value}
onChange={(value) => {

View File

@@ -1,6 +1,7 @@
import { Button, DatePicker, Input, Select } from 'antd';
import { stringify } from 'qs';
import { useEffect, useRef, useState } from 'react';
import { useSearchParams } from 'react-router-dom';
import { FormItemPlugin, FormPlugin } from '@/components/FormPlugin';
import { GapBox } from '@/components/GapBox';
import PageContainerPlugin from '@/components/PageContainer/PageContainerPlugin';
@@ -11,6 +12,7 @@ import { TablePlugin } from '@/components/TablePlugin';
import { staffType } from '@/configs/staffsConfig';
import { stateOptions, userSex, userState } from '@/configs/usersConfig';
import type { IAjaxDataBase, IParamsBase } from '@/interfaces/common';
import CompanySelect from '@/pages/Company/List/components/CompanySelect';
import { type IUserEditModalType, UserEditModal } from '@/pages/User/List/components/UserEditModal';
import { UserServices } from '@/services/UserServices';
import { useAuthStore } from '@/store/AuthStore';
@@ -25,6 +27,7 @@ type IParams = IParamsBase & {
nick_name?: string;
user_phone?: string;
state?: number;
company_id?: any;
create_dateL?: string;
create_dateU?: string;
};
@@ -32,10 +35,13 @@ type IParams = IParamsBase & {
/** 用户列表页面 */
const UserListForm: React.FC = () => {
const auth = useAuthStore().auth;
const [params, setParams] = useState<IParams>({ curr_page: 1, page_count: 20 });
const [ajaxData, setAjaxData] = useState<IAjaxData>({ count: 0, data: [] });
const [showMoreSearch, setShowMoreSearch] = useState(false);
const UserEditModalRef = useRef<IUserEditModalType>(null);
const [searchParams] = useSearchParams();
const company_id = searchParams.get('company_id');
const [params, setParams] = useState<IParams>({ curr_page: 1, page_count: 20, company_id });
const { loading: userLoading, request: userRequest } = useRequest(UserServices.getUserList, {
onSuccessCodeZero: (res) => {
@@ -75,7 +81,7 @@ const UserListForm: React.FC = () => {
),
},
{ title: '用户名', dataIndex: 'login_name', width: 120 },
{ title: '企业名称', dataIndex: 'company_name', width: 120 },
{ title: '企业', dataIndex: 'company_name', width: 120 },
{ title: '类型', dataIndex: 'staff_type', width: 60, render: (value) => staffType[value] },
{ title: '昵称', dataIndex: 'nick_name', width: 120 },
{ title: '手机', dataIndex: 'user_phone', width: 120 },
@@ -180,6 +186,16 @@ const UserListForm: React.FC = () => {
}}
/>
</FormItemPlugin>
<FormItemPlugin label={'企业'}>
<CompanySelect
allowClear
value={params.company_id} //
onChange={(value) => {
params.company_id = value || undefined;
setParams({ ...params });
}}
/>
</FormItemPlugin>
<FormItemPlugin label={'创建日期'}>
<DatePicker.RangePicker
style={{ width: '100%' }}

View File

@@ -1,3 +1,5 @@
export const CompanyServices = {
getCompanyList: '/Company/getCompanyList',
getCompanyAjaxList: '/Company/getCompanyAjaxList',
edit: '/Company/edit',
} as const;