feat(前端):终端列表

master
shaot 2025-08-11 17:19:58 +08:00
parent af9e040f01
commit e1fc19aeab
18 changed files with 671 additions and 319 deletions

0
node_modules/.cache/logger/umi.log generated vendored
View File

View File

@ -15,6 +15,7 @@
"@umijs/max": "^4.4.11", "@umijs/max": "^4.4.11",
"antd": "^5.4.0", "antd": "^5.4.0",
"dayjs": "^1.11.13", "dayjs": "^1.11.13",
"moment": "^2.30.1",
"spark-md5": "^3.0.2", "spark-md5": "^3.0.2",
"uuid": "^11.1.0" "uuid": "^11.1.0"
}, },

View File

@ -23,9 +23,9 @@ export const GENDER_MAP = {
// priority // priority
export const PRIORITY_MAP = { export const PRIORITY_MAP = {
1: '', 1: '一级',
2: '', 2: '二级',
3: '', 3: '三级',
} as const; } as const;
export const USER_TYPE_OPTIONS = [ export const USER_TYPE_OPTIONS = [
@ -42,3 +42,9 @@ export const GENDER_OPTIONS = [
{ value: 1, label: '女' }, { value: 1, label: '女' },
{ value: 2, label: '男' }, { value: 2, label: '男' },
]; ];
export const PRIOPRITY_OPTIONS = [
{ value: 1, label: '一级' },
{ value: 2, label: '二级' },
{ value: 3, label: '三级' },
];

View File

@ -16,6 +16,7 @@ import {
message, message,
Popconfirm, Popconfirm,
Popover, Popover,
Spin,
Table, Table,
Tooltip, Tooltip,
} from 'antd'; } from 'antd';
@ -34,6 +35,7 @@ const UserListPage: React.FC = () => {
const [searchText, setSearchText] = useState<string>(''); const [searchText, setSearchText] = useState<string>('');
const [selectedRowKeys, setSelectedRowKeys] = useState<[]>([]); const [selectedRowKeys, setSelectedRowKeys] = useState<[]>([]);
const [orgSearchText, setOrgSearchText] = useState<string>(''); const [orgSearchText, setOrgSearchText] = useState<string>('');
const [spinning, setSpinning] = useState<boolean>(false);
// 分页参数 // 分页参数
const [currentPage, setCurrentPage] = useState<number>(1); const [currentPage, setCurrentPage] = useState<number>(1);
@ -42,7 +44,7 @@ const UserListPage: React.FC = () => {
// 添加分组 // 添加分组
const [visible, setVisible] = useState<boolean>(false); const [visible, setVisible] = useState<boolean>(false);
// 编辑用户 // 编辑用户
const [currentUserInfo, setCurrentUserInfo] = useState<any>({ const [currentDeviceInfo, setCurrentDeviceInfo] = useState<any>({
visible: false, visible: false,
}); });
const [bindUserDta, setBindUserData] = useState<any>({ const [bindUserDta, setBindUserData] = useState<any>({
@ -55,7 +57,7 @@ const UserListPage: React.FC = () => {
// 获取用户分组组织树 // 获取用户分组组织树
useEffect(() => { useEffect(() => {
// getGroupList(); getGroupList();
}, []); }, []);
const filterTreeData = ( const filterTreeData = (
@ -91,28 +93,34 @@ const UserListPage: React.FC = () => {
// 获取用户列表数据 // 获取用户列表数据
useEffect(() => { useEffect(() => {
// if (selectedOrg) { getDataSource();
// getDataSource();
// }
}, [searchText, selectedOrg, currentPage, pageSize]); }, [searchText, selectedOrg, currentPage, pageSize]);
const getGroupList = async () => { const getGroupList = async () => {
setSpinning(true);
const params = { const params = {
type: 2, type: 2,
}; };
try { try {
const result = await getGroupTree(params); const result = await getGroupTree(params);
if (result.error_code === ERROR_CODE) { console.log('result=====', result);
setOrgTreeData(result.data.data || []); const { code, data = [] } = result || {};
if (result.data.data.length > 0) { if (code === ERROR_CODE) {
setSelectedOrg(result.data.data[0].id as number); if (data.length > 0) {
const { children = [] } = data[0] || {};
setOrgTreeData(children);
// if (children.length > 0) {
// setSelectedOrg(children[0].id);
// }
} }
setSpinning(false);
} else { } else {
setSpinning(false);
message.error(result.message || '获取终端分组失败'); message.error(result.message || '获取终端分组失败');
} }
} catch (err) { } catch (err) {
message.error('获取终端分组失败'); message.error('获取终端分组失败');
setLoading(false); setSpinning(false);
} }
}; };
@ -121,15 +129,21 @@ const UserListPage: React.FC = () => {
page_size: pageSize, page_size: pageSize,
page_num: currentPage, page_num: currentPage,
}; };
if (selectedOrg) {
params.device_group_id = selectedOrg;
}
if (searchText) { if (searchText) {
params.keywords = searchText; params.device_name = searchText;
} }
setLoading(true); setLoading(true);
try { try {
const result = await getTerminalList(params); const result: any = await getTerminalList(params);
if (result.error_code === ERROR_CODE) { console.log('result=====', result);
setDataSource(result.data.data || []); const { code, data } = result || {};
setTotal(result.data.paging.total || 0); const { data: list, total = 0 } = data || {};
if (code === ERROR_CODE) {
setDataSource(list);
setTotal(total);
setLoading(false); setLoading(false);
} else { } else {
message.error(result.message || '获取终端列表失败'); message.error(result.message || '获取终端列表失败');
@ -145,11 +159,11 @@ const UserListPage: React.FC = () => {
try { try {
const { id } = device || {}; const { id } = device || {};
const payload = { const payload = {
ids: id ? [id] : selectedRowKeys, ids: id ? id : selectedRowKeys,
}; };
const res = await deleteDevice(payload); const res: any = await deleteDevice(payload);
const { error_code } = res || {}; const { code } = res || {};
if (error_code === ERROR_CODE) { if (code === ERROR_CODE) {
message.success('终端删除成功'); message.success('终端删除成功');
setSelectedRowKeys([]); setSelectedRowKeys([]);
getDataSource(); getDataSource();
@ -159,8 +173,8 @@ const UserListPage: React.FC = () => {
} }
}; };
const handleEditUserInfo = (device: Termial.TermialItem) => { const handleEditInfo = (device: Termial.TermialItem) => {
setCurrentUserInfo({ setCurrentDeviceInfo({
recordData: { ...device }, recordData: { ...device },
visible: true, visible: true,
}); });
@ -186,9 +200,9 @@ const UserListPage: React.FC = () => {
}, },
}, },
{ {
title: '终端分组', title: '序列号',
dataIndex: 'device_group_name', dataIndex: 'device_id',
key: 'device_group_name', key: 'device_id',
width: 220, width: 220,
align: 'center', align: 'center',
render: (text) => { render: (text) => {
@ -196,20 +210,10 @@ const UserListPage: React.FC = () => {
}, },
}, },
{ {
title: 'IP地址', title: '终端分组',
dataIndex: 'ip_addr', dataIndex: 'device_group_name',
key: 'ip_addr', key: 'device_group_name',
width: 150, width: 220,
align: 'center',
render: (text) => {
return <Tooltip>{text || '--'}</Tooltip>;
},
},
{
title: '终端标识',
dataIndex: 'mac_addr',
key: 'mac_addr',
ellipsis: true,
align: 'center', align: 'center',
render: (text) => { render: (text) => {
return <Tooltip>{text || '--'}</Tooltip>; return <Tooltip>{text || '--'}</Tooltip>;
@ -226,6 +230,46 @@ const UserListPage: React.FC = () => {
return <Tooltip>{DEVICE_TYPE_MAP[key] || '--'}</Tooltip>; return <Tooltip>{DEVICE_TYPE_MAP[key] || '--'}</Tooltip>;
}, },
}, },
{
title: '型号',
dataIndex: 'model',
key: 'model',
width: 150,
align: 'center',
render: (text) => {
return <Tooltip>{text || '--'}</Tooltip>;
},
},
{
title: 'IP地址',
dataIndex: 'ip_addr',
key: 'ip_addr',
width: 150,
align: 'center',
render: (text) => {
return <Tooltip>{text || '--'}</Tooltip>;
},
},
{
title: 'MAC地址',
dataIndex: 'mac_addr',
key: 'mac_addr',
ellipsis: true,
align: 'center',
render: (text) => {
return <Tooltip>{text || '--'}</Tooltip>;
},
},
{
title: '备注',
dataIndex: 'description',
key: 'description',
ellipsis: true,
align: 'center',
render: (text) => {
return <Tooltip>{text || '--'}</Tooltip>;
},
},
{ {
title: '操作', title: '操作',
key: 'actions', key: 'actions',
@ -234,7 +278,7 @@ const UserListPage: React.FC = () => {
fixed: 'right', fixed: 'right',
render: (_, record) => ( render: (_, record) => (
<div style={{ display: 'flex', alignItems: 'center' }}> <div style={{ display: 'flex', alignItems: 'center' }}>
<Button type="link" onClick={() => handleEditUserInfo(record)}> <Button type="link" onClick={() => handleEditInfo(record)}>
</Button> </Button>
<Popover <Popover
@ -315,8 +359,8 @@ const UserListPage: React.FC = () => {
id: selectedOrg, id: selectedOrg,
}; };
const res = await deleteUserGroup(params); const res = await deleteUserGroup(params);
const { error_code } = res || {}; const { code } = res || {};
if (error_code === ERROR_CODE) { if (code === ERROR_CODE) {
message.success('分组删除成功'); message.success('分组删除成功');
getGroupList(); getGroupList();
} }
@ -326,6 +370,26 @@ const UserListPage: React.FC = () => {
} }
}; };
const onSaveGroup = () => {
getGroupList();
};
const onDeviceSave = () => {
setCurrentDeviceInfo({
recordData: {},
visible: false,
});
getDataSource();
};
const onBindUserSave = () => {
setBindUserData({
recordData: {},
visible: false,
});
getDataSource();
};
return ( return (
<div className={styles.user_content}> <div className={styles.user_content}>
<div className={styles.left_content}> <div className={styles.left_content}>
@ -361,16 +425,18 @@ const UserListPage: React.FC = () => {
/> />
</div> </div>
<div className={styles.tree_box}> <div className={styles.tree_box}>
<CustomTree <Spin spinning={spinning} delay={100}>
treeData={filteredOrgTreeData} <CustomTree
titleField="name" treeData={filteredOrgTreeData}
keyField="id" titleField="name"
childrenField="children" keyField="id"
defaultExpandAll={true} childrenField="children"
onSelect={onOrgSelect} defaultExpandAll={true}
selectedKeys={selectedOrg ? [selectedOrg] : []} onSelect={onOrgSelect}
icon={<TeamOutlined style={{ fontSize: '15px' }} />} selectedKeys={selectedOrg ? [selectedOrg] : []}
/> icon={<TeamOutlined style={{ fontSize: '15px' }} />}
/>
</Spin>
</div> </div>
</div> </div>
<div className={styles.right_content}> <div className={styles.right_content}>
@ -383,7 +449,7 @@ const UserListPage: React.FC = () => {
}} }}
> >
<div> <div>
<Popconfirm {/* <Popconfirm
title="" title=""
description="删除操作不可逆,请确认是否删除?" description="删除操作不可逆,请确认是否删除?"
onConfirm={() => onDelete()} onConfirm={() => onDelete()}
@ -398,7 +464,7 @@ const UserListPage: React.FC = () => {
> >
</Button> </Button>
</Popconfirm> </Popconfirm> */}
<Button style={{ marginRight: '8px' }} onClick={getDataSource}> <Button style={{ marginRight: '8px' }} onClick={getDataSource}>
</Button> </Button>
@ -424,10 +490,10 @@ const UserListPage: React.FC = () => {
dataSource={dataSource} dataSource={dataSource}
loading={loading} loading={loading}
rowKey="id" rowKey="id"
rowSelection={{ // rowSelection={{
selectedRowKeys, // selectedRowKeys,
onChange: onSelectChange, // onChange: onSelectChange,
}} // }}
pagination={{ pagination={{
current: currentPage, current: currentPage,
pageSize: pageSize, pageSize: pageSize,
@ -446,40 +512,47 @@ const UserListPage: React.FC = () => {
</div> </div>
</div> </div>
</div> </div>
<CreatGroup {visible && (
visible={visible} <CreatGroup
type={2} visible={visible}
title="新增终端分组" type={2}
onCancel={() => { title="新增终端分组"
setVisible(false); onCancel={() => {
}} setVisible(false);
selectedOrg={selectedOrg} }}
onOk={() => {}} selectedOrg={selectedOrg}
orgTreeData={orgTreeData} onOk={() => {
/> onSaveGroup();
<EditModal }}
selectedOrg={selectedOrg} orgTreeData={orgTreeData}
orgTreeData={orgTreeData} />
currentUserInfo={currentUserInfo} )}
onCancel={() => { {currentDeviceInfo.visible && (
setCurrentUserInfo({ <EditModal
recordData: {}, selectedOrg={selectedOrg}
visible: false, orgTreeData={orgTreeData}
}); currentDeviceInfo={currentDeviceInfo}
}} onCancel={() => {
onOk={() => {}} setCurrentDeviceInfo({
/> recordData: {},
visible: false,
});
}}
onOk={() => {
onDeviceSave();
}}
/>
)}
{bindUserDta.visible && ( {bindUserDta.visible && (
<BindUserModal <BindUserModal
dataDetial={bindUserDta} dataDetial={bindUserDta}
orgTreeData={orgTreeData}
onCancel={() => { onCancel={() => {
setBindUserData({ setBindUserData({
recordData: {}, recordData: {},
visible: false, visible: false,
}); });
}} }}
onOk={() => {}} onOk={() => {onBindUserSave()}}
/> />
)} )}
{bindImageDta.visible && ( {bindImageDta.visible && (

View File

@ -8,10 +8,8 @@ import SelectConponents from './table';
interface SelectedTableProps { interface SelectedTableProps {
placement?: PopoverProps['placement']; placement?: PopoverProps['placement'];
selectedOrg?: number;
onCancel?: () => void; onCancel?: () => void;
onOk?: (values: any) => void; onOk?: (values: any) => void;
orgTreeData?: User.OrganizationNode[];
value?: any; value?: any;
onChange: (values: any) => void; onChange: (values: any) => void;
} }
@ -19,7 +17,6 @@ interface SelectedTableProps {
const SelectedTable: React.FC<SelectedTableProps> = (props) => { const SelectedTable: React.FC<SelectedTableProps> = (props) => {
const { const {
placement = 'bottomLeft', placement = 'bottomLeft',
orgTreeData,
value: formValue, value: formValue,
onChange: onBindImageChange, onChange: onBindImageChange,
} = props; } = props;
@ -95,7 +92,6 @@ const SelectedTable: React.FC<SelectedTableProps> = (props) => {
const accessPopover = ( const accessPopover = (
<div style={{ width: '600px' }}> <div style={{ width: '600px' }}>
<SelectConponents <SelectConponents
treeData={orgTreeData}
onUserTableSelect={onUserTableSelect} onUserTableSelect={onUserTableSelect}
selectedRowKeys={selectedRowKeys} selectedRowKeys={selectedRowKeys}
/> />

View File

@ -1,14 +1,12 @@
/* eslint-disable @typescript-eslint/no-use-before-define */ /* eslint-disable @typescript-eslint/no-use-before-define */
import { IMAGES_TYPE_MAP } from '@/constants/images.constants';
import { ERROR_CODE } from '@/constants/constants'; import { ERROR_CODE } from '@/constants/constants';
import { getImagesList } from '@/services/images'; import { getImageList } from '@/services/terminal';
import { Input, Table, message,Tooltip } from 'antd'; import { Input, message, Table } from 'antd';
import type { ColumnsType } from 'antd/es/table'; import type { ColumnsType } from 'antd/es/table';
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import styles from './index.less'; import styles from './index.less';
interface TableProps { interface TableProps {
treeData?: User.OrganizationNode[];
selectedRowKeys?: any[]; selectedRowKeys?: any[];
onUserTableSelect?: (keys: any[], row: any[]) => void; onUserTableSelect?: (keys: any[], row: any[]) => void;
} }
@ -38,10 +36,13 @@ const TablePage: React.FC<TableProps> = ({
} }
setLoading(true); setLoading(true);
try { try {
const imagesRes = await getImagesList(params); const imagesRes: any = await getImageList(params);
if (imagesRes.error_code === ERROR_CODE) { console.log('imagesRes=========', imagesRes);
setData(imagesRes.data.data || []); const { code, data } = imagesRes || {};
setTotal(imagesRes.data.paging.total || 0); const { data: list = [], total = 0 } = data || {};
if (code === ERROR_CODE) {
setData(list);
setTotal(total);
setLoading(false); setLoading(false);
} else { } else {
message.error(imagesRes.message || '获取镜像列表失败'); message.error(imagesRes.message || '获取镜像列表失败');
@ -66,16 +67,6 @@ const TablePage: React.FC<TableProps> = ({
dataIndex: 'image_name', dataIndex: 'image_name',
render: (text: any) => <span>{text || ''}</span>, render: (text: any) => <span>{text || ''}</span>,
}, },
{
title: '桌面类型',
dataIndex: 'image_type',
key: 'image_type',
width: 200,
render: (text: number) => {
const key = text as keyof typeof IMAGES_TYPE_MAP;
return <Tooltip>{IMAGES_TYPE_MAP[key] || '--'}</Tooltip>;
},
},
]; ];
const handleSearch = (value: string) => { const handleSearch = (value: string) => {

View File

@ -1,5 +1,7 @@
// index.tsx // index.tsx
import { Button, Form, Input, message, Modal } from 'antd'; import { ERROR_CODE } from '@/constants/constants';
import { getBindImageList } from '@/services/terminal';
import { Button, Form, message, Modal } from 'antd';
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
import SelectedTable from '../ImageSelectedTable/index'; import SelectedTable from '../ImageSelectedTable/index';
import styles from './index.less'; import styles from './index.less';
@ -19,11 +21,20 @@ const BindUserModal: React.FC<UserEditModalProps> = ({
dataDetial, dataDetial,
}) => { }) => {
const { recordData, visible, selectedOrg } = dataDetial || {}; const { recordData, visible, selectedOrg } = dataDetial || {};
const { id: device_id } = recordData || {};
const [form] = Form.useForm(); const [form] = Form.useForm();
useEffect(() => { useEffect(() => {
// const initialValues = { user_group_id: [selectedOrg], status: 1 }; const params = { device_id: device_id };
// form.setFieldsValue(initialValues); getBindImageList(params).then((res: any) => {
const { code, data = [] } = res || {};
if (code === ERROR_CODE) {
if (data && data.length) {
const initialValues = { image_list: data };
form.setFieldsValue(initialValues);
}
}
});
}, [visible, form, recordData, selectedOrg]); }, [visible, form, recordData, selectedOrg]);
const handleOk = async () => { const handleOk = async () => {
@ -73,19 +84,19 @@ const BindUserModal: React.FC<UserEditModalProps> = ({
style={{ paddingTop: '20px', paddingBottom: '20px' }} style={{ paddingTop: '20px', paddingBottom: '20px' }}
> >
<Form.Item <Form.Item
name="user_list" name="image_list"
label="选择镜像" label="选择镜像"
rules={[{ required: true, message: '请输入终端型号' }]} rules={[{ required: true, message: '请输入终端型号' }]}
> >
<SelectedTable /> <SelectedTable />
</Form.Item> </Form.Item>
<Form.Item {/* <Form.Item
name="description" name="description"
label="描述内容" label="描述内容"
rules={[{ required: false, message: '请输入描述内容' }]} rules={[{ required: false, message: '请输入描述内容' }]}
> >
<Input.TextArea rows={4} /> <Input.TextArea rows={4} />
</Form.Item> </Form.Item> */}
</Form> </Form>
</div> </div>
</Modal> </Modal>

View File

@ -1,39 +1,129 @@
/* eslint-disable array-callback-return */
// index.tsx // index.tsx
import { Button, Form, Input, message, Modal } from 'antd'; import { ERROR_CODE } from '@/constants/constants';
import React, { useEffect } from 'react'; import { bindUserAdd, getBindUserList } from '@/services/terminal';
import { getGroupTree } from '@/services/userList';
import { Button, Form, message, Modal } from 'antd';
import React, { useEffect, useState } from 'react';
import SelectedTable from '../selectedTable'; import SelectedTable from '../selectedTable';
import styles from './index.less'; import styles from './index.less';
interface UserEditModalProps { interface UserEditModalProps {
// visible: boolean; // visible: boolean;
orgTreeData?: User.OrganizationNode[]; // orgTreeData?: User.OrganizationNode[];
onCancel: () => void; onCancel: () => void;
onOk: (values: any) => void; onOk: (values?: any) => void;
confirmLoading?: boolean; confirmLoading?: boolean;
dataDetial?: Termial.ModalBaseNode; dataDetial?: Termial.ModalBaseNode;
selectedOrg?: number; selectedOrg?: number;
} }
const BindUserModal: React.FC<UserEditModalProps> = ({ const BindUserModal: React.FC<UserEditModalProps> = ({
orgTreeData, // orgTreeData,
onCancel, onCancel,
onOk, onOk,
confirmLoading = false, confirmLoading = false,
dataDetial, dataDetial,
}) => { }) => {
const { recordData, visible, selectedOrg } = dataDetial || {}; const { recordData, visible } = dataDetial || {};
const { device_id, device_group_id } = recordData || {};
const [orgTreeData, setOrgTreeData] = useState<User.OrganizationNode[]>([]);
const [form] = Form.useForm(); const [form] = Form.useForm();
const getGroupList = async () => {
const params = {
type: 1,
};
try {
const result = await getGroupTree(params);
console.log('result=====', result);
const { code, data = [] } = result || {};
if (code === ERROR_CODE) {
if (data.length > 0) {
const { children = [] } = data[0] || {};
setOrgTreeData(children);
}
} else {
message.error(result.message || '获取终端分组失败');
}
} catch (err) {
message.error('获取终端分组失败');
}
};
useEffect(() => { useEffect(() => {
// const initialValues = { user_group_id: [selectedOrg], status: 1 }; getGroupList();
// form.setFieldsValue(initialValues); }, [visible]);
}, [visible, form, recordData, selectedOrg]);
useEffect(() => {
if (!device_id) return;
const payload = { device_id: device_id };
getBindUserList(payload).then((res: any) => {
console.log('res========', res);
const { code, data = [] } = res || {};
if (code === ERROR_CODE) {
if (data && data.length > 0) {
const list: any[] = [];
data.map((item: any) => {
const { type, user_id, user_name, user_group_id, user_group_name } =
item || {};
if (type === 1) {
list.push({ record_id: user_id, name: user_name, ...item });
} else {
list.push({
record_id: user_group_id,
name: user_group_name,
...item,
});
}
});
const initialValues = { user_list: list, status: 1 };
form.setFieldsValue(initialValues);
}
}
});
}, [visible, form, recordData]);
const handleOk = async () => { const handleOk = async () => {
try { try {
const values = await form.validateFields(); const values = await form.validateFields();
console.log("values=====",values) const { user_list = [] } = values || {};
onOk(values); const list: any[] = [];
if (user_list && user_list.length > 0) {
user_list.forEach((item: any) => {
const { record_id, type, id } = item || {};
if (type === 1) {
// 用户
list.push({
user_id: record_id,
id: id,
device_id,
device_group_id,
type: type,
});
} else {
//用户分组
list.push({
user_group_id: record_id,
id: id,
device_id: device_id,
device_group_id,
type: type,
});
}
});
const payload = {
data: list,
};
bindUserAdd(payload)
.then(() => {
message.success('绑定成功');
onOk();
})
.catch(() => {});
}
console.log('list=====', list);
onOk(list);
} catch (error) { } catch (error) {
message.error('请检查表单字段'); message.error('请检查表单字段');
} }
@ -78,17 +168,17 @@ const BindUserModal: React.FC<UserEditModalProps> = ({
<Form.Item <Form.Item
name="user_list" name="user_list"
label="选择用户" label="选择用户"
rules={[{ required: true, message: '请输入终端型号' }]} rules={[{ required: true, message: '请选择绑定用户' }]}
> >
<SelectedTable orgTreeData={orgTreeData} /> <SelectedTable orgTreeData={orgTreeData} />
</Form.Item> </Form.Item>
<Form.Item {/* <Form.Item
name="description" name="description"
label="描述内容" label="描述内容"
rules={[{ required: false, message: '请输入描述内容' }]} rules={[{ required: false, message: '请输入描述内容' }]}
> >
<Input.TextArea rows={4} /> <Input.TextArea rows={4} />
</Form.Item> </Form.Item> */}
</Form> </Form>
</div> </div>
</Modal> </Modal>

View File

@ -1,16 +1,15 @@
// index.tsx // index.tsx
import { DEVICE_TYPE_OPTIONS,ERROR_CODE } from '@/constants/constants'; import { DEVICE_TYPE_OPTIONS, ERROR_CODE } from '@/constants/constants';
import { } from '@/constants/constants'; import { getDevieDetial, saveDevice } from '@/services/terminal';
import { saveDevice } from '@/services/terminal';
import { Button, Form, Input, message, Modal, Select, TreeSelect } from 'antd'; import { Button, Form, Input, message, Modal, Select, TreeSelect } from 'antd';
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
interface UserEditModalProps { interface UserEditModalProps {
orgTreeData: User.OrganizationNode[]; orgTreeData: User.OrganizationNode[];
onCancel: () => void; onCancel: () => void;
onOk?: (values: any) => void; onOk?: (values?: any) => void;
confirmLoading?: boolean; confirmLoading?: boolean;
currentUserInfo?: Termial.ModalBaseNode; currentDeviceInfo?: Termial.ModalBaseNode;
selectedOrg?: number; selectedOrg?: number;
} }
@ -19,27 +18,34 @@ const UserEditModal: React.FC<UserEditModalProps> = ({
onCancel, onCancel,
onOk, onOk,
confirmLoading = false, confirmLoading = false,
currentUserInfo, currentDeviceInfo,
}) => { }) => {
const { recordData, visible, selectedOrg } = currentUserInfo || {}; const { recordData, visible, selectedOrg } = currentDeviceInfo || {};
const { user_id } = recordData || {}; const { id, device_name } = recordData || {};
const [form] = Form.useForm(); const [form] = Form.useForm();
useEffect(() => { useEffect(() => {
const initialValues = { user_group_id: [selectedOrg], status: 1 }; const params = { id: id };
form.setFieldsValue(initialValues); getDevieDetial(params).then((res: any) => {
console.log('res=======', res);
const { code, data } = res || {};
if (code === ERROR_CODE) {
const initialValues = { ...data };
form.setFieldsValue(initialValues);
}
});
}, [visible, form, recordData, selectedOrg]); }, [visible, form, recordData, selectedOrg]);
const handleOk = async () => { const handleOk = async () => {
try { try {
const values = await form.validateFields(); const values = await form.validateFields();
const params = { ...values, user_id }; const params = { ...values, id };
const res = await saveDevice(params); const res: any = await saveDevice(params);
const { error_code } = res || {}; const { code } = res || {};
if (error_code === ERROR_CODE) { if (code === ERROR_CODE) {
message.success('保存成功'); message.success('保存成功');
onOk();
} }
} catch (error) { } catch (error) {
message.error('保存失败'); message.error('保存失败');
} }
@ -58,7 +64,7 @@ const UserEditModal: React.FC<UserEditModalProps> = ({
return ( return (
<Modal <Modal
title={user_id ? '编辑用户信息' : '新增用户'} title={id ? `${device_name}终端信息修改` : '新增终端'}
open={visible} open={visible}
onCancel={onCancel} onCancel={onCancel}
onOk={handleOk} onOk={handleOk}
@ -124,24 +130,19 @@ const UserEditModal: React.FC<UserEditModalProps> = ({
/> />
</Form.Item> </Form.Item>
<Form.Item <Form.Item
name="device_typ" name="device_type"
label="终端类型" label="终端类型"
rules={[{ required: false, message: '请输入终端型号' }]} rules={[{ required: true, message: '请输入终端型号' }]}
> >
<Select options={DEVICE_TYPE_OPTIONS} /> <Select options={DEVICE_TYPE_OPTIONS} />
</Form.Item> </Form.Item>
<Form.Item
{/* <Form.Item name="model"
name="status" label="型号"
label="认证方式" rules={[{ required: false, message: '请输入显示名称' }]}
rules={[{ required: false, message: '请选择认证方式' }]}
> >
<Radio.Group optionType="button"> <Input />
<Radio value={1}></Radio> </Form.Item>
<Radio value={2}></Radio>
</Radio.Group>
</Form.Item> */}
<Form.Item <Form.Item
name="ip_addr" name="ip_addr"
label="IP地址" label="IP地址"
@ -150,20 +151,12 @@ const UserEditModal: React.FC<UserEditModalProps> = ({
<Input placeholder="请输入IP地址" /> <Input placeholder="请输入IP地址" />
</Form.Item> </Form.Item>
<Form.Item <Form.Item
name="mac addr" name="mac_addr"
label="MAC地址" label="MAC地址"
rules={[{ required: false, message: '请输入MAC地址' }]} rules={[{ required: false, message: '请输入MAC地址' }]}
> >
<Input /> <Input />
</Form.Item> </Form.Item>
{/* <Form.Item
name="终端厂商"
label="mac_addr"
rules={[{ required: true, message: '请输入终端厂商' }]}
>
<Input />
</Form.Item> */}
<Form.Item <Form.Item
name="description" name="description"
label="描述" label="描述"

View File

@ -1,4 +1,7 @@
import { Input, Table, TreeSelect } from 'antd'; import { ERROR_CODE } from '@/constants/constants';
import { getUserList } from '@/services/userList';
import { Input, Table, Tooltip, TreeSelect, message } from 'antd';
import type { ColumnsType } from 'antd/es/table';
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import styles from './index.less'; import styles from './index.less';
@ -21,30 +24,64 @@ const TablePage: React.FC<TableProps> = ({
selectedRowKeys, selectedRowKeys,
}) => { }) => {
const [data, setData] = useState<any[]>([]); const [data, setData] = useState<any[]>([]);
// const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]); const [loading, setLoading] = useState<boolean>(false);
const [selectedOrg, setSelectedOrg] = useState<any>();
const [searchText, setSearchText] = useState(''); const [searchText, setSearchText] = useState('');
const [currentPage, setCurrentPage] = useState(1); const [currentPage, setCurrentPage] = useState(1);
const [pageSize, setPageSize] = useState(20); const [pageSize, setPageSize] = useState(20);
const [total, setTotal] = useState(0); const [total, setTotal] = useState(0);
// Mock data generation const getDataSource = async () => {
useEffect(() => { const params: any = {
const mockData: DataType[] = []; page_size: pageSize,
for (let i = 0; i < 100; i++) { page_num: currentPage,
mockData.push({ };
id: i + 99, if (selectedOrg) {
name: `User ${i}`, params.user_group_id = selectedOrg;
});
} }
setData(mockData); if (searchText) {
setTotal(mockData.length); params.user_name = searchText;
}, []); }
setLoading(true);
try {
const result = await getUserList(params);
console.log('res======', result);
const { code, data = {} } = result || {};
const { data: list, total = 0 } = data || {};
if (code === ERROR_CODE) {
setData(list || []);
setTotal(total);
setLoading(false);
} else {
message.error(result.message || '获取用户列表失败');
setLoading(false);
}
} catch (err) {
message.error('获取用户列表失败');
}
};
const columns: TableProps<DataType>['columns'] = [ useEffect(() => {
getDataSource();
}, [selectedOrg, searchText]);
const columns: ColumnsType<User.UserItem> = [
{ {
title: 'Name', title: '序号',
dataIndex: 'name', dataIndex: 'order',
sorter: (a, b) => a.name.localeCompare(b.name), key: 'order',
width: 80,
align: 'center',
render: (_: any, record: any, index: number) => <span>{index + 1}</span>,
},
{
title: '用户名',
dataIndex: 'user_name',
key: 'user_name',
align: 'center',
render: (text) => {
return <Tooltip>{text || '--'}</Tooltip>;
},
}, },
]; ];
@ -63,16 +100,21 @@ const TablePage: React.FC<TableProps> = ({
setPageSize(size); setPageSize(size);
}; };
const onTreeChange = (newValue: any) => {
setSelectedOrg(newValue);
};
return ( return (
<div className={styles.content_wrap}> <div className={styles.content_wrap}>
<div className={styles.search_wrap}> <div className={styles.search_wrap}>
<TreeSelect <TreeSelect
style={{ width: '300px' }} style={{ width: '300px' }}
showSearch showSearch
allowClear={false} allowClear={true}
treeDefaultExpandAll treeDefaultExpandAll
placeholder="请选择终端分组" placeholder="请选择用户分组"
treeData={treeData} treeData={treeData}
onChange={onTreeChange}
fieldNames={{ label: 'name', value: 'id', children: 'children' }} fieldNames={{ label: 'name', value: 'id', children: 'children' }}
/> />
<Input.Search <Input.Search
@ -85,9 +127,9 @@ const TablePage: React.FC<TableProps> = ({
</div> </div>
<Table <Table
// rowSelection={rowSelection}
columns={columns} columns={columns}
dataSource={data} dataSource={data}
loading={loading}
rowKey="id" rowKey="id"
rowSelection={{ rowSelection={{
selectedRowKeys, selectedRowKeys,

View File

@ -47,12 +47,13 @@ const SelectedTable: React.FC<SelectedTableProps> = (props) => {
formValue.forEach((item: any) => { formValue.forEach((item: any) => {
if (item.type === 1) { if (item.type === 1) {
userList.push(item); userList.push(item);
userId.push(item.id); userId.push(item.record_id);
} else { } else {
groupList.push(item); groupList.push(item);
groupId.push(item.id); groupId.push(item.record_id);
} }
}); });
setTableData(formValue);
setSelectedRowKeys(userId); setSelectedRowKeys(userId);
setSelectedRows(userList); setSelectedRows(userList);
setCheckedKeys(groupId); setCheckedKeys(groupId);
@ -63,10 +64,10 @@ const SelectedTable: React.FC<SelectedTableProps> = (props) => {
// const onOrgSelect = (selectedKeys: React.Key[], info: any) => {}; // const onOrgSelect = (selectedKeys: React.Key[], info: any) => {};
const onCheckChange = (keys: any[], info: any) => { const onCheckChange = (keys: any[], info: any) => {
const { checkedNodes } = info; // const { checkedNodes } = info;
console.log('info=========', info); console.log('info=========', info);
setCheckedKeys(keys); setCheckedKeys(keys);
setCheckedRow(checkedNodes); setCheckedRow(info);
}; };
const onHnadleCancel = () => { const onHnadleCancel = () => {
@ -82,15 +83,15 @@ const SelectedTable: React.FC<SelectedTableProps> = (props) => {
// 用户 // 用户
(selectedRows || []).forEach((item) => { (selectedRows || []).forEach((item) => {
list.push({ list.push({
id: item.id, record_id: item.id,
name: item.name, name: item.user_name,
type: 1, type: 1,
}); });
}); });
// 用户组 // 用户组
checkedRow.forEach((item) => { (checkedRow || []).forEach((item) => {
list.push({ list.push({
id: item.id, record_id: item.id,
name: item.name, name: item.name,
type: 2, type: 2,
}); });
@ -116,13 +117,13 @@ const SelectedTable: React.FC<SelectedTableProps> = (props) => {
console.log('record=====handleDelete', record); console.log('record=====handleDelete', record);
if (record) { if (record) {
// 单个删除 // 单个删除
const { id } = record || {}; const { record_id } = record || {};
const newData = tableData.filter((item) => item.id !== id); const newData = tableData.filter((item) => item.record_id !== record_id);
setTableData(newData); setTableData(newData);
} else { } else {
// 批量删除 // 批量删除
const newData = tableData.filter( const newData = tableData.filter(
(item) => !bindTableKeys.includes(item.id), (item) => !bindTableKeys.includes(item.record_id),
); );
setTableData(newData); setTableData(newData);
setSelectedRowKeys([]); setSelectedRowKeys([]);
@ -131,39 +132,39 @@ const SelectedTable: React.FC<SelectedTableProps> = (props) => {
}; };
const getColumns = (): ColumnsType<any> => { const getColumns = (): ColumnsType<any> => {
const columns: ColumnsType<any> = [ const columns: ColumnsType<any> = [
{ {
title: '序号', title: '序号',
dataIndex: 'order', dataIndex: 'order',
key: 'order', key: 'order',
width: 80, width: 80,
render: (_, record, index) => <span>{index + 1}</span>, render: (_, record, index) => <span>{index + 1}</span>,
}, },
{ {
title: '名称', title: '名称',
dataIndex: 'name', dataIndex: 'name',
key: 'name', key: 'name',
}, },
{ {
title: '类型', title: '类型',
dataIndex: 'type', dataIndex: 'type',
key: 'type', key: 'type',
render: (text) => ( render: (text) => (
<span>{text == 1 ? '用户' : text == 2 ? '用户组' : ''}</span> <span>{text == 1 ? '用户' : text == 2 ? '用户组' : ''}</span>
), ),
}, },
{ {
title: '操作', title: '操作',
key: 'action', key: 'action',
render: (_, record) => ( render: (_, record) => (
<Button type="link" danger onClick={() => handleDelete(record)}> <Button type="link" onClick={() => handleDelete(record)}>
</Button> </Button>
), ),
} },
]; ];
return columns; return columns;
}; };
const accessPopover = ( const accessPopover = (
<div style={{ width: '600px' }}> <div style={{ width: '600px' }}>
@ -178,6 +179,7 @@ const SelectedTable: React.FC<SelectedTableProps> = (props) => {
<CustomTree <CustomTree
checkable={true} checkable={true}
multiple={true} multiple={true}
checkStrictly={true}
treeData={orgTreeData} treeData={orgTreeData}
titleField="name" titleField="name"
keyField="id" keyField="id"
@ -240,12 +242,12 @@ const SelectedTable: React.FC<SelectedTableProps> = (props) => {
<Popconfirm <Popconfirm
title="" title=""
description="删除操作不可逆,请确认是否删除?" description="删除操作不可逆,请确认是否删除?"
onConfirm={()=>handleDelete()} onConfirm={() => handleDelete()}
disabled={bindTableKeys.length === 0} disabled={bindTableKeys.length === 0}
okText="删除" okText="删除"
cancelText="取消" cancelText="取消"
> >
<Button disabled={bindTableKeys.length === 0}></Button> <Button disabled={bindTableKeys.length === 0}></Button>
</Popconfirm> </Popconfirm>
</div> </div>
</Popover> </Popover>
@ -254,9 +256,9 @@ const SelectedTable: React.FC<SelectedTableProps> = (props) => {
dataSource={tableData} dataSource={tableData}
onDelete={handleDelete} onDelete={handleDelete}
scrollY={400} scrollY={400}
rowKey="id" rowKey="record_id"
pagination={false} pagination={false}
columns={getColumns()} columns={getColumns()}
rowSelection={{ rowSelection={{
bindTableKeys, bindTableKeys,
onChange: onSelectChange, onChange: onSelectChange,

View File

@ -62,13 +62,13 @@ const UserListPage: React.FC = () => {
// 获取用户列表数据 // 获取用户列表数据
useEffect(() => { useEffect(() => {
getDataSource(); getDataSource();
}, [searchText,selectedOrg, currentPage, pageSize]); }, [searchText, selectedOrg, currentPage, pageSize]);
const getUserGroupList = async () => { const getUserGroupList = async () => {
setSpinning(true);
const params = { const params = {
type: 1, type: 1,
}; };
setSpinning(true);
try { try {
const result = await getGroupTree(params); const result = await getGroupTree(params);
console.log('result=====', result); console.log('result=====', result);
@ -144,24 +144,24 @@ const UserListPage: React.FC = () => {
setTotal(total); setTotal(total);
setLoading(false); setLoading(false);
} else { } else {
message.error(result.message || '获取终端列表失败'); message.error(result.message || '获取用户列表失败');
setLoading(false); setLoading(false);
} }
} catch (err) { } catch (err) {
message.error('获取终端列表失败'); message.error('获取用户列表失败');
setLoading(false); setLoading(false);
} }
}; };
const onDelete = (user?: User.UserItem) => { const onDelete = (user?: User.UserItem) => {
const { user_id } = user || {}; const { id } = user || {};
const payload = { const payload = {
ids: user_id ? [user_id] : selectedRowKeys, id: id ? id : selectedRowKeys,
}; };
deleteUser(payload as any).then((res) => { deleteUser(payload as any).then((res) => {
console.log('res=====', res); console.log('res=====', res);
const { success } = res || {}; const { code } = res || {};
if (success) { if (code === ERROR_CODE) {
message.success('删除成功'); message.success('删除成功');
setSelectedRowKeys([]); setSelectedRowKeys([]);
getDataSource(); getDataSource();
@ -267,7 +267,7 @@ const UserListPage: React.FC = () => {
key: 'cell_phone', key: 'cell_phone',
width: 150, width: 150,
align: 'center', align: 'center',
render: (text:any) => { render: (text: any) => {
return <Tooltip>{text || '--'}</Tooltip>; return <Tooltip>{text || '--'}</Tooltip>;
}, },
}, },
@ -277,7 +277,7 @@ const UserListPage: React.FC = () => {
key: 'birthday', key: 'birthday',
width: 150, width: 150,
align: 'center', align: 'center',
render: (text:any) => { render: (text: any) => {
return <Tooltip>{text || '--'}</Tooltip>; return <Tooltip>{text || '--'}</Tooltip>;
}, },
}, },
@ -287,7 +287,7 @@ const UserListPage: React.FC = () => {
key: 'identity_no', key: 'identity_no',
width: 150, width: 150,
align: 'center', align: 'center',
render: (text:any) => { render: (text: any) => {
return <Tooltip>{text || '--'}</Tooltip>; return <Tooltip>{text || '--'}</Tooltip>;
}, },
}, },
@ -299,9 +299,9 @@ const UserListPage: React.FC = () => {
fixed: 'right', fixed: 'right',
render: (_, record) => ( render: (_, record) => (
<div style={{ display: 'flex' }}> <div style={{ display: 'flex' }}>
<Button type="link" onClick={() => handlePassword(record)}> {/* <Button type="link" onClick={() => handlePassword(record)}>
</Button> </Button> */}
<Button type="link" onClick={() => handleEditUserInfo(record)}> <Button type="link" onClick={() => handleEditUserInfo(record)}>
</Button> </Button>
@ -346,6 +346,14 @@ const UserListPage: React.FC = () => {
getUserGroupList(); getUserGroupList();
}; };
const onSaveUserCallback = () => {
setCurrentUserInfo({
recordData: {},
visible: false,
});
getDataSource();
};
const onDeleteGroup = async () => { const onDeleteGroup = async () => {
if (selectedOrg) { if (selectedOrg) {
try { try {
@ -440,7 +448,7 @@ const UserListPage: React.FC = () => {
> >
</Button> </Button>
<Popconfirm {/* <Popconfirm
title="" title=""
description="删除操作不可逆,请确认是否删除?" description="删除操作不可逆,请确认是否删除?"
onConfirm={() => onDelete()} onConfirm={() => onDelete()}
@ -452,10 +460,11 @@ const UserListPage: React.FC = () => {
<Button <Button
disabled={selectedRowKeys.length === 0} disabled={selectedRowKeys.length === 0}
style={{ marginRight: '8px' }} style={{ marginRight: '8px' }}
icon={<DeleteOutlined />}
> >
</Button> </Button>
</Popconfirm> </Popconfirm> */}
<Button style={{ marginRight: '8px' }} onClick={getDataSource}> <Button style={{ marginRight: '8px' }} onClick={getDataSource}>
</Button> </Button>
@ -494,38 +503,44 @@ const UserListPage: React.FC = () => {
return `${total}条数据`; return `${total}条数据`;
}, },
}} }}
rowSelection={{ // rowSelection={{
selectedRowKeys, // selectedRowKeys,
onChange: onSelectChange, // onChange: onSelectChange,
}} // }}
scroll={{ x: 'max-content', y: 55 * 12 }} scroll={{ x: 'max-content', y: 55 * 12 }}
/> />
</div> </div>
</div> </div>
</div> </div>
<CreatGroup {visible && (
visible={visible} <CreatGroup
type={1} visible={visible}
title="新增用户分组" type={1}
selectedOrg={selectedOrg} title="新增用户分组"
onCancel={() => { selectedOrg={selectedOrg}
setVisible(false); onCancel={() => {
}} setVisible(false);
onOk={onSaveGroup} }}
orgTreeData={orgTreeData} onOk={onSaveGroup}
/> orgTreeData={orgTreeData}
<UserEditModal />
selectedOrg={selectedOrg} )}
orgTreeData={orgTreeData} {currentUserInfo.visible && (
currentUserInfo={currentUserInfo} <UserEditModal
onCancel={() => { selectedOrg={selectedOrg}
setCurrentUserInfo({ orgTreeData={orgTreeData}
recordData: {}, currentUserInfo={currentUserInfo}
visible: false, onCancel={() => {
}); setCurrentUserInfo({
}} recordData: {},
onOk={() => {}} visible: false,
/> });
}}
onOk={() => {
onSaveUserCallback();
}}
/>
)}
<PasswordResetModal <PasswordResetModal
visible={eidtPassword.visible} visible={eidtPassword.visible}
onCancel={() => { onCancel={() => {

View File

@ -1,6 +1,10 @@
// index.tsx import {
import { GENDER_OPTIONS, USER_TYPE_OPTIONS } from '@/constants/constants'; ERROR_CODE,
import { idIDIntl } from '@ant-design/pro-components'; GENDER_OPTIONS,
PRIOPRITY_OPTIONS,
USER_TYPE_OPTIONS,
} from '@/constants/constants';
import { addUser, editUser, getUserById } from '@/services/userList';
import { import {
Button, Button,
Form, Form,
@ -10,6 +14,7 @@ import {
Radio, Radio,
Select, Select,
TreeSelect, TreeSelect,
DatePicker
} from 'antd'; } from 'antd';
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
@ -17,7 +22,7 @@ interface UserEditModalProps {
// visible: boolean; // visible: boolean;
orgTreeData: User.OrganizationNode[]; orgTreeData: User.OrganizationNode[];
onCancel: () => void; onCancel: () => void;
onOk: (values: any) => void; onOk: (values?: any) => void;
confirmLoading?: boolean; confirmLoading?: boolean;
currentUserInfo?: User.UserModalBaseNode; currentUserInfo?: User.UserModalBaseNode;
selectedOrg?: number; selectedOrg?: number;
@ -35,14 +40,31 @@ const UserEditModal: React.FC<UserEditModalProps> = ({
const [form] = Form.useForm(); const [form] = Form.useForm();
useEffect(() => { useEffect(() => {
const initialValues = { user_group_id: [selectedOrg], status: 1 }; if (id) {
form.setFieldsValue(initialValues); getUserById({ id }).then((res) => {
const { data } = res;
form.setFieldsValue(data);
});
} else {
const initialValues = { user_group_id: [selectedOrg], status: 1 };
form.setFieldsValue(initialValues);
}
}, [visible, form, recordData, selectedOrg]); }, [visible, form, recordData, selectedOrg]);
const handleOk = async () => { const handleOk = async () => {
const values = await form.validateFields();
try { try {
const values = await form.validateFields(); const params = { ...values };
onOk(values); if (id) {
params.id = id;
}
const result: any = id ? await editUser(params) : await addUser(params);
const { code } = result || {};
if (code === ERROR_CODE) {
onOk();
} else {
message.error('保存失败');
}
} catch (error) { } catch (error) {
message.error('请检查表单字段'); message.error('请检查表单字段');
} }
@ -53,13 +75,41 @@ const UserEditModal: React.FC<UserEditModalProps> = ({
types: { types: {
email: '${label} is not a valid email!', email: '${label} is not a valid email!',
number: '${label} is not a valid number!', number: '${label} is not a valid number!',
cell_phone: '${label} is not a valid cell phone number!',
}, },
number: { number: {
range: '${label} must be between ${min} and ${max}', range: '${label} must be between ${min} and ${max}',
}, },
}; };
// Password validation rule
const passwordValidator = (_: any, value: string) => {
if (!value) {
return Promise.reject('请输入新密码');
}
if (value.length < 6) {
return Promise.reject('密码长度至少6位');
}
const hasNumber = /\d/.test(value);
const hasLetter = /[a-zA-Z]/.test(value);
// const hasSpecialChar = /[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]/.test(value);
if (!hasNumber) {
return Promise.reject('密码必须包含数字');
}
if (!hasLetter) {
return Promise.reject('密码必须包含字母');
}
// if (!hasSpecialChar) {
// return Promise.reject('密码必须包含特殊字符');
// }
return Promise.resolve();
};
return ( return (
<Modal <Modal
title={id ? '编辑用户信息' : '新增用户'} title={id ? '编辑用户信息' : '新增用户'}
@ -98,24 +148,23 @@ const UserEditModal: React.FC<UserEditModalProps> = ({
validateMessages={validateMessages} validateMessages={validateMessages}
> >
<Form.Item <Form.Item
name="loginName" name="user_name"
label="登录名"
rules={[
{ required: true, message: '请输入登录名' },
{ min: 3, message: '登录名至少3个字符' },
]}
>
<Input placeholder="请输入登录名" />
</Form.Item>
<Form.Item
name="userName"
label="用户姓名" label="用户姓名"
rules={[{ required: true, message: '请输入用户姓名' }]} rules={[{ required: true, message: '请输入用户姓名' }]}
> >
<Input placeholder="请输入用户姓名" /> <Input placeholder="请输入用户姓名" />
</Form.Item> </Form.Item>
<Form.Item
name="password"
label="密码"
rules={[{ required: true, validator: passwordValidator }]}
help="密码必须包含数字和字母,字母区分大小写,且至少6位"
style={{ marginBottom: '30px' }}
>
<Input.Password placeholder="请输入密码" />
</Form.Item>
<Form.Item <Form.Item
name="user_group_id" name="user_group_id"
label="用户分组" label="用户分组"
@ -149,6 +198,16 @@ const UserEditModal: React.FC<UserEditModalProps> = ({
> >
<Select placeholder="请选择用户类别" options={USER_TYPE_OPTIONS} /> <Select placeholder="请选择用户类别" options={USER_TYPE_OPTIONS} />
</Form.Item> </Form.Item>
<Form.Item name="birthday" label="出生日期" >
<DatePicker style={{width:"414px"}}/>
</Form.Item>
<Form.Item
name="priority"
label="优先级"
rules={[{ required: false, message: '请选择用户优先级' }]}
>
<Select placeholder="请选择用户类别" options={PRIOPRITY_OPTIONS} />
</Form.Item>
<Form.Item <Form.Item
name="gender" name="gender"
label="性别" label="性别"

View File

@ -6,7 +6,7 @@ import React, { useEffect, useState } from 'react';
interface CreatGroupProps { interface CreatGroupProps {
title: string; title: string;
type:number; type: number;
visible: boolean; visible: boolean;
selectedOrg?: number; selectedOrg?: number;
onCancel: () => void; onCancel: () => void;
@ -22,14 +22,14 @@ const CreatGroup: React.FC<CreatGroupProps> = (props) => {
onOk, onOk,
orgTreeData, orgTreeData,
selectedOrg, selectedOrg,
type type,
} = props; } = props;
const [loading, setLoading] = useState<boolean>(false); const [loading, setLoading] = useState<boolean>(false);
const [form] = Form.useForm(); const [form] = Form.useForm();
useEffect(() => { useEffect(() => {
if (selectedOrg) { if (selectedOrg) {
const initialValues = { parent_id: [selectedOrg] }; const initialValues = { parent_id: selectedOrg };
form.setFieldsValue(initialValues); form.setFieldsValue(initialValues);
} }
}, [visible, form, selectedOrg]); }, [visible, form, selectedOrg]);
@ -49,10 +49,11 @@ const CreatGroup: React.FC<CreatGroupProps> = (props) => {
try { try {
console.log('values=====', values); console.log('values=====', values);
const { name, parent_id } = values || {}; const { name, parent_id } = values || {};
const params: any = { name, type: type }; const params: any = { name, type: type, parent_id: parent_id };
if (parent_id) { // if (parent_id) {
params.parent_id = parent_id; // params.parent_id =
} // parent_id && parent_id.length > 0 ? parent_id[0] : null;
// }
const res = await addUserGroup(params); const res = await addUserGroup(params);
setLoading(false); setLoading(false);
const { code } = res || {}; const { code } = res || {};

View File

@ -1,28 +1,74 @@
import { request } from '@umijs/max'; import { request } from '@umijs/max';
const BASE_URL = '/api/v1/terminal'; const BASE_URL = '/api/nex/v1';
// 根据终端序列号查询镜像列表 // 根据终端序列号查询镜像列表
export async function getTerminalList(params:any) { export async function getTerminalList(params: any) {
// console.log('终端列表 params', params); return request<Termial.Termial_ListInfo>(`${BASE_URL}/device/select/page`, {
return request<Termial.Termial_ListInfo>(`${BASE_URL}/query/devicelist`, {
method: 'POST', method: 'POST',
data: params, data: params,
}); });
} }
export async function deleteDevice(params:any) { // 根据id查询终端信息
// console.log('终端列表 params', params); export async function getDevieDetial(params: any) {
return request<Termial.Termial_ListInfo>(`${BASE_URL}/delete/device`, { return request<Termial.Termial_ListInfo>(`${BASE_URL}/device/query`, {
method: 'POST', method: 'POST',
data: params, data: params,
}); });
} }
export async function saveDevice(params:any) { //删除终端
// console.log('终端列表 params', params); export async function deleteDevice(params: any) {
return request<Termial.Termial_ListInfo>(`${BASE_URL}/save/device`, { return request<Termial.Termial_ListInfo>(`${BASE_URL}/device/delete`, {
method: 'POST', method: 'POST',
data: params, data: params,
}); });
} }
// 终端编辑保存
export async function saveDevice(params: any) {
return request<Termial.Termial_ListInfo>(`${BASE_URL}/device/update`, {
method: 'POST',
data: params,
});
}
// 终端绑定用户
export async function bindUserAdd(params: any) {
return request<Termial.Termial_ListInfo>(`${BASE_URL}/device/user/mapping/add`, {
method: 'POST',
data: params,
});
}
export async function getBindUserList(params: any) {
return request<Termial.Termial_ListInfo>(`${BASE_URL}/device/user/mapping/select`, {
method: 'POST',
data: params,
});
}
// 镜像列表
export async function getImageList(params: any) {
return request<Termial.Termial_ListInfo>(`${BASE_URL}/image/select/page`, {
method: 'POST',
data: params,
});
}
// 终端绑定镜像列表
export async function getBindImageList(params: any) {
return request<Termial.Termial_ListInfo>(`${BASE_URL}/device/image/mapping/select`, {
method: 'POST',
data: params,
});
}
// 终端绑定镜像列表
export async function getBindImageAdd(params: any) {
return request<Termial.Termial_ListInfo>(`${BASE_URL}/device/image/mapping/add`, {
method: 'POST',
data: params,
});
}

View File

@ -58,7 +58,7 @@ export async function getUserById(body?: any) {
//删除用户 //删除用户
export async function deleteUser(body?: any) { export async function deleteUser(body?: any) {
return request<any>(`${BASE_URL}/user/delete`, { return request<any>(`${BASE_URL}/user/delete`, {
method: 'DELETE', method: 'POST',
data: body, data: body,
}); });
} }

View File

@ -15,6 +15,7 @@ declare namespace User {
} }
interface UserItem { interface UserItem {
id?:number;
user_id?: number; user_id?: number;
user_group_id?: number; user_group_id?: number;
user_group_name?: number; user_group_name?: number;

View File

@ -6665,7 +6665,7 @@ minimist-options@4.1.0:
resolved "https://registry.npmmirror.com/minipass/-/minipass-7.1.2.tgz#93a9626ce5e5e66bd4db86849e7515e92340a707" resolved "https://registry.npmmirror.com/minipass/-/minipass-7.1.2.tgz#93a9626ce5e5e66bd4db86849e7515e92340a707"
integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw== integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==
moment@^2.24.0, moment@^2.29.2, moment@^2.29.4: moment@^2.24.0, moment@^2.29.2, moment@^2.29.4, moment@^2.30.1:
version "2.30.1" version "2.30.1"
resolved "https://registry.npmmirror.com/moment/-/moment-2.30.1.tgz#f8c91c07b7a786e30c59926df530b4eac96974ae" resolved "https://registry.npmmirror.com/moment/-/moment-2.30.1.tgz#f8c91c07b7a786e30c59926df530b4eac96974ae"
integrity sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how== integrity sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==
@ -9412,7 +9412,16 @@ string-convert@^0.2.0:
resolved "https://registry.npmmirror.com/string-convert/-/string-convert-0.2.1.tgz#6982cc3049fbb4cd85f8b24568b9d9bf39eeff97" resolved "https://registry.npmmirror.com/string-convert/-/string-convert-0.2.1.tgz#6982cc3049fbb4cd85f8b24568b9d9bf39eeff97"
integrity sha512-u/1tdPl4yQnPBjnVrmdLo9gtuLvELKsAoRapekWggdiQNvvvum+jYF329d84NAa660KQw7pB2n36KrIKVoXa3A== integrity sha512-u/1tdPl4yQnPBjnVrmdLo9gtuLvELKsAoRapekWggdiQNvvvum+jYF329d84NAa660KQw7pB2n36KrIKVoXa3A==
"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: "string-width-cjs@npm:string-width@^4.2.0":
version "4.2.3"
resolved "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
dependencies:
emoji-regex "^8.0.0"
is-fullwidth-code-point "^3.0.0"
strip-ansi "^6.0.1"
string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
version "4.2.3" version "4.2.3"
resolved "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" resolved "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
@ -9502,7 +9511,14 @@ string_decoder@~1.1.1:
dependencies: dependencies:
safe-buffer "~5.1.0" safe-buffer "~5.1.0"
"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: "strip-ansi-cjs@npm:strip-ansi@^6.0.1":
version "6.0.1"
resolved "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
dependencies:
ansi-regex "^5.0.1"
strip-ansi@^6.0.0, strip-ansi@^6.0.1:
version "6.0.1" version "6.0.1"
resolved "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" resolved "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
@ -10260,7 +10276,16 @@ word-wrap@^1.2.5:
resolved "https://registry.npmmirror.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" resolved "https://registry.npmmirror.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34"
integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: "wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
version "7.0.0"
resolved "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
dependencies:
ansi-styles "^4.0.0"
string-width "^4.1.0"
strip-ansi "^6.0.0"
wrap-ansi@^7.0.0:
version "7.0.0" version "7.0.0"
resolved "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" resolved "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==