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