企业管理
This commit is contained in:
@@ -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
34
pnpm-lock.yaml
generated
@@ -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: {}
|
||||
|
||||
12
src/configs/companyConfig.ts
Normal file
12
src/configs/companyConfig.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
/**
|
||||
* 企业状态
|
||||
*/
|
||||
export const stateObj: any = {
|
||||
1: '正常',
|
||||
2: '禁用',
|
||||
};
|
||||
|
||||
export const stateOptions = [
|
||||
{ label: '正常', value: '1' },
|
||||
{ label: '禁用', value: '2' },
|
||||
];
|
||||
@@ -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>
|
||||
<HashRouter>
|
||||
<App />,
|
||||
</HashRouter>,
|
||||
// </StrictMode>,
|
||||
);
|
||||
|
||||
139
src/pages/Company/List/components/CompanyEditModal.tsx
Normal file
139
src/pages/Company/List/components/CompanyEditModal.tsx
Normal 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>
|
||||
);
|
||||
};
|
||||
62
src/pages/Company/List/components/CompanySelect.tsx
Normal file
62
src/pages/Company/List/components/CompanySelect.tsx
Normal 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;
|
||||
@@ -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>
|
||||
);
|
||||
};
|
||||
@@ -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'
|
||||
type='text'
|
||||
onClick={() => {
|
||||
UserEditModalRef.current?.show(item);
|
||||
//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 }}
|
||||
style={{ marginBottom: 12, marginRight: 12 }}
|
||||
current={params.curr_page}
|
||||
pageSize={params.page_count}
|
||||
total={ajaxData.count}
|
||||
onChange={page}
|
||||
/>
|
||||
</GapBox>
|
||||
|
||||
<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)} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -229,6 +229,16 @@ export const AdminGrpEditModal: React.FC<IProps> = (props) => {
|
||||
<Button onClick={expandAll}>展开</Button>
|
||||
<Button onClick={collapseAll}>折叠</Button>
|
||||
</Space>
|
||||
<div
|
||||
style={{
|
||||
maxHeight: 360,
|
||||
overflow: 'auto',
|
||||
border: '1px solid #d9d9d9',
|
||||
borderRadius: 6,
|
||||
padding: 8,
|
||||
background: '#fff',
|
||||
}}
|
||||
>
|
||||
<Tree
|
||||
checkable
|
||||
checkStrictly={false} // 父子联动
|
||||
@@ -238,6 +248,7 @@ export const AdminGrpEditModal: React.FC<IProps> = (props) => {
|
||||
onExpand={(keys) => setExpandedKeys(keys)}
|
||||
onCheck={(keys) => setCheckedKeys(keys as React.Key[])}
|
||||
/>
|
||||
</div>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</ModalPlugin>
|
||||
|
||||
@@ -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) => {
|
||||
|
||||
@@ -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) => {
|
||||
|
||||
@@ -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%' }}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
export const CompanyServices = {
|
||||
getCompanyList: '/Company/getCompanyList',
|
||||
getCompanyAjaxList: '/Company/getCompanyAjaxList',
|
||||
edit: '/Company/edit',
|
||||
} as const;
|
||||
|
||||
Reference in New Issue
Block a user