feat(前端):用户、终端组织树
parent
b92552f653
commit
c3d3ab36e3
|
@ -43,5 +43,11 @@ export default defineConfig({
|
|||
},
|
||||
],
|
||||
npmClient: 'pnpm',
|
||||
proxy: {
|
||||
'/api/nex/v1/': {
|
||||
target: 'http://10.100.51.85:8112',
|
||||
// changeOrigin: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
@ -0,0 +1,120 @@
|
|||
export default {
|
||||
'POST /api/v1/terminal/query/devicelist': (req: any, res: any) => {
|
||||
const { page_size, page_num } = req.body;
|
||||
const data = [];
|
||||
|
||||
for (let i = 1; i <= page_size; i++) {
|
||||
data.push({
|
||||
id: i,
|
||||
device_id: i,
|
||||
device_name: `终端${(page_num - 1) * page_size + i}`,
|
||||
device_group_id: 1,
|
||||
device_group_name: '分组名称',
|
||||
device_type: 1,
|
||||
ip_addr: '10.10.10.10',
|
||||
mac_addr: 'fd:12:12:12:12:12',
|
||||
model: 'model',
|
||||
description: '描述',
|
||||
});
|
||||
}
|
||||
const result = {
|
||||
error_code: '0000000000',
|
||||
message: '操作成功',
|
||||
data: {
|
||||
paging: {
|
||||
total: 520,
|
||||
total_num: 520,
|
||||
page_num: page_num,
|
||||
page_size: page_size,
|
||||
},
|
||||
data: data,
|
||||
},
|
||||
};
|
||||
setTimeout(() => {
|
||||
res.send(result);
|
||||
}, 500);
|
||||
},
|
||||
|
||||
'POST /api/v1/tree/query': (req: any, res: any) => {
|
||||
const data = [
|
||||
{
|
||||
name: '总分组',
|
||||
id: 1,
|
||||
children: [
|
||||
{
|
||||
name: '组别1',
|
||||
id: 2,
|
||||
},
|
||||
{
|
||||
name: '组别2',
|
||||
id: 3,
|
||||
children: [
|
||||
{
|
||||
name: '子分组1',
|
||||
id: 4,
|
||||
},
|
||||
{
|
||||
name: '子分组1',
|
||||
id: 5,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: '分组3',
|
||||
id: 6,
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
const result = {
|
||||
error_code: '0000000000',
|
||||
message: '操作成功',
|
||||
data: {
|
||||
data: data,
|
||||
},
|
||||
};
|
||||
setTimeout(() => {
|
||||
res.send(result);
|
||||
}, 500);
|
||||
},
|
||||
|
||||
'POST /api/v1/user/query/list': (req: any, res: any) => {
|
||||
const { page_size, page_num } = req.body;
|
||||
const data = [];
|
||||
|
||||
for (let i = 1; i <= page_size; i++) {
|
||||
data.push({
|
||||
user_id: i,
|
||||
user_group_id: i,
|
||||
user_group_name: '分组',
|
||||
user_name: `用户${(page_num - 1) * page_size + i}`,
|
||||
password: '1111111',
|
||||
birthday: '2022-01-01',
|
||||
cell_phone: '12345678901',
|
||||
email: '1111111111@emial.com',
|
||||
gender: 1,
|
||||
identity_no: '111111184736524352622',
|
||||
priority: 1,
|
||||
user_type: 1,
|
||||
status: 1,
|
||||
description: 'stringNumber',
|
||||
});
|
||||
}
|
||||
const result = {
|
||||
error_code: '0000000000',
|
||||
message: '操作成功',
|
||||
data: {
|
||||
paging: {
|
||||
total: 520,
|
||||
total_num: 520,
|
||||
page_num: page_num,
|
||||
page_size: page_size,
|
||||
},
|
||||
data: data,
|
||||
},
|
||||
};
|
||||
setTimeout(() => {
|
||||
res.send(result);
|
||||
}, 500);
|
||||
},
|
||||
};
|
|
@ -0,0 +1,44 @@
|
|||
export const ERROR_CODE = '200';
|
||||
export const DEVICE_TYPE_MAP = {
|
||||
1: 'VDI',
|
||||
3: 'VOI',
|
||||
} as const;
|
||||
|
||||
export const RESTORE_TYPE_MAP = {
|
||||
1: '全盘还原',
|
||||
2: '数据盘还原',
|
||||
3: '定时还原',
|
||||
0: '不还原',
|
||||
} as const;
|
||||
|
||||
export const USER_TYPE_MAP = {
|
||||
1: '域用户',
|
||||
0: '本地用户',
|
||||
} as const;
|
||||
|
||||
export const GENDER_MAP = {
|
||||
1: '女',
|
||||
2: '男',
|
||||
} as const;
|
||||
|
||||
// priority
|
||||
export const PRIORITY_MAP = {
|
||||
1: '低',
|
||||
2: '中',
|
||||
3: '高',
|
||||
} as const;
|
||||
|
||||
export const USER_TYPE_OPTIONS = [
|
||||
{ value: 1, label: '域用户' },
|
||||
{ value: 0, label: '本地用户' },
|
||||
];
|
||||
|
||||
export const DEVICE_TYPE_OPTIONS = [
|
||||
{ value: 1, label: 'VDI' },
|
||||
{ value: 3, label: 'VOI' },
|
||||
];
|
||||
|
||||
export const GENDER_OPTIONS = [
|
||||
{ value: 1, label: '女' },
|
||||
{ value: 2, label: '男' },
|
||||
];
|
|
@ -1,14 +1,61 @@
|
|||
// // custom-tree.tsx
|
||||
// import React from 'react';
|
||||
// import { Tree } from 'antd';
|
||||
// import type { DataNode, TreeProps } from 'antd/es/tree';
|
||||
// import type { Key } from 'react';
|
||||
|
||||
// interface CustomTreeProps extends Omit<TreeProps, 'treeData' | 'onCheck'> {
|
||||
// treeData: any[];
|
||||
// titleField: string;
|
||||
// keyField: string;
|
||||
// childrenField?: string;
|
||||
// onCheck?: (checkedKeys?: Key[], rows?: any[], info?: any) => void;
|
||||
// }
|
||||
|
||||
// const CustomTree: React.FC<CustomTreeProps> = ({
|
||||
// treeData,
|
||||
// titleField,
|
||||
// keyField,
|
||||
// childrenField = 'children',
|
||||
// ...restProps
|
||||
// }) => {
|
||||
// // Transform the tree data to match Ant Design's expected structure
|
||||
// const transformTreeData = (data: any[]): DataNode[] => {
|
||||
// return data.map(item => {
|
||||
// const node: DataNode = {
|
||||
// title: item[titleField],
|
||||
// key: item[keyField],
|
||||
// ...item
|
||||
// };
|
||||
|
||||
// // Handle children if they exist
|
||||
// if (item[childrenField] && Array.isArray(item[childrenField])) {
|
||||
// node.children = transformTreeData(item[childrenField]);
|
||||
// }
|
||||
|
||||
// return node;
|
||||
// });
|
||||
// };
|
||||
|
||||
// const transformedData = transformTreeData(treeData);
|
||||
|
||||
// return <Tree treeData={transformedData} {...restProps} />;
|
||||
// };
|
||||
|
||||
// export default CustomTree;
|
||||
|
||||
// custom-tree.tsx
|
||||
import React from 'react';
|
||||
import { Tree } from 'antd';
|
||||
import type { DataNode, TreeProps } from 'antd/es/tree';
|
||||
import type { Key } from 'react';
|
||||
|
||||
interface CustomTreeProps extends Omit<TreeProps, 'treeData'> {
|
||||
// treeData: User.OrganizationNode[];
|
||||
interface CustomTreeProps extends Omit<TreeProps, 'treeData' | 'onCheck'> {
|
||||
treeData: any[];
|
||||
titleField: string;
|
||||
keyField: string;
|
||||
childrenField?: string;
|
||||
onCheck?: (checkedKeys?: Key[], rows?: any[], info?: any) => void;
|
||||
}
|
||||
|
||||
const CustomTree: React.FC<CustomTreeProps> = ({
|
||||
|
@ -16,6 +63,7 @@ const CustomTree: React.FC<CustomTreeProps> = ({
|
|||
titleField,
|
||||
keyField,
|
||||
childrenField = 'children',
|
||||
onCheck,
|
||||
...restProps
|
||||
}) => {
|
||||
// Transform the tree data to match Ant Design's expected structure
|
||||
|
@ -38,7 +86,17 @@ const CustomTree: React.FC<CustomTreeProps> = ({
|
|||
|
||||
const transformedData = transformTreeData(treeData);
|
||||
|
||||
return <Tree treeData={transformedData} {...restProps} />;
|
||||
const handleCheck: TreeProps['onCheck'] = (checked, info) => {
|
||||
let checkedKeys: Key[] = [];
|
||||
if (Array.isArray(checked)) {
|
||||
checkedKeys = checked;
|
||||
} else {
|
||||
checkedKeys = checked.checked;
|
||||
}
|
||||
onCheck?.(checkedKeys, info.checkedNodes, info);
|
||||
};
|
||||
|
||||
return <Tree treeData={transformedData} onCheck={handleCheck} {...restProps} />;
|
||||
};
|
||||
|
||||
export default CustomTree;
|
|
@ -1,6 +1,9 @@
|
|||
/* eslint-disable @typescript-eslint/no-use-before-define */
|
||||
import { DEVICE_TYPE_MAP, ERROR_CODE } from '@/constants/constants';
|
||||
import CustomTree from '@/pages/components/customTree';
|
||||
import { deleteUser } from '@/services/userList';
|
||||
import CreatGroup from '@/pages/userList/mod/group';
|
||||
import { deleteDevice, getTerminalList } from '@/services/terminal';
|
||||
import { deleteUserGroup, getGroupTree } from '@/services/userList';
|
||||
import {
|
||||
DeleteOutlined,
|
||||
DownOutlined,
|
||||
|
@ -19,20 +22,18 @@ import {
|
|||
import type { ColumnsType } from 'antd/es/table';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import styles from './index.less';
|
||||
import BindImage from './mod/bindImage';
|
||||
import BindUserModal from './mod/bindUser';
|
||||
import EditModal from './mod/eidtDevice';
|
||||
import CreatGroup from './mod/group';
|
||||
import BindImage from './mod/bindImage';
|
||||
|
||||
const UserListPage: React.FC = () => {
|
||||
const [orgTreeData, setOrgTreeData] = useState<User.OrganizationNode[]>([]);
|
||||
const [selectedOrg, setSelectedOrg] = useState<number>();
|
||||
|
||||
// 用户列表
|
||||
const [dataSource, setDataSource] = useState<Termial.TermialItem[]>([]);
|
||||
const [loading, setLoading] = useState<boolean>(false);
|
||||
const [searchText, setSearchText] = useState<string>('');
|
||||
const [selectedRowKeys, setSelectedRowKeys] = useState<[]>([]);
|
||||
const [orgSearchText, setOrgSearchText] = useState<string>('');
|
||||
|
||||
// 分页参数
|
||||
const [currentPage, setCurrentPage] = useState<number>(1);
|
||||
|
@ -54,83 +55,108 @@ const UserListPage: React.FC = () => {
|
|||
|
||||
// 获取用户分组组织树
|
||||
useEffect(() => {
|
||||
getGroupList();
|
||||
// getGroupList();
|
||||
}, []);
|
||||
|
||||
const filterTreeData = (
|
||||
data: User.OrganizationNode[],
|
||||
searchTerm: string,
|
||||
): User.OrganizationNode[] => {
|
||||
if (!searchTerm) return data;
|
||||
|
||||
return data.reduce((acc: User.OrganizationNode[], node) => {
|
||||
const isMatch = node.name
|
||||
?.toLowerCase()
|
||||
.includes(searchTerm.toLowerCase());
|
||||
|
||||
if (isMatch) {
|
||||
// If current node matches, include it
|
||||
acc.push({ ...node });
|
||||
} else if (node.children && node.children.length > 0) {
|
||||
// If current node doesn't match, check children
|
||||
const filteredChildren = filterTreeData(node.children, searchTerm);
|
||||
if (filteredChildren.length > 0) {
|
||||
// If any children match, include current node with filtered children
|
||||
acc.push({
|
||||
...node,
|
||||
children: filteredChildren,
|
||||
});
|
||||
}
|
||||
}
|
||||
return acc;
|
||||
}, []);
|
||||
};
|
||||
|
||||
const filteredOrgTreeData = filterTreeData(orgTreeData, orgSearchText);
|
||||
|
||||
// 获取用户列表数据
|
||||
useEffect(() => {
|
||||
getDataSource();
|
||||
}, [selectedOrg, currentPage, pageSize]);
|
||||
// if (selectedOrg) {
|
||||
// getDataSource();
|
||||
// }
|
||||
}, [searchText, selectedOrg, currentPage, pageSize]);
|
||||
|
||||
const getGroupList = () => {
|
||||
const mockOrgData: User.OrganizationNode[] = [
|
||||
{
|
||||
name: 'Headquarters',
|
||||
id: 1,
|
||||
children: [
|
||||
{
|
||||
name: 'HR Department',
|
||||
id: 2,
|
||||
},
|
||||
{
|
||||
name: 'IT Department',
|
||||
id: 3,
|
||||
children: [
|
||||
{
|
||||
name: 'Frontend Team',
|
||||
id: 4,
|
||||
},
|
||||
{
|
||||
name: 'Backend Team',
|
||||
id: 5,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'Finance Department',
|
||||
id: 6,
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
setSelectedOrg(mockOrgData[0].id as number);
|
||||
setOrgTreeData(mockOrgData);
|
||||
};
|
||||
|
||||
const getDataSource = () => {
|
||||
setLoading(true);
|
||||
setTimeout(() => {
|
||||
const mockUsers: Termial.TermialItem[] = Array.from(
|
||||
{ length: pageSize },
|
||||
(_, index) => ({
|
||||
id: index + 1,
|
||||
device_id: 'string',
|
||||
device_name: 'string',
|
||||
device_group_id: 1,
|
||||
device_group_name: 'string',
|
||||
device_type: 1,
|
||||
}),
|
||||
);
|
||||
setDataSource(mockUsers);
|
||||
setTotal(100);
|
||||
setLoading(false);
|
||||
}, 300);
|
||||
};
|
||||
|
||||
const onDelete = (device?: Termial.TermialItem) => {
|
||||
const { id } = device || {};
|
||||
const payload = {
|
||||
ids: id ? [id] : selectedRowKeys,
|
||||
const getGroupList = async () => {
|
||||
const params = {
|
||||
type: 2,
|
||||
};
|
||||
deleteUser(payload as any).then((res) => {
|
||||
console.log('res=====', res);
|
||||
const { success } = res || {};
|
||||
if (success) {
|
||||
message.success('删除成功');
|
||||
try {
|
||||
const result = await getGroupTree(params);
|
||||
if (result.error_code === ERROR_CODE) {
|
||||
setOrgTreeData(result.data.data || []);
|
||||
if (result.data.data.length > 0) {
|
||||
setSelectedOrg(result.data.data[0].id as number);
|
||||
}
|
||||
} else {
|
||||
message.error(result.message || '获取终端分组失败');
|
||||
}
|
||||
} catch (err) {
|
||||
message.error('获取终端分组失败');
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const getDataSource = async () => {
|
||||
const params: any = {
|
||||
page_size: pageSize,
|
||||
page_num: currentPage,
|
||||
};
|
||||
if (searchText) {
|
||||
params.keywords = searchText;
|
||||
}
|
||||
setLoading(true);
|
||||
try {
|
||||
const result = await getTerminalList(params);
|
||||
if (result.error_code === ERROR_CODE) {
|
||||
setDataSource(result.data.data || []);
|
||||
setTotal(result.data.paging.total || 0);
|
||||
setLoading(false);
|
||||
} else {
|
||||
message.error(result.message || '获取终端列表失败');
|
||||
setLoading(false);
|
||||
}
|
||||
} catch (err) {
|
||||
message.error('获取终端列表失败');
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const onDelete = async (device?: Termial.TermialItem) => {
|
||||
try {
|
||||
const { id } = device || {};
|
||||
const payload = {
|
||||
ids: id ? [id] : selectedRowKeys,
|
||||
};
|
||||
const res = await deleteDevice(payload);
|
||||
const { error_code } = res || {};
|
||||
if (error_code === ERROR_CODE) {
|
||||
message.success('终端删除成功');
|
||||
setSelectedRowKeys([]);
|
||||
getDataSource();
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
message.error('终端删除失败');
|
||||
}
|
||||
};
|
||||
|
||||
const handleEditUserInfo = (device: Termial.TermialItem) => {
|
||||
|
@ -142,42 +168,62 @@ const UserListPage: React.FC = () => {
|
|||
|
||||
const columns: ColumnsType<Termial.TermialItem> = [
|
||||
{
|
||||
title: '显示名称',
|
||||
dataIndex: 'username',
|
||||
key: 'username',
|
||||
title: '序号',
|
||||
dataIndex: 'order',
|
||||
key: 'order',
|
||||
width: 80,
|
||||
align: 'center',
|
||||
render: (_: any, record: any, index: number) => <span>{index + 1}</span>,
|
||||
},
|
||||
{
|
||||
title: '终端名称',
|
||||
dataIndex: 'device_name',
|
||||
key: 'device_name',
|
||||
width: 220,
|
||||
align: 'center',
|
||||
render: (text) => {
|
||||
return <Tooltip>{text || '--'}</Tooltip>;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '终端分组',
|
||||
dataIndex: 'device_group_name',
|
||||
key: 'device_group_name',
|
||||
width: 220,
|
||||
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: '终端标识',
|
||||
dataIndex: 'mac_addr',
|
||||
key: 'mac_addr',
|
||||
ellipsis: true,
|
||||
align: 'center',
|
||||
render: (text) => {
|
||||
return <Tooltip>{text || '--'}</Tooltip>;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '终端类型',
|
||||
dataIndex: 'device_type',
|
||||
key: 'device_type',
|
||||
render: (text) => {
|
||||
return (
|
||||
<div>
|
||||
<Tooltip placement="top" title={text}>
|
||||
{text}
|
||||
</Tooltip>
|
||||
</div>
|
||||
);
|
||||
width: 150,
|
||||
align: 'center',
|
||||
render: (text: number) => {
|
||||
const key = text as keyof typeof DEVICE_TYPE_MAP;
|
||||
return <Tooltip>{DEVICE_TYPE_MAP[key] || '--'}</Tooltip>;
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -262,8 +308,23 @@ const UserListPage: React.FC = () => {
|
|||
console.log('selectedRowKeys changed: ', newSelectedRowKeys);
|
||||
setSelectedRowKeys(newSelectedRowKeys as any);
|
||||
};
|
||||
|
||||
const onDeleteGroup = () => {};
|
||||
const onDeleteGroup = async () => {
|
||||
if (selectedOrg) {
|
||||
try {
|
||||
const params = {
|
||||
id: selectedOrg,
|
||||
};
|
||||
const res = await deleteUserGroup(params);
|
||||
const { error_code } = res || {};
|
||||
if (error_code === ERROR_CODE) {
|
||||
message.success('分组删除成功');
|
||||
getGroupList();
|
||||
}
|
||||
} catch (error) {
|
||||
message.error('分组删除失败');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={styles.user_content}>
|
||||
|
@ -293,18 +354,19 @@ const UserListPage: React.FC = () => {
|
|||
</Popconfirm>
|
||||
</div>
|
||||
<Input.Search
|
||||
placeholder="请输入名称"
|
||||
placeholder="请输入分组名"
|
||||
style={{ marginBottom: 6 }}
|
||||
onSearch={(value) => console.log('Search org:', value)}
|
||||
onSearch={(value) => setOrgSearchText(value)}
|
||||
onChange={(e) => setOrgSearchText(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.tree_box}>
|
||||
<CustomTree
|
||||
treeData={orgTreeData}
|
||||
treeData={filteredOrgTreeData}
|
||||
titleField="name"
|
||||
keyField="id"
|
||||
childrenField="children"
|
||||
defaultExpandAll
|
||||
defaultExpandAll={true}
|
||||
onSelect={onOrgSelect}
|
||||
selectedKeys={selectedOrg ? [selectedOrg] : []}
|
||||
icon={<TeamOutlined style={{ fontSize: '15px' }} />}
|
||||
|
@ -344,7 +406,7 @@ const UserListPage: React.FC = () => {
|
|||
<div>
|
||||
<div>
|
||||
<Input.Search
|
||||
placeholder="Search users"
|
||||
placeholder="终端名称"
|
||||
value={searchText}
|
||||
onChange={(e) => setSearchText(e.target.value)}
|
||||
style={{ width: 300 }}
|
||||
|
@ -374,6 +436,7 @@ const UserListPage: React.FC = () => {
|
|||
onShowSizeChange: handlePageSizeChange,
|
||||
showSizeChanger: true,
|
||||
showQuickJumper: true,
|
||||
pageSizeOptions: ['10', '20', '50', '100'],
|
||||
showTotal: (total) => {
|
||||
return `共${total}条数据`;
|
||||
},
|
||||
|
@ -385,6 +448,8 @@ const UserListPage: React.FC = () => {
|
|||
</div>
|
||||
<CreatGroup
|
||||
visible={visible}
|
||||
type={2}
|
||||
title="新增终端分组"
|
||||
onCancel={() => {
|
||||
setVisible(false);
|
||||
}}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/* eslint-disable @typescript-eslint/no-use-before-define */
|
||||
import type { PopoverProps } from 'antd';
|
||||
import { Alert, Button, Popconfirm, Popover, Space } from 'antd';
|
||||
import { Button, Popconfirm, Popover, Space } from 'antd';
|
||||
import type { ColumnsType } from 'antd/es/table';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import CustomTable from '../selectedTable/table';
|
||||
import SelectConponents from './table';
|
||||
|
@ -12,7 +13,7 @@ interface SelectedTableProps {
|
|||
onOk?: (values: any) => void;
|
||||
orgTreeData?: User.OrganizationNode[];
|
||||
value?: any;
|
||||
onChange?: (values: any) => void;
|
||||
onChange: (values: any) => void;
|
||||
}
|
||||
|
||||
const SelectedTable: React.FC<SelectedTableProps> = (props) => {
|
||||
|
@ -20,7 +21,7 @@ const SelectedTable: React.FC<SelectedTableProps> = (props) => {
|
|||
placement = 'bottomLeft',
|
||||
orgTreeData,
|
||||
value: formValue,
|
||||
onChange: onBindUserChange,
|
||||
onChange: onBindImageChange,
|
||||
} = props;
|
||||
const [open, setOpen] = useState<boolean>(false);
|
||||
const [tableData, setTableData] = useState<any[]>([]);
|
||||
|
@ -32,16 +33,15 @@ const SelectedTable: React.FC<SelectedTableProps> = (props) => {
|
|||
const [bindTableKeys, setBindTableKeys] = useState<any[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
console.log('formValue==========', formValue);
|
||||
const userList: any = [];
|
||||
const userId: any = [];
|
||||
const list: any = [];
|
||||
const idList: any = [];
|
||||
if (formValue && formValue.length > 0) {
|
||||
formValue.forEach((item: any) => {
|
||||
userList.push(item);
|
||||
userId.push(item.id);
|
||||
list.push(item);
|
||||
idList.push(item.id);
|
||||
});
|
||||
setSelectedRowKeys(userId);
|
||||
setSelectedRows(userList);
|
||||
setSelectedRowKeys(idList);
|
||||
setSelectedRows(list);
|
||||
}
|
||||
}, [formValue]);
|
||||
|
||||
|
@ -56,30 +56,26 @@ const SelectedTable: React.FC<SelectedTableProps> = (props) => {
|
|||
// 用户
|
||||
(selectedRows || []).forEach((item) => {
|
||||
list.push({
|
||||
id: item.id,
|
||||
name: item.name,
|
||||
type: 1,
|
||||
id: item.image_id,
|
||||
name: item.image_name,
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
setTableData(list);
|
||||
onBindImageChange(list);
|
||||
onHnadleCancel();
|
||||
};
|
||||
|
||||
const onUserTableSelect = (keys: any[], row: any[]) => {
|
||||
console.log('selectedRowKeys changed: ', keys);
|
||||
console.log('selectedRowKeys rows: ', row);
|
||||
setSelectedRowKeys(keys as any);
|
||||
setSelectedRows(row);
|
||||
};
|
||||
|
||||
const onSelectChange = (keys: any[]) => {
|
||||
console.log('selectedRowKeys changed: ', keys);
|
||||
setBindTableKeys(keys as any);
|
||||
};
|
||||
|
||||
const handleDelete = (record?: any) => {
|
||||
console.log('record=====handleDelete', record);
|
||||
if (record) {
|
||||
// 单个删除
|
||||
const { id } = record || {};
|
||||
|
@ -98,12 +94,6 @@ const SelectedTable: React.FC<SelectedTableProps> = (props) => {
|
|||
|
||||
const accessPopover = (
|
||||
<div style={{ width: '600px' }}>
|
||||
{/* <Alert
|
||||
message="可切换选择多个不同类型进行绑定"
|
||||
type="info"
|
||||
showIcon
|
||||
closeIcon
|
||||
/> */}
|
||||
<SelectConponents
|
||||
treeData={orgTreeData}
|
||||
onUserTableSelect={onUserTableSelect}
|
||||
|
@ -130,6 +120,33 @@ const SelectedTable: React.FC<SelectedTableProps> = (props) => {
|
|||
</div>
|
||||
);
|
||||
|
||||
const getColumns = (): ColumnsType<any> => {
|
||||
const columns: ColumnsType<any> = [
|
||||
{
|
||||
title: '序号',
|
||||
dataIndex: 'order',
|
||||
key: 'order',
|
||||
width: 80,
|
||||
render: (_, record, index) => <span>{index + 1}</span>,
|
||||
},
|
||||
{
|
||||
title: '镜像名称',
|
||||
dataIndex: 'image_name',
|
||||
key: 'image_name',
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
render: (_, record) => (
|
||||
<Button type="link" danger onClick={() => handleDelete(record)}>
|
||||
删除
|
||||
</Button>
|
||||
),
|
||||
},
|
||||
];
|
||||
return columns;
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Space style={{ marginBottom: '10px' }}>
|
||||
|
@ -166,6 +183,7 @@ const SelectedTable: React.FC<SelectedTableProps> = (props) => {
|
|||
<CustomTable
|
||||
dataSource={tableData}
|
||||
onDelete={handleDelete}
|
||||
columns={getColumns()}
|
||||
scrollY={400}
|
||||
rowKey="id"
|
||||
pagination={false}
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
import { Input, Table } from 'antd';
|
||||
/* eslint-disable @typescript-eslint/no-use-before-define */
|
||||
import { ERROR_CODE,IMAGES_TYPE_MAP } from '@/constants/images.constants';
|
||||
import { getImagesList } from '@/services/images';
|
||||
import { Input, Table, message,Tooltip } from 'antd';
|
||||
import type { ColumnsType } from 'antd/es/table';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import styles from './index.less';
|
||||
|
||||
|
@ -8,42 +12,69 @@ interface TableProps {
|
|||
onUserTableSelect?: (keys: any[], row: any[]) => void;
|
||||
}
|
||||
|
||||
interface DataType {
|
||||
key: React.Key;
|
||||
name: string;
|
||||
age: number;
|
||||
address: string;
|
||||
}
|
||||
|
||||
const TablePage: React.FC<TableProps> = ({
|
||||
onUserTableSelect,
|
||||
selectedRowKeys,
|
||||
}) => {
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [data, setData] = useState<any[]>([]);
|
||||
const [searchText, setSearchText] = useState('');
|
||||
const [searchText, setSearchText] = useState<any>();
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const [pageSize, setPageSize] = useState(20);
|
||||
const [total, setTotal] = useState(0);
|
||||
|
||||
// Mock data generation
|
||||
useEffect(() => {
|
||||
const mockData: DataType[] = [];
|
||||
for (let i = 0; i < 100; i++) {
|
||||
mockData.push({
|
||||
id: i + 99,
|
||||
name: `User ${i}`,
|
||||
});
|
||||
}
|
||||
setData(mockData);
|
||||
setTotal(mockData.length);
|
||||
}, []);
|
||||
loadImages();
|
||||
}, [searchText, currentPage, pageSize]);
|
||||
|
||||
const columns: TableProps<DataType>['columns'] = [
|
||||
const loadImages = async () => {
|
||||
const params: any = {
|
||||
page_size: pageSize,
|
||||
page_num: currentPage,
|
||||
};
|
||||
if (searchText) {
|
||||
params.keywords = searchText;
|
||||
}
|
||||
setLoading(true);
|
||||
try {
|
||||
const imagesRes = await getImagesList(params);
|
||||
if (imagesRes.error_code === ERROR_CODE) {
|
||||
setData(imagesRes.data.data || []);
|
||||
setTotal(imagesRes.data.paging.total || 0);
|
||||
setLoading(false);
|
||||
} else {
|
||||
message.error(imagesRes.message || '获取镜像列表失败');
|
||||
setLoading(false);
|
||||
}
|
||||
} catch (err) {
|
||||
message.error('获取镜像列表失败');
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const columns: ColumnsType<any> = [
|
||||
{
|
||||
title: 'Name',
|
||||
dataIndex: 'name',
|
||||
sorter: (a, b) => a.name.localeCompare(b.name),
|
||||
title: '序号',
|
||||
dataIndex: 'order',
|
||||
key: 'order',
|
||||
width: 80,
|
||||
render: (_: any, record: any, index: number) => <span>{index + 1}</span>,
|
||||
},
|
||||
{
|
||||
title: '镜像名称',
|
||||
dataIndex: 'image_name',
|
||||
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) => {
|
||||
|
@ -74,10 +105,10 @@ const TablePage: React.FC<TableProps> = ({
|
|||
</div>
|
||||
|
||||
<Table
|
||||
// rowSelection={rowSelection}
|
||||
columns={columns}
|
||||
dataSource={data}
|
||||
rowKey="id"
|
||||
loading={loading}
|
||||
rowSelection={{
|
||||
selectedRowKeys,
|
||||
preserveSelectedRowKeys: true,
|
||||
|
@ -92,6 +123,7 @@ const TablePage: React.FC<TableProps> = ({
|
|||
onShowSizeChange: handlePageSizeChange,
|
||||
showSizeChanger: false,
|
||||
showQuickJumper: false,
|
||||
pageSizeOptions: ['10', '20', '50', '100'],
|
||||
}}
|
||||
scroll={{ x: 'max-content', y: 300 }}
|
||||
/>
|
||||
|
|
|
@ -1,17 +1,11 @@
|
|||
// index.tsx
|
||||
import {
|
||||
Button,
|
||||
Form,
|
||||
Input,
|
||||
message,
|
||||
Modal,
|
||||
Radio,
|
||||
TreeSelect,
|
||||
} from 'antd';
|
||||
import { DEVICE_TYPE_OPTIONS } from '@/constants/constants';
|
||||
import { ERROR_CODE } from '@/constants/images.constants';
|
||||
import { saveDevice } from '@/services/terminal';
|
||||
import { Button, Form, Input, message, Modal, Select, TreeSelect } from 'antd';
|
||||
import React, { useEffect } from 'react';
|
||||
|
||||
interface UserEditModalProps {
|
||||
// visible: boolean;
|
||||
orgTreeData: User.OrganizationNode[];
|
||||
onCancel: () => void;
|
||||
onOk: (values: any) => void;
|
||||
|
@ -39,9 +33,15 @@ const UserEditModal: React.FC<UserEditModalProps> = ({
|
|||
const handleOk = async () => {
|
||||
try {
|
||||
const values = await form.validateFields();
|
||||
onOk(values);
|
||||
const params = { ...values, user_id };
|
||||
const res = await saveDevice(params);
|
||||
const { error_code } = res || {};
|
||||
if (error_code === ERROR_CODE) {
|
||||
message.success('保存成功');
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
message.error('请检查表单字段');
|
||||
message.error('保存失败');
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -50,7 +50,6 @@ const UserEditModal: React.FC<UserEditModalProps> = ({
|
|||
types: {
|
||||
email: '${label} is not a valid email!',
|
||||
number: '${label} is not a valid number!',
|
||||
cell_phone: '${label} is not a valid cell phone number!',
|
||||
},
|
||||
number: {
|
||||
range: '${label} must be between ${min} and ${max}',
|
||||
|
@ -95,8 +94,8 @@ const UserEditModal: React.FC<UserEditModalProps> = ({
|
|||
validateMessages={validateMessages}
|
||||
>
|
||||
<Form.Item
|
||||
name="loginName"
|
||||
label="显示名称"
|
||||
name="device_name"
|
||||
label="终端名称"
|
||||
rules={[{ required: true, message: '请输入显示名称' }]}
|
||||
>
|
||||
<Input />
|
||||
|
@ -111,7 +110,7 @@ const UserEditModal: React.FC<UserEditModalProps> = ({
|
|||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="user_group_id"
|
||||
name="device_group_id"
|
||||
label="终端分组"
|
||||
rules={[{ required: true, message: '请选择终端分组' }]}
|
||||
>
|
||||
|
@ -124,8 +123,15 @@ const UserEditModal: React.FC<UserEditModalProps> = ({
|
|||
fieldNames={{ label: 'name', value: 'id', children: 'children' }}
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="device_typ"
|
||||
label="终端类型"
|
||||
rules={[{ required: false, message: '请输入终端型号' }]}
|
||||
>
|
||||
<Select options={DEVICE_TYPE_OPTIONS} />
|
||||
</Form.Item>
|
||||
|
||||
{/* <Form.Item
|
||||
name="status"
|
||||
label="认证方式"
|
||||
rules={[{ required: false, message: '请选择认证方式' }]}
|
||||
|
@ -134,7 +140,7 @@ const UserEditModal: React.FC<UserEditModalProps> = ({
|
|||
<Radio value={1}>用户认证</Radio>
|
||||
<Radio value={2}>终端认证</Radio>
|
||||
</Radio.Group>
|
||||
</Form.Item>
|
||||
</Form.Item> */}
|
||||
|
||||
<Form.Item
|
||||
name="ip_addr"
|
||||
|
@ -157,13 +163,7 @@ const UserEditModal: React.FC<UserEditModalProps> = ({
|
|||
>
|
||||
<Input />
|
||||
</Form.Item> */}
|
||||
<Form.Item
|
||||
name="model"
|
||||
label="终端型号"
|
||||
rules={[{ required: false, message: '请输入终端型号' }]}
|
||||
>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="description"
|
||||
label="描述"
|
||||
|
|
|
@ -1,36 +1,28 @@
|
|||
import { Button, Form, Input, Modal, TreeSelect } from 'antd';
|
||||
import React, { useEffect } from 'react';
|
||||
import { ERROR_CODE } from '@/constants/constants';
|
||||
import { addUserGroup } from '@/services/userList';
|
||||
import { Button, Form, Input, Modal, TreeSelect, message } from 'antd';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
|
||||
interface CreatGroupProps {
|
||||
visible: boolean;
|
||||
selectedOrg?: number;
|
||||
onCancel: () => void;
|
||||
onOk: (values: any) => void;
|
||||
onOk: (values?: any) => void;
|
||||
orgTreeData: User.OrganizationNode[];
|
||||
}
|
||||
|
||||
const CreatGroup: React.FC<CreatGroupProps> = (props) => {
|
||||
const { visible, onCancel, onOk, orgTreeData, selectedOrg } = props;
|
||||
const [loading, setLoading] = useState<boolean>(false);
|
||||
const [form] = Form.useForm();
|
||||
|
||||
useEffect(() => {
|
||||
const initialValues = { parent_device_group_id: [selectedOrg] };
|
||||
form.setFieldsValue(initialValues);
|
||||
if (selectedOrg) {
|
||||
const initialValues = { parent_device_group_id: [selectedOrg] };
|
||||
form.setFieldsValue(initialValues);
|
||||
}
|
||||
}, [visible, form, selectedOrg]);
|
||||
|
||||
// Flatten tree data for parent group selection
|
||||
// const flattenTreeData = (data: OrganizationNode[], result: { value: string; label: string }[] = []) => {
|
||||
// data.forEach(item => {
|
||||
// result.push({ value: item.id as string, label: item.name as string });
|
||||
// if (item.children) {
|
||||
// flattenTreeData(item.children, result);
|
||||
// }
|
||||
// });
|
||||
// return result;
|
||||
// };
|
||||
|
||||
// const parentGroupOptions = flattenTreeData(orgTreeData);
|
||||
|
||||
const handleOk = () => {
|
||||
form.submit();
|
||||
};
|
||||
|
@ -40,14 +32,34 @@ const CreatGroup: React.FC<CreatGroupProps> = (props) => {
|
|||
onCancel();
|
||||
};
|
||||
|
||||
const handleFinish = (values: any) => {
|
||||
onOk(values);
|
||||
form.resetFields();
|
||||
const handleFinish = async () => {
|
||||
const values: any = await form.validateFields();
|
||||
setLoading(true);
|
||||
try {
|
||||
console.log('values=====', values);
|
||||
const { name, parent_id } = values || {};
|
||||
const params: any = { name, type: 2 };
|
||||
if (parent_id) {
|
||||
params.parent_id = parent_id;
|
||||
}
|
||||
const res = await addUserGroup(params);
|
||||
setLoading(false);
|
||||
const { code } = res || {};
|
||||
if (code === ERROR_CODE) {
|
||||
message.success('添加成功');
|
||||
form.resetFields();
|
||||
onCancel();
|
||||
onOk();
|
||||
}
|
||||
} catch (error) {
|
||||
setLoading(false);
|
||||
message.error('创建用户分组失败');
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal
|
||||
title="添加用户分组"
|
||||
title="添加终端分组"
|
||||
open={visible}
|
||||
onOk={handleOk}
|
||||
onCancel={handleCancel}
|
||||
|
@ -55,12 +67,14 @@ const CreatGroup: React.FC<CreatGroupProps> = (props) => {
|
|||
cancelText="取消"
|
||||
centered={true}
|
||||
destroyOnHidden={true}
|
||||
width={600}
|
||||
footer={
|
||||
<div style={{ display: 'flex', justifyContent: 'right' }}>
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={handleOk}
|
||||
style={{ marginRight: '20px' }}
|
||||
loading={loading}
|
||||
>
|
||||
确定
|
||||
</Button>
|
||||
|
@ -80,17 +94,17 @@ const CreatGroup: React.FC<CreatGroupProps> = (props) => {
|
|||
style={{ paddingTop: '20px', paddingBottom: '20px' }}
|
||||
>
|
||||
<Form.Item
|
||||
name="device_group_name:"
|
||||
name="name:"
|
||||
label="分组名"
|
||||
rules={[{ required: true, message: '请输入分组名!' }]}
|
||||
>
|
||||
<Input placeholder="请输入分组名" />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item name="parent_device_group_id" label="父分组名">
|
||||
<Form.Item name="parent_id" label="父分组名">
|
||||
<TreeSelect
|
||||
showSearch
|
||||
allowClear={false}
|
||||
allowClear={true}
|
||||
treeDefaultExpandAll
|
||||
placeholder="请选择用户分组"
|
||||
treeData={orgTreeData}
|
||||
|
|
|
@ -3,6 +3,7 @@ import CustomTree from '@/pages/components/customTree';
|
|||
import { TeamOutlined } from '@ant-design/icons';
|
||||
import type { PopoverProps } from 'antd';
|
||||
import { Alert, Button, Popconfirm, Popover, Space, Tabs } from 'antd';
|
||||
import type { ColumnsType } from 'antd/es/table';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import SelectConponents from '../selectConponents';
|
||||
import CustomTable from './table';
|
||||
|
@ -129,6 +130,41 @@ const SelectedTable: React.FC<SelectedTableProps> = (props) => {
|
|||
}
|
||||
};
|
||||
|
||||
const getColumns = (): ColumnsType<any> => {
|
||||
const columns: ColumnsType<any> = [
|
||||
{
|
||||
title: '序号',
|
||||
dataIndex: 'order',
|
||||
key: 'order',
|
||||
width: 80,
|
||||
render: (_, record, index) => <span>{index + 1}</span>,
|
||||
},
|
||||
{
|
||||
title: '名称',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
},
|
||||
{
|
||||
title: '类型',
|
||||
dataIndex: 'type',
|
||||
key: 'type',
|
||||
render: (text) => (
|
||||
<span>{text == 1 ? '用户' : text == 2 ? '用户组' : ''}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
render: (_, record) => (
|
||||
<Button type="link" danger onClick={() => handleDelete(record)}>
|
||||
删除
|
||||
</Button>
|
||||
),
|
||||
}
|
||||
];
|
||||
return columns;
|
||||
};
|
||||
|
||||
const accessPopover = (
|
||||
<div style={{ width: '600px' }}>
|
||||
<Alert
|
||||
|
@ -220,6 +256,7 @@ const SelectedTable: React.FC<SelectedTableProps> = (props) => {
|
|||
scrollY={400}
|
||||
rowKey="id"
|
||||
pagination={false}
|
||||
columns={getColumns()}
|
||||
rowSelection={{
|
||||
bindTableKeys,
|
||||
onChange: onSelectChange,
|
||||
|
|
|
@ -11,6 +11,7 @@ interface DeletableTableProps {
|
|||
rowKey?: string;
|
||||
rowSelection?: any;
|
||||
pagination?:any;
|
||||
columns: ColumnsType<any>;
|
||||
}
|
||||
|
||||
const DeletableTable: React.FC<DeletableTableProps> = (props) => {
|
||||
|
@ -23,52 +24,52 @@ const DeletableTable: React.FC<DeletableTableProps> = (props) => {
|
|||
...restProps
|
||||
} = props;
|
||||
console.log("datasource=====",dataSource);
|
||||
const getColumns = (): ColumnsType<any> => {
|
||||
const columns: ColumnsType<any> = [
|
||||
{
|
||||
title: '名称',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
},
|
||||
{
|
||||
title: '类型',
|
||||
dataIndex: 'type',
|
||||
key: 'type',
|
||||
render: (text) => (
|
||||
<span>{text == 1 ? '用户' : text == 2 ? '用户组' : ''}</span>
|
||||
),
|
||||
},
|
||||
];
|
||||
// const getColumns = (): ColumnsType<any> => {
|
||||
// const columns: ColumnsType<any> = [
|
||||
// {
|
||||
// title: '名称',
|
||||
// dataIndex: 'name',
|
||||
// key: 'name',
|
||||
// },
|
||||
// {
|
||||
// title: '类型',
|
||||
// dataIndex: 'type',
|
||||
// key: 'type',
|
||||
// render: (text) => (
|
||||
// <span>{text == 1 ? '用户' : text == 2 ? '用户组' : ''}</span>
|
||||
// ),
|
||||
// },
|
||||
// ];
|
||||
|
||||
if (isSerial) {
|
||||
columns.unshift({
|
||||
title: '序号',
|
||||
dataIndex: 'order',
|
||||
key: 'order',
|
||||
width: 80,
|
||||
render: (_, record, index) => <span>{index + 1}</span>,
|
||||
});
|
||||
}
|
||||
// if (isSerial) {
|
||||
// columns.unshift({
|
||||
// title: '序号',
|
||||
// dataIndex: 'order',
|
||||
// key: 'order',
|
||||
// width: 80,
|
||||
// render: (_, record, index) => <span>{index + 1}</span>,
|
||||
// });
|
||||
// }
|
||||
|
||||
if (isAction) {
|
||||
columns.push({
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
render: (_, record) => (
|
||||
<Button type="link" danger onClick={() => onDelete(record)}>
|
||||
删除
|
||||
</Button>
|
||||
),
|
||||
});
|
||||
}
|
||||
// if (isAction) {
|
||||
// columns.push({
|
||||
// title: '操作',
|
||||
// key: 'action',
|
||||
// render: (_, record) => (
|
||||
// <Button type="link" danger onClick={() => onDelete(record)}>
|
||||
// 删除
|
||||
// </Button>
|
||||
// ),
|
||||
// });
|
||||
// }
|
||||
|
||||
return columns;
|
||||
};
|
||||
// return columns;
|
||||
// };
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Table
|
||||
columns={getColumns()}
|
||||
// columns={getColumns()}
|
||||
dataSource={dataSource}
|
||||
scroll={{ y: scrollY }}
|
||||
{...restProps}
|
||||
|
|
|
@ -1,8 +1,24 @@
|
|||
/* eslint-disable @typescript-eslint/no-use-before-define */
|
||||
import {
|
||||
ERROR_CODE,
|
||||
GENDER_MAP,
|
||||
PRIORITY_MAP,
|
||||
USER_TYPE_MAP,
|
||||
} from '@/constants/constants';
|
||||
import CustomTree from '@/pages/components/customTree';
|
||||
import { deleteUser } from '@/services/userList';
|
||||
import { DeleteOutlined, PlusOutlined, TeamOutlined } from '@ant-design/icons';
|
||||
import { Button, Input, Popconfirm, Table, message } from 'antd';
|
||||
import {
|
||||
deleteUser,
|
||||
deleteUserGroup,
|
||||
getGroupTree,
|
||||
getUserList,
|
||||
} from '@/services/userList';
|
||||
import {
|
||||
DeleteOutlined,
|
||||
PlusOutlined,
|
||||
RedoOutlined,
|
||||
TeamOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import { Button, Input, message, Popconfirm, Spin, Table, Tooltip } from 'antd';
|
||||
import type { ColumnsType } from 'antd/es/table';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import styles from './index.less';
|
||||
|
@ -12,18 +28,20 @@ import PasswordResetModal from './mod/passwordEdit';
|
|||
|
||||
const UserListPage: React.FC = () => {
|
||||
const [orgTreeData, setOrgTreeData] = useState<User.OrganizationNode[]>([]);
|
||||
const [selectedOrg, setSelectedOrg] = useState<number>();
|
||||
const [selectedOrg, setSelectedOrg] = useState<any>();
|
||||
|
||||
// 用户列表
|
||||
const [users, setUsers] = useState<User.UserItem[]>([]);
|
||||
const [dataSource, setDataSource] = useState<User.UserItem[]>([]);
|
||||
const [loading, setLoading] = useState<boolean>(false);
|
||||
const [spinning, setSpinning] = useState<boolean>(false);
|
||||
const [searchText, setSearchText] = useState<string>('');
|
||||
const [selectedRowKeys, setSelectedRowKeys] = useState<[]>([]);
|
||||
const [orgSearchText, setOrgSearchText] = useState<string>('');
|
||||
|
||||
// 分页参数
|
||||
const [currentPage, setCurrentPage] = useState<number>(1);
|
||||
const [pageSize, setPageSize] = useState<number>(10);
|
||||
const [totalUsers, setTotalUsers] = useState<number>(0);
|
||||
const [total, setTotal] = useState<number>(0);
|
||||
// 编辑用户
|
||||
const [currentUserInfo, setCurrentUserInfo] = useState<any>({
|
||||
visible: false,
|
||||
|
@ -43,60 +61,96 @@ const UserListPage: React.FC = () => {
|
|||
|
||||
// 获取用户列表数据
|
||||
useEffect(() => {
|
||||
getUserListInit();
|
||||
}, [selectedOrg, currentPage, pageSize]);
|
||||
getDataSource();
|
||||
}, [searchText,selectedOrg, currentPage, pageSize]);
|
||||
|
||||
const getUserGroupList = () => {
|
||||
const mockOrgData: User.OrganizationNode[] = [
|
||||
{
|
||||
name: 'Headquarters',
|
||||
id: 1,
|
||||
children: [
|
||||
{
|
||||
name: 'HR Department',
|
||||
id: 2,
|
||||
},
|
||||
{
|
||||
name: 'IT Department',
|
||||
id: 3,
|
||||
children: [
|
||||
{
|
||||
name: 'Frontend Team',
|
||||
id: 4,
|
||||
},
|
||||
{
|
||||
name: 'Backend Team',
|
||||
id: 5,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'Finance Department',
|
||||
id: 6,
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
setSelectedOrg(mockOrgData[0].id as number);
|
||||
setOrgTreeData(mockOrgData);
|
||||
const getUserGroupList = async () => {
|
||||
const params = {
|
||||
type: 1,
|
||||
};
|
||||
setSpinning(true);
|
||||
try {
|
||||
const result = await getGroupTree(params);
|
||||
console.log('result=====', result);
|
||||
const { code, data = [] } = result || {};
|
||||
setSpinning(false);
|
||||
if (code === ERROR_CODE) {
|
||||
if (data.length > 0) {
|
||||
const { children = [] } = data[0] || {};
|
||||
setOrgTreeData(children);
|
||||
// if (children.length > 0) {
|
||||
// setSelectedOrg(children[0].id);
|
||||
// }
|
||||
}
|
||||
} else {
|
||||
message.error(result.message || '获取用户分组失败');
|
||||
}
|
||||
} catch (err) {
|
||||
message.error('获取用户分组失败');
|
||||
setSpinning(false);
|
||||
}
|
||||
};
|
||||
|
||||
const getUserListInit = () => {
|
||||
setLoading(true);
|
||||
setTimeout(() => {
|
||||
const startIndex = (currentPage - 1) * pageSize;
|
||||
const mockUsers: User.UserItem[] = Array.from(
|
||||
{ length: pageSize },
|
||||
(_, index) => ({
|
||||
user_id: startIndex + index + 1,
|
||||
user_name: 'string',
|
||||
}),
|
||||
);
|
||||
const filterTreeData = (
|
||||
data: User.OrganizationNode[],
|
||||
searchTerm: string,
|
||||
): User.OrganizationNode[] => {
|
||||
if (!searchTerm) return data;
|
||||
|
||||
setUsers(mockUsers);
|
||||
setTotalUsers(100);
|
||||
return data.reduce((acc: User.OrganizationNode[], node) => {
|
||||
const isMatch = node.name
|
||||
?.toLowerCase()
|
||||
.includes(searchTerm.toLowerCase());
|
||||
|
||||
if (isMatch) {
|
||||
// If current node matches, include it
|
||||
acc.push({ ...node });
|
||||
} else if (node.children && node.children.length > 0) {
|
||||
// If current node doesn't match, check children
|
||||
const filteredChildren = filterTreeData(node.children, searchTerm);
|
||||
if (filteredChildren.length > 0) {
|
||||
// If any children match, include current node with filtered children
|
||||
acc.push({
|
||||
...node,
|
||||
children: filteredChildren,
|
||||
});
|
||||
}
|
||||
}
|
||||
return acc;
|
||||
}, []);
|
||||
};
|
||||
|
||||
const filteredOrgTreeData = filterTreeData(orgTreeData, orgSearchText);
|
||||
|
||||
const getDataSource = async () => {
|
||||
const params: any = {
|
||||
page_size: pageSize,
|
||||
page_num: currentPage,
|
||||
};
|
||||
if (selectedOrg) {
|
||||
params.user_group_id = selectedOrg;
|
||||
}
|
||||
if (searchText) {
|
||||
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) {
|
||||
setDataSource(list || []);
|
||||
setTotal(total);
|
||||
setLoading(false);
|
||||
} else {
|
||||
message.error(result.message || '获取终端列表失败');
|
||||
setLoading(false);
|
||||
}
|
||||
} catch (err) {
|
||||
message.error('获取终端列表失败');
|
||||
setLoading(false);
|
||||
}, 300);
|
||||
}
|
||||
};
|
||||
|
||||
const onDelete = (user?: User.UserItem) => {
|
||||
|
@ -110,7 +164,7 @@ const UserListPage: React.FC = () => {
|
|||
if (success) {
|
||||
message.success('删除成功');
|
||||
setSelectedRowKeys([]);
|
||||
getUserListInit();
|
||||
getDataSource();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
@ -137,34 +191,105 @@ const UserListPage: React.FC = () => {
|
|||
|
||||
const columns: ColumnsType<User.UserItem> = [
|
||||
{
|
||||
title: '登录名',
|
||||
dataIndex: 'user_id',
|
||||
key: 'user_id',
|
||||
title: '序号',
|
||||
dataIndex: 'order',
|
||||
key: 'order',
|
||||
width: 80,
|
||||
align: 'center',
|
||||
render: (_: any, record: any, index: number) => <span>{index + 1}</span>,
|
||||
},
|
||||
{
|
||||
title: '用户姓名',
|
||||
title: '用户名',
|
||||
dataIndex: 'user_name',
|
||||
key: 'user_name',
|
||||
width: 150,
|
||||
align: 'center',
|
||||
render: (text) => {
|
||||
return <Tooltip>{text || '--'}</Tooltip>;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '用户分组',
|
||||
dataIndex: 'userGroup',
|
||||
key: 'userGroup',
|
||||
},
|
||||
{
|
||||
title: '性别',
|
||||
dataIndex: 'sex',
|
||||
key: 'sex',
|
||||
dataIndex: 'user_group_name',
|
||||
key: 'user_group_name',
|
||||
width: 150,
|
||||
align: 'center',
|
||||
render: (text) => {
|
||||
return <Tooltip>{text || '--'}</Tooltip>;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
dataIndex: 'status',
|
||||
key: 'status',
|
||||
width: 150,
|
||||
align: 'center',
|
||||
render: (text) => {
|
||||
return <Tooltip>{text || '--'}</Tooltip>;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '用户类别',
|
||||
dataIndex: 'userType',
|
||||
key: 'userType',
|
||||
dataIndex: 'user_type',
|
||||
key: 'user_type',
|
||||
width: 150,
|
||||
align: 'center',
|
||||
render: (text: number) => {
|
||||
const key = text as keyof typeof USER_TYPE_MAP;
|
||||
return <Tooltip>{USER_TYPE_MAP[key] || '--'}</Tooltip>;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '优先级',
|
||||
dataIndex: 'priority',
|
||||
key: 'priority',
|
||||
width: 150,
|
||||
align: 'center',
|
||||
render: (text: number) => {
|
||||
const key = text as keyof typeof PRIORITY_MAP;
|
||||
return <Tooltip>{PRIORITY_MAP[key] || '--'}</Tooltip>;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '性别',
|
||||
dataIndex: 'gender',
|
||||
key: 'gender',
|
||||
width: 150,
|
||||
align: 'center',
|
||||
render: (text: number) => {
|
||||
const key = text as keyof typeof GENDER_MAP;
|
||||
return <Tooltip>{GENDER_MAP[key] || '--'}</Tooltip>;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '电话',
|
||||
dataIndex: 'cell_phone',
|
||||
key: 'cell_phone',
|
||||
width: 150,
|
||||
align: 'center',
|
||||
render: (text:any) => {
|
||||
return <Tooltip>{text || '--'}</Tooltip>;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '出生日期',
|
||||
dataIndex: 'birthday',
|
||||
key: 'birthday',
|
||||
width: 150,
|
||||
align: 'center',
|
||||
render: (text:any) => {
|
||||
return <Tooltip>{text || '--'}</Tooltip>;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '身份证号',
|
||||
dataIndex: 'identity_no',
|
||||
key: 'identity_no',
|
||||
width: 150,
|
||||
align: 'center',
|
||||
render: (text:any) => {
|
||||
return <Tooltip>{text || '--'}</Tooltip>;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
|
@ -197,7 +322,7 @@ const UserListPage: React.FC = () => {
|
|||
|
||||
const onOrgSelect = (selectedKeys: React.Key[]) => {
|
||||
if (selectedKeys.length > 0) {
|
||||
setSelectedOrg(selectedKeys[0] as number);
|
||||
setSelectedOrg(selectedKeys[0]);
|
||||
setCurrentPage(1);
|
||||
}
|
||||
};
|
||||
|
@ -217,18 +342,47 @@ const UserListPage: React.FC = () => {
|
|||
setSelectedRowKeys(newSelectedRowKeys as any);
|
||||
};
|
||||
|
||||
const onDeleteGroup = () => {};
|
||||
const onSaveGroup = () => {
|
||||
getUserGroupList();
|
||||
};
|
||||
|
||||
const onDeleteGroup = async () => {
|
||||
if (selectedOrg) {
|
||||
try {
|
||||
const params = {
|
||||
id: selectedOrg,
|
||||
};
|
||||
const res = await deleteUserGroup(params);
|
||||
const { code } = res || {};
|
||||
if (code === ERROR_CODE) {
|
||||
message.success('分组删除成功');
|
||||
setSelectedOrg(null);
|
||||
getUserGroupList();
|
||||
}
|
||||
} catch (error) {
|
||||
message.error('分组删除失败');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={styles.user_content}>
|
||||
<div className={styles.left_content}>
|
||||
<div className={styles.search}>
|
||||
<div style={{ paddingBottom: '5px' }}>
|
||||
<Button
|
||||
type="text"
|
||||
style={{ marginRight: '8px', fontSize: '16px' }}
|
||||
icon={<RedoOutlined />}
|
||||
onClick={() => getUserGroupList()}
|
||||
title="刷新"
|
||||
/>
|
||||
<Button
|
||||
type="text"
|
||||
style={{ marginRight: '8px', fontSize: '16px' }}
|
||||
icon={<PlusOutlined />}
|
||||
onClick={() => setVisible(true)}
|
||||
title="新增"
|
||||
/>
|
||||
<Popconfirm
|
||||
title=""
|
||||
|
@ -243,26 +397,31 @@ const UserListPage: React.FC = () => {
|
|||
type="text"
|
||||
style={{ fontSize: '16px' }}
|
||||
icon={<DeleteOutlined />}
|
||||
title="删除"
|
||||
disabled={!selectedOrg}
|
||||
/>
|
||||
</Popconfirm>
|
||||
</div>
|
||||
<Input.Search
|
||||
placeholder="请输入名称"
|
||||
style={{ marginBottom: 6 }}
|
||||
onSearch={(value) => console.log('Search org:', value)}
|
||||
onSearch={(value) => setOrgSearchText(value)}
|
||||
onChange={(e) => setOrgSearchText(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.tree_box}>
|
||||
<CustomTree
|
||||
treeData={orgTreeData}
|
||||
titleField="name"
|
||||
keyField="id"
|
||||
childrenField="children"
|
||||
defaultExpandAll
|
||||
onSelect={onOrgSelect}
|
||||
selectedKeys={selectedOrg ? [selectedOrg] : []}
|
||||
icon={<TeamOutlined style={{ fontSize: '15px' }} />}
|
||||
/>
|
||||
<Spin spinning={spinning} delay={100}>
|
||||
<CustomTree
|
||||
treeData={filteredOrgTreeData}
|
||||
titleField="name"
|
||||
keyField="id"
|
||||
childrenField="children"
|
||||
defaultExpandAll
|
||||
onSelect={onOrgSelect}
|
||||
selectedKeys={selectedOrg ? [selectedOrg] : []}
|
||||
icon={<TeamOutlined style={{ fontSize: '15px' }} />}
|
||||
/>
|
||||
</Spin>
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.right_content}>
|
||||
|
@ -297,14 +456,14 @@ const UserListPage: React.FC = () => {
|
|||
删除
|
||||
</Button>
|
||||
</Popconfirm>
|
||||
<Button style={{ marginRight: '8px' }} onClick={getUserListInit}>
|
||||
<Button style={{ marginRight: '8px' }} onClick={getDataSource}>
|
||||
刷新
|
||||
</Button>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<Input.Search
|
||||
placeholder="Search users"
|
||||
placeholder="用户名"
|
||||
value={searchText}
|
||||
onChange={(e) => setSearchText(e.target.value)}
|
||||
style={{ width: 300 }}
|
||||
|
@ -319,17 +478,18 @@ const UserListPage: React.FC = () => {
|
|||
<div className={styles.teble_box}>
|
||||
<Table
|
||||
columns={columns}
|
||||
dataSource={users}
|
||||
dataSource={dataSource}
|
||||
loading={loading}
|
||||
rowKey="id"
|
||||
pagination={{
|
||||
current: currentPage,
|
||||
pageSize: pageSize,
|
||||
total: totalUsers,
|
||||
total: total,
|
||||
onChange: handlePageChange,
|
||||
onShowSizeChange: handlePageSizeChange,
|
||||
showSizeChanger: true,
|
||||
showQuickJumper: true,
|
||||
pageSizeOptions: ['10', '20', '50', '100'],
|
||||
showTotal: (total) => {
|
||||
return `共${total}条数据`;
|
||||
},
|
||||
|
@ -345,11 +505,13 @@ const UserListPage: React.FC = () => {
|
|||
</div>
|
||||
<CreatGroup
|
||||
visible={visible}
|
||||
type={1}
|
||||
title="新增用户分组"
|
||||
selectedOrg={selectedOrg}
|
||||
onCancel={() => {
|
||||
setVisible(false);
|
||||
}}
|
||||
onOk={() => {}}
|
||||
onOk={onSaveGroup}
|
||||
orgTreeData={orgTreeData}
|
||||
/>
|
||||
<UserEditModal
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
// index.tsx
|
||||
import { GENDER_OPTIONS, USER_TYPE_OPTIONS } from '@/constants/constants';
|
||||
import { idIDIntl } from '@ant-design/pro-components';
|
||||
import {
|
||||
Button,
|
||||
Form,
|
||||
|
@ -10,7 +12,6 @@ import {
|
|||
TreeSelect,
|
||||
} from 'antd';
|
||||
import React, { useEffect } from 'react';
|
||||
const { Option } = Select;
|
||||
|
||||
interface UserEditModalProps {
|
||||
// visible: boolean;
|
||||
|
@ -30,13 +31,13 @@ const UserEditModal: React.FC<UserEditModalProps> = ({
|
|||
currentUserInfo,
|
||||
}) => {
|
||||
const { recordData, visible, selectedOrg } = currentUserInfo || {};
|
||||
const { user_id } = recordData || {};
|
||||
const { id } = recordData || {};
|
||||
const [form] = Form.useForm();
|
||||
|
||||
useEffect(() => {
|
||||
const initialValues = { user_group_id: [selectedOrg], status: 1 };
|
||||
form.setFieldsValue(initialValues);
|
||||
}, [visible, form,recordData, selectedOrg]);
|
||||
}, [visible, form, recordData, selectedOrg]);
|
||||
|
||||
const handleOk = async () => {
|
||||
try {
|
||||
|
@ -61,7 +62,7 @@ const UserEditModal: React.FC<UserEditModalProps> = ({
|
|||
|
||||
return (
|
||||
<Modal
|
||||
title={user_id ? '编辑用户信息' : '新增用户'}
|
||||
title={id ? '编辑用户信息' : '新增用户'}
|
||||
open={visible}
|
||||
onCancel={onCancel}
|
||||
onOk={handleOk}
|
||||
|
@ -142,22 +143,24 @@ const UserEditModal: React.FC<UserEditModalProps> = ({
|
|||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="userType"
|
||||
name="user_type"
|
||||
label="用户类别"
|
||||
rules={[{ required: true, message: '请选择用户类别' }]}
|
||||
rules={[{ required: false, message: '请选择用户类别' }]}
|
||||
>
|
||||
<Select placeholder="请选择用户类别">
|
||||
<Option value="internal">内部员工</Option>
|
||||
<Option value="external">外部用户</Option>
|
||||
<Option value="partner">合作伙伴</Option>
|
||||
<Option value="temporary">临时用户</Option>
|
||||
</Select>
|
||||
<Select placeholder="请选择用户类别" options={USER_TYPE_OPTIONS} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="idCard"
|
||||
name="gender"
|
||||
label="性别"
|
||||
rules={[{ required: false, message: '请选择性别' }]}
|
||||
>
|
||||
<Select placeholder="请选择性别" options={GENDER_OPTIONS} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="identity_no"
|
||||
label="身份证号"
|
||||
rules={[
|
||||
{ required: true, message: '请输入身份证号' },
|
||||
{ required: false, message: '请输入身份证号' },
|
||||
{
|
||||
pattern:
|
||||
/^[1-9]\d{5}(18|19|20|21|22|23|24|25|26|27|28|29|30|31)\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20)$/,
|
||||
|
@ -168,18 +171,6 @@ const UserEditModal: React.FC<UserEditModalProps> = ({
|
|||
<Input placeholder="请输入身份证号" />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="gender"
|
||||
label="性别"
|
||||
rules={[{ required: false, message: '请选择性别' }]}
|
||||
>
|
||||
<Select placeholder="请选择性别">
|
||||
<Option value="male">男</Option>
|
||||
<Option value="female">女</Option>
|
||||
<Option value="other">其他</Option>
|
||||
<Option value="prefer-not-to-say">不愿透露</Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
{/* 电话号码 */}
|
||||
<Form.Item
|
||||
name="cell_phone"
|
||||
|
|
|
@ -1,37 +1,39 @@
|
|||
// d:\VDI\vdi\web-fe\src\pages\userList\mod\group\index.tsx
|
||||
import { Button, Form, Input, Modal, TreeSelect } from 'antd';
|
||||
import React, { useEffect } from 'react';
|
||||
import { ERROR_CODE } from '@/constants/constants';
|
||||
import { addUserGroup } from '@/services/userList';
|
||||
import { Button, Form, Input, Modal, TreeSelect, message } from 'antd';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
|
||||
interface CreatGroupProps {
|
||||
title: string;
|
||||
type:number;
|
||||
visible: boolean;
|
||||
selectedOrg?: number;
|
||||
onCancel: () => void;
|
||||
onOk: (values: any) => void;
|
||||
onOk: (values?: any) => void;
|
||||
orgTreeData: User.OrganizationNode[];
|
||||
}
|
||||
|
||||
const CreatGroup: React.FC<CreatGroupProps> = (props) => {
|
||||
const { visible, onCancel, onOk, orgTreeData, selectedOrg } = props;
|
||||
const {
|
||||
title = '新增分组',
|
||||
visible,
|
||||
onCancel,
|
||||
onOk,
|
||||
orgTreeData,
|
||||
selectedOrg,
|
||||
type
|
||||
} = props;
|
||||
const [loading, setLoading] = useState<boolean>(false);
|
||||
const [form] = Form.useForm();
|
||||
|
||||
useEffect(() => {
|
||||
const initialValues = { parent_id: [selectedOrg] };
|
||||
form.setFieldsValue(initialValues);
|
||||
if (selectedOrg) {
|
||||
const initialValues = { parent_id: [selectedOrg] };
|
||||
form.setFieldsValue(initialValues);
|
||||
}
|
||||
}, [visible, form, selectedOrg]);
|
||||
|
||||
// Flatten tree data for parent group selection
|
||||
// const flattenTreeData = (data: OrganizationNode[], result: { value: string; label: string }[] = []) => {
|
||||
// data.forEach(item => {
|
||||
// result.push({ value: item.id as string, label: item.name as string });
|
||||
// if (item.children) {
|
||||
// flattenTreeData(item.children, result);
|
||||
// }
|
||||
// });
|
||||
// return result;
|
||||
// };
|
||||
|
||||
// const parentGroupOptions = flattenTreeData(orgTreeData);
|
||||
|
||||
const handleOk = () => {
|
||||
form.submit();
|
||||
};
|
||||
|
@ -41,14 +43,34 @@ const CreatGroup: React.FC<CreatGroupProps> = (props) => {
|
|||
onCancel();
|
||||
};
|
||||
|
||||
const handleFinish = (values: any) => {
|
||||
onOk(values);
|
||||
form.resetFields();
|
||||
const handleFinish = async () => {
|
||||
const values: any = await form.validateFields();
|
||||
setLoading(true);
|
||||
try {
|
||||
console.log('values=====', values);
|
||||
const { name, parent_id } = values || {};
|
||||
const params: any = { name, type: type };
|
||||
if (parent_id) {
|
||||
params.parent_id = parent_id;
|
||||
}
|
||||
const res = await addUserGroup(params);
|
||||
setLoading(false);
|
||||
const { code } = res || {};
|
||||
if (code === ERROR_CODE) {
|
||||
message.success('添加成功');
|
||||
form.resetFields();
|
||||
onCancel();
|
||||
onOk();
|
||||
}
|
||||
} catch (error) {
|
||||
setLoading(false);
|
||||
message.error('创建用户分组失败');
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal
|
||||
title="添加用户分组"
|
||||
title={title}
|
||||
open={visible}
|
||||
onOk={handleOk}
|
||||
onCancel={handleCancel}
|
||||
|
@ -56,12 +78,14 @@ const CreatGroup: React.FC<CreatGroupProps> = (props) => {
|
|||
cancelText="取消"
|
||||
centered={true}
|
||||
destroyOnHidden={true}
|
||||
width={600}
|
||||
footer={
|
||||
<div style={{ display: 'flex', justifyContent: 'right' }}>
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={handleOk}
|
||||
style={{ marginRight: '20px' }}
|
||||
loading={loading}
|
||||
>
|
||||
确定
|
||||
</Button>
|
||||
|
@ -81,7 +105,7 @@ const CreatGroup: React.FC<CreatGroupProps> = (props) => {
|
|||
style={{ paddingTop: '20px', paddingBottom: '20px' }}
|
||||
>
|
||||
<Form.Item
|
||||
name="groupName"
|
||||
name="name"
|
||||
label="分组名"
|
||||
rules={[{ required: true, message: '请输入分组名!' }]}
|
||||
>
|
||||
|
@ -91,7 +115,7 @@ const CreatGroup: React.FC<CreatGroupProps> = (props) => {
|
|||
<Form.Item name="parent_id" label="父分组名">
|
||||
<TreeSelect
|
||||
showSearch
|
||||
allowClear={false}
|
||||
allowClear={true}
|
||||
treeDefaultExpandAll
|
||||
placeholder="请选择父分组名"
|
||||
treeData={orgTreeData}
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
import { request } from '@umijs/max';
|
||||
|
||||
const BASE_URL = '/api/v1/terminal';
|
||||
|
||||
// 根据终端序列号查询镜像列表
|
||||
export async function getTerminalList(params:any) {
|
||||
// console.log('终端列表 params', params);
|
||||
return request<Termial.Termial_ListInfo>(`${BASE_URL}/query/devicelist`, {
|
||||
method: 'POST',
|
||||
data: params,
|
||||
});
|
||||
}
|
||||
|
||||
export async function deleteDevice(params:any) {
|
||||
// console.log('终端列表 params', params);
|
||||
return request<Termial.Termial_ListInfo>(`${BASE_URL}/delete/device`, {
|
||||
method: 'POST',
|
||||
data: params,
|
||||
});
|
||||
}
|
||||
|
||||
export async function saveDevice(params:any) {
|
||||
// console.log('终端列表 params', params);
|
||||
return request<Termial.Termial_ListInfo>(`${BASE_URL}/save/device`, {
|
||||
method: 'POST',
|
||||
data: params,
|
||||
});
|
||||
}
|
|
@ -1,15 +1,15 @@
|
|||
import { request } from '@umijs/max';
|
||||
|
||||
// 新建用户分组
|
||||
const BASE_URL = '/api/nex/v1';
|
||||
export async function addUserGroup(body?: any) {
|
||||
return request<any>('/api/v1/user', {
|
||||
return request<any>(`${BASE_URL}/user/device/group/add`, {
|
||||
method: 'POST',
|
||||
data: body,
|
||||
});
|
||||
}
|
||||
// 获取用户分组
|
||||
export async function getUserGroup(body?: any) {
|
||||
return request<any>('/api/v1/user', {
|
||||
export async function getGroupTree(body?: any) {
|
||||
return request<any>(`${BASE_URL}/user/device/group/query`, {
|
||||
method: 'POST',
|
||||
data: body,
|
||||
});
|
||||
|
@ -17,15 +17,15 @@ export async function getUserGroup(body?: any) {
|
|||
|
||||
// 删除用户分组
|
||||
export async function deleteUserGroup(body?: any) {
|
||||
return request<any>('/api/v1/user', {
|
||||
return request<any>(`${BASE_URL}/user/device/group/delete`, {
|
||||
method: 'POST',
|
||||
data: body,
|
||||
});
|
||||
}
|
||||
|
||||
// 查询用户分组
|
||||
// 查询用户
|
||||
export async function getUserList(body?: any) {
|
||||
return request<any>('/api/v1/user', {
|
||||
return request<any>(`${BASE_URL}/user/select/page`, {
|
||||
method: 'POST',
|
||||
data: body,
|
||||
});
|
||||
|
@ -33,7 +33,7 @@ export async function getUserList(body?: any) {
|
|||
|
||||
// 新建用户
|
||||
export async function addUser(body?: any) {
|
||||
return request<any>('/api/v1/user', {
|
||||
return request<any>(`${BASE_URL}/user/add`, {
|
||||
method: 'POST',
|
||||
data: body,
|
||||
});
|
||||
|
@ -41,7 +41,7 @@ export async function addUser(body?: any) {
|
|||
|
||||
// 编辑用户
|
||||
export async function editUser(body?: any) {
|
||||
return request<any>('/api/v1/user', {
|
||||
return request<any>(`${BASE_URL}/user/update`, {
|
||||
method: 'POST',
|
||||
data: body,
|
||||
});
|
||||
|
@ -49,7 +49,7 @@ export async function editUser(body?: any) {
|
|||
|
||||
//获取某个用户信息
|
||||
export async function getUserById(body?: any) {
|
||||
return request<any>('/api/v1/user', {
|
||||
return request<any>(`${BASE_URL}/user/query`, {
|
||||
method: 'POST',
|
||||
data: body,
|
||||
});
|
||||
|
@ -57,7 +57,7 @@ export async function getUserById(body?: any) {
|
|||
|
||||
//删除用户
|
||||
export async function deleteUser(body?: any) {
|
||||
return request<any>('/api/v1/user', {
|
||||
return request<any>(`${BASE_URL}/user/delete`, {
|
||||
method: 'DELETE',
|
||||
data: body,
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue