feat(前端):用户、终端

master
shaot 2025-08-14 14:18:36 +08:00
parent b73913d78e
commit f17de4dc33
12 changed files with 207 additions and 80 deletions

View File

@ -53,3 +53,6 @@ export const PRIOPRITY_OPTIONS = [
{ value: 2, label: '二级' }, { value: 2, label: '二级' },
{ value: 3, label: '三级' }, { value: 3, label: '三级' },
]; ];
export const DEFAULT_PASSWORD="a123456"
export const DEFAULT_BLICK_TAB="黑名单"

View File

@ -1,5 +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 {
DEFAULT_BLICK_TAB,
DEVICE_TYPE_MAP,
ERROR_CODE,
} from '@/constants/constants';
import CustomTree from '@/pages/components/customTree'; import CustomTree from '@/pages/components/customTree';
import CreatGroup from '@/pages/userList/mod/group'; import CreatGroup from '@/pages/userList/mod/group';
import { deleteDevice, getTerminalList } from '@/services/terminal'; import { deleteDevice, getTerminalList } from '@/services/terminal';
@ -31,6 +35,7 @@ import EditModal from './mod/eidtDevice';
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 [selectedOrgNode, setSelectedOrgNode] = useState<any>();
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>('');
@ -307,12 +312,30 @@ const UserListPage: React.FC = () => {
title: '操作', title: '操作',
key: 'actions', key: 'actions',
align: 'center', align: 'center',
width: 150, width: 230,
fixed: 'right', fixed: 'right',
render: (_, record) => ( render: (_, record) => (
<div style={{ display: 'flex', alignItems: 'center' }}> <div style={{ display: 'flex', alignItems: 'center' }}>
<Button type="link" onClick={() => handleEditInfo(record)}> <Button
type="link"
size="small"
onClick={() => {
setBindUserData({
recordData: record,
visible: true,
});
}}
>
</Button>
<Button
type="link"
size="small"
onClick={() => {
setBindImageDta({ recordData: record, visible: true });
}}
>
</Button> </Button>
<Popover <Popover
placement="bottomRight" placement="bottomRight"
@ -329,26 +352,8 @@ const UserListPage: React.FC = () => {
<Button type="link"></Button> <Button type="link"></Button>
</Popconfirm> </Popconfirm>
<div> <div>
<Button <Button type="link" onClick={() => handleEditInfo(record)}>
type="link"
onClick={() => {
setBindUserData({
recordData: record,
visible: true,
});
}}
>
</Button>
</div>
<div>
<Button
type="link"
onClick={() => {
setBindImageDta({ recordData: record, visible: true });
}}
>
</Button> </Button>
</div> </div>
</div> </div>
@ -364,10 +369,12 @@ const UserListPage: React.FC = () => {
}, },
]; ];
const onOrgSelect = (selectedKeys: React.Key[]) => { const onOrgSelect = (selectedKeys: React.Key[], e: any) => {
const { node } = e || {};
if (selectedKeys.length > 0) { if (selectedKeys.length > 0) {
setSelectedOrg(selectedKeys[0] as number); setSelectedOrg(selectedKeys[0] as number);
setCurrentPage(1); setCurrentPage(1);
setSelectedOrgNode(node);
} }
}; };
@ -382,7 +389,6 @@ const UserListPage: React.FC = () => {
}; };
const onSelectChange = (newSelectedRowKeys: React.Key[]) => { const onSelectChange = (newSelectedRowKeys: React.Key[]) => {
console.log('selectedRowKeys changed: ', newSelectedRowKeys);
setSelectedRowKeys(newSelectedRowKeys as any); setSelectedRowKeys(newSelectedRowKeys as any);
}; };
const onDeleteGroup = async () => { const onDeleteGroup = async () => {
@ -399,7 +405,7 @@ const UserListPage: React.FC = () => {
const { data } = result || {}; const { data } = result || {};
const { total = 0 } = data || {}; const { total = 0 } = data || {};
if (total > 0) { if (total > 0) {
message.info("该分组下有终端,请先删除该分组下的所有终端"); message.info('该分组下有终端,请先删除该分组下的所有终端');
} else { } else {
onDeleteGroupSave(); onDeleteGroupSave();
} }
@ -470,6 +476,9 @@ const UserListPage: React.FC = () => {
type="text" type="text"
style={{ marginRight: '8px', fontSize: '16px' }} style={{ marginRight: '8px', fontSize: '16px' }}
icon={<PlusOutlined />} icon={<PlusOutlined />}
disabled={
selectedOrgNode && selectedOrgNode.name === DEFAULT_BLICK_TAB
}
onClick={() => setVisible(true)} onClick={() => setVisible(true)}
/> />
<Popconfirm <Popconfirm
@ -479,13 +488,19 @@ const UserListPage: React.FC = () => {
// onCancel={cancel} // onCancel={cancel}
okText="删除" okText="删除"
cancelText="取消" cancelText="取消"
disabled={!selectedOrg} disabled={
!selectedOrg ||
(selectedOrgNode && selectedOrgNode.is_deleted === 0)
}
> >
<Button <Button
type="text" type="text"
style={{ fontSize: '16px' }} style={{ fontSize: '16px' }}
icon={<DeleteOutlined />} icon={<DeleteOutlined />}
disabled={!selectedOrg} disabled={
!selectedOrg ||
(selectedOrgNode && selectedOrgNode.is_deleted === 0)
}
/> />
</Popconfirm> </Popconfirm>
</div> </div>

View File

@ -7,6 +7,7 @@ import CustomTable from '../selectedTable/table';
import SelectConponents from './table'; import SelectConponents from './table';
interface SelectedTableProps { interface SelectedTableProps {
loading?: boolean;
placement?: PopoverProps['placement']; placement?: PopoverProps['placement'];
onCancel?: () => void; onCancel?: () => void;
onOk?: (values: any) => void; onOk?: (values: any) => void;
@ -17,6 +18,7 @@ interface SelectedTableProps {
const SelectedTable: React.FC<SelectedTableProps> = (props) => { const SelectedTable: React.FC<SelectedTableProps> = (props) => {
const { const {
placement = 'bottomLeft', placement = 'bottomLeft',
loading,
value: formValue, value: formValue,
onChange: onBindImageChange, onChange: onBindImageChange,
} = props; } = props;
@ -56,6 +58,7 @@ const SelectedTable: React.FC<SelectedTableProps> = (props) => {
list.push({ list.push({
id: item.id, id: item.id,
image_name: item.image_name, image_name: item.image_name,
image_file_name: item.image_file_name,
}); });
}); });
setTableData(list); setTableData(list);
@ -100,7 +103,7 @@ const SelectedTable: React.FC<SelectedTableProps> = (props) => {
}; };
const accessPopover = ( const accessPopover = (
<div style={{ width: '600px' }}> <div style={{ width: '700px' }}>
<SelectConponents <SelectConponents
onUserTableSelect={onUserTableSelect} onUserTableSelect={onUserTableSelect}
selectedRowKeys={selectedRowKeys} selectedRowKeys={selectedRowKeys}
@ -139,8 +142,17 @@ const SelectedTable: React.FC<SelectedTableProps> = (props) => {
title: '镜像名称', title: '镜像名称',
dataIndex: 'image_name', dataIndex: 'image_name',
key: 'image_name', key: 'image_name',
ellipsis: true,
render: (text) => { render: (text) => {
return <Tooltip>{text || '--'}</Tooltip>; return <Tooltip title={text || '--'}>{text || '--'}</Tooltip>;
},
},
{
title: '源文件名',
ellipsis: true,
dataIndex: 'image_file_name',
render: (text) => {
return <Tooltip title={text || '--'}>{text || '--'}</Tooltip>;
}, },
}, },
{ {
@ -157,9 +169,7 @@ const SelectedTable: React.FC<SelectedTableProps> = (props) => {
okText="删除" okText="删除"
cancelText="取消" cancelText="取消"
> >
<Button type="link"> <Button type="link"></Button>
</Button>
</Popconfirm> </Popconfirm>
), ),
}, },
@ -201,6 +211,7 @@ const SelectedTable: React.FC<SelectedTableProps> = (props) => {
</Popconfirm> </Popconfirm>
</Space> </Space>
<CustomTable <CustomTable
loading={loading}
dataSource={tableData} dataSource={tableData}
onDelete={handleDelete} onDelete={handleDelete}
columns={getColumns()} columns={getColumns()}

View File

@ -65,8 +65,18 @@ const TablePage: React.FC<TableProps> = ({
{ {
title: '镜像名称', title: '镜像名称',
dataIndex: 'image_name', dataIndex: 'image_name',
ellipsis: true,
render: (text) => { render: (text) => {
return <Tooltip>{text || '--'}</Tooltip>; return <Tooltip title={text || '--'}>{text || '--'}</Tooltip>;
},
},
{
title: '源文件名',
ellipsis: true,
width: 300,
dataIndex: 'image_file_name',
render: (text) => {
return <Tooltip title={text || '--'}>{text || '--'}</Tooltip>;
}, },
}, },
]; ];
@ -104,7 +114,7 @@ const TablePage: React.FC<TableProps> = ({
rowKey="id" rowKey="id"
loading={loading} loading={loading}
rowSelection={{ rowSelection={{
selectedRowKeys:selectedRowKeys, selectedRowKeys: selectedRowKeys,
preserveSelectedRowKeys: true, preserveSelectedRowKeys: true,
onChange: onUserTableSelect, onChange: onUserTableSelect,
}} }}

View File

@ -1,8 +1,10 @@
// index.tsx // index.tsx
import { ERROR_CODE } from '@/constants/constants'; import { ERROR_CODE } from '@/constants/constants';
import { getBindImageAdd, getBindImageList } from '@/services/terminal'; import { getBindImageAdd, getBindImageList } from '@/services/terminal';
import { ExclamationCircleOutlined } from '@ant-design/icons';
import { Button, Form, message, Modal } from 'antd'; import { Button, Form, message, Modal } from 'antd';
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { v4 as uuidv4 } from 'uuid';
import SelectedTable from '../ImageSelectedTable/index'; import SelectedTable from '../ImageSelectedTable/index';
import styles from './index.less'; import styles from './index.less';
@ -22,36 +24,46 @@ const BindUserModal: React.FC<UserEditModalProps> = ({
const { recordData, visible } = dataDetial || {}; const { recordData, visible } = dataDetial || {};
const { device_id } = recordData || {}; const { device_id } = recordData || {};
const [form] = Form.useForm(); const [form] = Form.useForm();
const [loading, setLoading] = useState<boolean>(false);
const [dataSource, setDataSource] = useState<any[]>([]); const [dataSource, setDataSource] = useState<any[]>([]);
const [currentId, setCurrentId] = useState<any>(uuidv4());
useEffect(() => { useEffect(() => {
if (!device_id) return;
setLoading(true);
const params = { device_id: device_id }; const params = { device_id: device_id };
getBindImageList(params).then((res: any) => { getBindImageList(params)
const { code, data = [] } = res || {}; .then((res: any) => {
if (code === ERROR_CODE) { const { code, data = [] } = res || {};
if (data && data.length) { if (code === ERROR_CODE) {
const imageList: any[] = []; if (data && data.length) {
data.forEach((item: any) => { const imageList: any[] = [];
imageList.push({ data.forEach((item: any) => {
id: item.image_id, imageList.push({
image_name: item.image_name, id: item.image_id,
// current_id: item.id, image_name: item.image_name,
image_file_name: item.image_file_name,
// current_id: item.id,
});
}); });
}); setDataSource(data);
setDataSource(data); const initialValues = { image_list: imageList };
const initialValues = { image_list: imageList }; form.setFieldsValue(initialValues);
form.setFieldsValue(initialValues); }
} }
} })
}); .finally(() => {
}, [visible, form, recordData]); setLoading(false);
});
}, [visible, form, recordData, currentId]);
const onBind = (payload: any) => { const onBind = (payload: any) => {
getBindImageAdd(payload).then((res: any) => { getBindImageAdd(payload).then((res: any) => {
const { code } = res || {}; const { code } = res || {};
if (code === ERROR_CODE) { if (code === ERROR_CODE) {
message.success('绑定成功'); message.success('绑定成功');
if (onOk) onOk(); setCurrentId(uuidv4());
// if (onOk) onOk();
} else { } else {
message.error('绑定失败'); message.error('绑定失败');
} }
@ -79,7 +91,7 @@ const BindUserModal: React.FC<UserEditModalProps> = ({
}); });
const payload: any = { const payload: any = {
data: list, data: list,
device_id:device_id, device_id: device_id,
}; };
onBind(payload); onBind(payload);
} catch (error) { } catch (error) {
@ -87,6 +99,25 @@ const BindUserModal: React.FC<UserEditModalProps> = ({
} }
}; };
// const onCancelHandle = async () => {
// const values = await form.validateFields();
// const { image_list = [] } = values || {};
// if (dataSource.length === image_list.length) {
// onCancel();
// } else {
// Modal.confirm({
// title: '镜像绑定信息有更新未保存,请确认是关闭弹窗',
// icon: <ExclamationCircleOutlined />,
// content: '',
// onOk() {
// onCancel();
// },
// okText: '确认',
// cancelText: '取消',
// });
// }
// };
return ( return (
<Modal <Modal
title={'绑定镜像'} title={'绑定镜像'}
@ -130,7 +161,7 @@ const BindUserModal: React.FC<UserEditModalProps> = ({
label="选择镜像" label="选择镜像"
rules={[{ required: false, message: '请输入终端型号' }]} rules={[{ required: false, message: '请输入终端型号' }]}
> >
<SelectedTable /> <SelectedTable loading={loading} />
</Form.Item> </Form.Item>
{/* <Form.Item {/* <Form.Item
name="description" name="description"

View File

@ -6,6 +6,7 @@ import { getGroupTree } from '@/services/userList';
import { Button, Form, message, Modal } from 'antd'; import { Button, Form, message, Modal } from 'antd';
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import SelectedTable from '../selectedTable'; import SelectedTable from '../selectedTable';
import { v4 as uuidv4 } from 'uuid';
import styles from './index.less'; import styles from './index.less';
interface UserEditModalProps { interface UserEditModalProps {
@ -25,8 +26,10 @@ const BindUserModal: React.FC<UserEditModalProps> = ({
}) => { }) => {
const { recordData, visible } = dataDetial || {}; const { recordData, visible } = dataDetial || {};
const { device_id, device_group_id } = recordData || {}; const { device_id, device_group_id } = recordData || {};
const [loading, setLoading] = useState<boolean>(false);
const [orgTreeData, setOrgTreeData] = useState<User.OrganizationNode[]>([]); const [orgTreeData, setOrgTreeData] = useState<User.OrganizationNode[]>([]);
const [userDataSource, setUserDataSource] = useState<any[]>([]); const [userDataSource, setUserDataSource] = useState<any[]>([]);
const [currentId,setCurrentId] = useState<any>(uuidv4());
// const [groupDataSource, setGroupDataSource] = useState<any[]>([]); // const [groupDataSource, setGroupDataSource] = useState<any[]>([]);
const [form] = Form.useForm(); const [form] = Form.useForm();
@ -57,6 +60,7 @@ const BindUserModal: React.FC<UserEditModalProps> = ({
useEffect(() => { useEffect(() => {
if (!device_id) return; if (!device_id) return;
setLoading(true);
const payload = { device_id: device_id }; const payload = { device_id: device_id };
getBindUserList(payload).then((res: any) => { getBindUserList(payload).then((res: any) => {
const { code, data = [] } = res || {}; const { code, data = [] } = res || {};
@ -90,8 +94,10 @@ const BindUserModal: React.FC<UserEditModalProps> = ({
form.setFieldsValue(initialValues); form.setFieldsValue(initialValues);
} }
} }
}).finally(() => {
setLoading(false);
}); });
}, [visible, form, recordData]); }, [visible, form, recordData,currentId]);
const onBind = (payload: any) => { const onBind = (payload: any) => {
bindUserAdd(payload) bindUserAdd(payload)
@ -99,7 +105,8 @@ const BindUserModal: React.FC<UserEditModalProps> = ({
const { code } = res || {}; const { code } = res || {};
if (code === ERROR_CODE) { if (code === ERROR_CODE) {
message.success('绑定成功'); message.success('绑定成功');
onOk(); // onOk();
setCurrentId(uuidv4())
} else { } else {
message.error('绑定失败'); message.error('绑定失败');
} }
@ -199,7 +206,7 @@ const BindUserModal: React.FC<UserEditModalProps> = ({
label="选择用户" label="选择用户"
rules={[{ required: false, message: '请选择绑定用户' }]} rules={[{ required: false, message: '请选择绑定用户' }]}
> >
<SelectedTable orgTreeData={orgTreeData} /> <SelectedTable orgTreeData={orgTreeData} loading={loading}/>
</Form.Item> </Form.Item>
{/* <Form.Item {/* <Form.Item
name="description" name="description"

View File

@ -114,7 +114,7 @@ const UserEditModal: React.FC<UserEditModalProps> = ({
label="终端标识" label="终端标识"
rules={[{ required: true, message: '请输入终端标识' }]} rules={[{ required: true, message: '请输入终端标识' }]}
> >
<Input /> <Input disabled={id ? true : false} />
</Form.Item> </Form.Item>
<Form.Item <Form.Item

View File

@ -2,13 +2,14 @@
import CustomTree from '@/pages/components/customTree'; 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,Tooltip } from 'antd'; import { Alert, Button, Popconfirm, Popover, Space, Tabs, 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 SelectConponents from '../selectConponents'; import SelectConponents from '../selectConponents';
import CustomTable from './table'; import CustomTable from './table';
interface SelectedTableProps { interface SelectedTableProps {
loading?: boolean;
placement?: PopoverProps['placement']; placement?: PopoverProps['placement'];
selectedOrg?: number; selectedOrg?: number;
onCancel?: () => void; onCancel?: () => void;
@ -22,6 +23,7 @@ const SelectedTable: React.FC<SelectedTableProps> = (props) => {
const { const {
placement = 'bottomLeft', placement = 'bottomLeft',
orgTreeData, orgTreeData,
loading,
value: formValue, value: formValue,
onChange: onBindUserChange, onChange: onBindUserChange,
} = props; } = props;
@ -141,8 +143,9 @@ const SelectedTable: React.FC<SelectedTableProps> = (props) => {
dataIndex: 'name', dataIndex: 'name',
key: 'name', key: 'name',
align: 'center', align: 'center',
ellipsis: true,
render: (text) => { render: (text) => {
return <Tooltip>{text || '--'}</Tooltip>; return <Tooltip title={text || '--'}>{text || '--'}</Tooltip>;
}, },
}, },
{ {
@ -150,7 +153,7 @@ const SelectedTable: React.FC<SelectedTableProps> = (props) => {
dataIndex: 'type', dataIndex: 'type',
key: 'type', key: 'type',
align: 'center', align: 'center',
width: 220, width: 220,
render: (text) => ( render: (text) => (
<span>{text == 1 ? '用户' : text == 2 ? '用户组' : ''}</span> <span>{text == 1 ? '用户' : text == 2 ? '用户组' : ''}</span>
), ),
@ -256,6 +259,7 @@ const SelectedTable: React.FC<SelectedTableProps> = (props) => {
</Popconfirm> </Popconfirm>
</Space> </Space>
<CustomTable <CustomTable
loading={loading}
dataSource={tableData} dataSource={tableData}
onDelete={handleDelete} onDelete={handleDelete}
scrollY={400} scrollY={400}

View File

@ -3,6 +3,7 @@ import type { ColumnsType } from 'antd/es/table';
import React from 'react'; import React from 'react';
interface DeletableTableProps { interface DeletableTableProps {
loading?: boolean;
dataSource: any[]; dataSource: any[];
isSerial?: boolean; isSerial?: boolean;
isAction?: boolean; isAction?: boolean;
@ -16,6 +17,7 @@ interface DeletableTableProps {
const DeletableTable: React.FC<DeletableTableProps> = (props) => { const DeletableTable: React.FC<DeletableTableProps> = (props) => {
const { const {
loading,
dataSource, dataSource,
onDelete, onDelete,
isSerial = true, isSerial = true,

View File

@ -1,5 +1,6 @@
/* eslint-disable @typescript-eslint/no-use-before-define */ /* eslint-disable @typescript-eslint/no-use-before-define */
import { import {
DEFAULT_BLICK_TAB,
ERROR_CODE, ERROR_CODE,
GENDER_MAP, GENDER_MAP,
PRIORITY_MAP, PRIORITY_MAP,
@ -30,6 +31,7 @@ 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<any>(); const [selectedOrg, setSelectedOrg] = useState<any>();
const [selectedOrgNode, setSelectedOrgNode] = useState<any>();
// 用户列表 // 用户列表
const [dataSource, setDataSource] = useState<User.UserItem[]>([]); const [dataSource, setDataSource] = useState<User.UserItem[]>([]);
@ -333,16 +335,24 @@ const UserListPage: React.FC = () => {
title: '操作', title: '操作',
key: 'actions', key: 'actions',
align: 'center', align: 'center',
width: 160, width: 200,
fixed: 'right', fixed: 'right',
render: (_, record) => ( render: (_, record) => (
<div style={{ display: 'flex' }}> <div style={{ display: 'flex' }}>
{/* <Button type="link" onClick={() => handlePassword(record)}> <Button
size="small"
</Button> */} type="link"
<Button type="link" onClick={() => handleEditUserInfo(record)}> onClick={() => handleEditUserInfo(record)}
>
</Button> </Button>
<Button
size="small"
type="link"
onClick={() => handlePassword(record)}
>
</Button>
<Popconfirm <Popconfirm
title="" title=""
description="删除操作不可逆,请确认是否删除?" description="删除操作不可逆,请确认是否删除?"
@ -351,17 +361,21 @@ const UserListPage: React.FC = () => {
okText="删除" okText="删除"
cancelText="取消" cancelText="取消"
> >
<Button type="link"></Button> <Button size="small" type="link">
</Button>
</Popconfirm> </Popconfirm>
</div> </div>
), ),
}, },
]; ];
const onOrgSelect = (selectedKeys: React.Key[]) => { const onOrgSelect = (selectedKeys: React.Key[], e: any) => {
const { node } = e || {};
if (selectedKeys.length > 0) { if (selectedKeys.length > 0) {
setSelectedOrg(selectedKeys[0]); setSelectedOrg(selectedKeys[0]);
setCurrentPage(1); setCurrentPage(1);
setSelectedOrgNode(node);
} }
}; };
@ -462,6 +476,9 @@ const UserListPage: React.FC = () => {
style={{ marginRight: '8px', fontSize: '16px' }} style={{ marginRight: '8px', fontSize: '16px' }}
icon={<PlusOutlined />} icon={<PlusOutlined />}
onClick={() => setVisible(true)} onClick={() => setVisible(true)}
disabled={
selectedOrgNode && selectedOrgNode.name === DEFAULT_BLICK_TAB
}
title="新增" title="新增"
/> />
<Popconfirm <Popconfirm
@ -471,14 +488,20 @@ const UserListPage: React.FC = () => {
// onCancel={cancel} // onCancel={cancel}
okText="删除" okText="删除"
cancelText="取消" cancelText="取消"
disabled={!selectedOrg} disabled={
!selectedOrg ||
(selectedOrgNode && selectedOrgNode.is_deleted === 0)
}
> >
<Button <Button
type="text" type="text"
style={{ fontSize: '16px' }} style={{ fontSize: '16px' }}
icon={<DeleteOutlined />} icon={<DeleteOutlined />}
title="删除" title="删除"
disabled={!selectedOrg} disabled={
!selectedOrg ||
(selectedOrgNode && selectedOrgNode.is_deleted === 0)
}
/> />
</Popconfirm> </Popconfirm>
</div> </div>
@ -630,13 +653,16 @@ const UserListPage: React.FC = () => {
)} )}
<PasswordResetModal <PasswordResetModal
visible={eidtPassword.visible} visible={eidtPassword.visible}
recordData={eidtPassword.recordData}
onCancel={() => { onCancel={() => {
setEidtPassword({ setEidtPassword({
recordData: {}, recordData: {},
visible: false, visible: false,
}); });
}} }}
onOk={() => {}} onOk={() => {
getDataSource();
}}
/> />
</div> </div>
); );

View File

@ -1,4 +1,5 @@
import { import {
DEFAULT_PASSWORD,
ERROR_CODE, ERROR_CODE,
GENDER_OPTIONS, GENDER_OPTIONS,
PRIOPRITY_OPTIONS, PRIOPRITY_OPTIONS,
@ -54,6 +55,7 @@ const UserEditModal: React.FC<UserEditModalProps> = ({
const initialValues = { const initialValues = {
user_group_id: selectedOrg ? selectedOrg : null, user_group_id: selectedOrg ? selectedOrg : null,
status: 1, status: 1,
password: DEFAULT_PASSWORD,
}; };
form.setFieldsValue(initialValues); form.setFieldsValue(initialValues);
} }
@ -176,7 +178,7 @@ const UserEditModal: React.FC<UserEditModalProps> = ({
help="密码必须包含数字和字母,字母区分大小写,且至少6位" help="密码必须包含数字和字母,字母区分大小写,且至少6位"
style={{ marginBottom: '30px' }} style={{ marginBottom: '30px' }}
> >
<Input.Password placeholder="请输入密码" /> <Input.Password disabled={!!id} placeholder="请输入密码" />
</Form.Item> </Form.Item>
<Form.Item <Form.Item

View File

@ -1,13 +1,15 @@
// index.tsx // index.tsx
import { DEFAULT_PASSWORD, ERROR_CODE } from '@/constants/constants';
import { editUser } from '@/services/userList';
import { Button, Form, Input, message, Modal } from 'antd'; import { Button, Form, Input, message, Modal } from 'antd';
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
interface PasswordResetModalProps { interface PasswordResetModalProps {
visible: boolean; visible: boolean;
recordData?: any;
onCancel: () => void; onCancel: () => void;
onOk: (values: { password: string }) => void; onOk: (values?: { password: string }) => void;
confirmLoading?: boolean; confirmLoading?: boolean;
username?: string;
} }
const PasswordResetModal: React.FC<PasswordResetModalProps> = ({ const PasswordResetModal: React.FC<PasswordResetModalProps> = ({
@ -15,20 +17,34 @@ const PasswordResetModal: React.FC<PasswordResetModalProps> = ({
onCancel, onCancel,
onOk, onOk,
confirmLoading = false, confirmLoading = false,
username, recordData,
}) => { }) => {
const [form] = Form.useForm(); const [form] = Form.useForm();
const { id } = recordData || {};
useEffect(() => { useEffect(() => {
if (!visible) { if (!visible) {
form.resetFields(); form.setFieldsValue({ password: DEFAULT_PASSWORD });
} }
}, [visible, form]); }, [visible, form]);
const handleOk = async () => { const handleOk = async () => {
try { try {
const values = await form.validateFields(); const values = await form.validateFields();
onOk(values); const { password } = values || {};
const params = {
id: id,
password: password,
};
const result: any = await editUser(params);
const { code } = result || {};
if (code === ERROR_CODE) {
message.success('密码重置成功');
onCancel();
onOk();
} else {
message.error('密码重置失败');
}
} catch (error) { } catch (error) {
message.error('请检查表单字段'); message.error('请检查表单字段');
} }
@ -65,7 +81,7 @@ const PasswordResetModal: React.FC<PasswordResetModalProps> = ({
return ( return (
<Modal <Modal
title={username ? `重置密码 - ${username}` : '重置密码'} title={`重置密码`}
open={visible} open={visible}
onCancel={onCancel} onCancel={onCancel}
onOk={handleOk} onOk={handleOk}