import React, { useState, useEffect, useCallback, useRef } from 'react';
import { Empty, message, Select, Input } from 'antd';
import { EditOutlined } from '@ant-design/icons';
import { Button, Dialog, Drawer } from 'tdesign-mobile-react';
import { setNavigationBar } from '@suplink/jssdk';
import { useNavigate } from 'react-router-dom';
import { URLData } from "../../util/deviceOption";
import { postData } from "../../util/requestMethod";
import _ from 'lodash';
import './index.css';
import UserUpdate from './UserUpdate';
const { Option } = Select;
const Alarm = () => {
const navigate = useNavigate();
const [totalList, setTotalList] = useState([]);
const [loading, setLoading] = useState(false);
const [loadingMore, setLoadingMore] = useState(false);
const [drawerVisible, setDrawerVisible] = useState(false);
const [editingUserId, setEditingUserId] = useState(null);
const [editingUserData, setEditingUserData] = useState(null);
// 查询条件状态
const [usernameInput, setUsernameInput] = useState('');
const [realNameInput, setRealNameInput] = useState('');
const [selectedRole, setSelectedRole] = useState();
const isLoadMoreRef = useRef(false);
const searchParamsRef = useRef({});
const totalCountRef = useRef(0);
const initializedRef = useRef(false);
const isFirstLoadRef = useRef(true);
const roleOptions = [
{ label: '管理员', value: 'admin' },
{ label: '操作员', value: 'operator' },
{ label: '查看者', value: 'viewer' }
];
const [pagination, setPagination] = useState({
current: 1,
pageSize: 10,
hasMore: true
});
// 构建查询参数
const buildSearchParams = useCallback(() => {
const params = {};
if (usernameInput.trim()) {
params.username = usernameInput.trim();
}
if (realNameInput.trim()) {
params.realName = realNameInput.trim();
}
if (selectedRole) {
params.role = selectedRole;
}
return params;
}, [usernameInput, realNameInput, selectedRole]);
// 查询人员数据
const getAlarmData = useCallback(async (isLoadMore = false, targetPage = null, searchParams = null) => {
if ((!isLoadMore && loading) || (isLoadMore && loadingMore)) {
return;
}
if (isLoadMore) {
setLoadingMore(true);
isLoadMoreRef.current = true;
} else {
setLoading(true);
isLoadMoreRef.current = false;
}
const targetPageNum = targetPage || (isLoadMore ? pagination.current + 1 : 1);
const currentSearchParams = searchParams !== null ? searchParams : buildSearchParams();
const params = {
...currentSearchParams,
page: targetPageNum,
per_page: pagination.pageSize
};
try {
const res = await postData(URLData.queryPreson, params);
if (res && res.list) {
const receivedDataCount = res.list.length;
if (isLoadMore) {
setTotalList(prevList => [...prevList, ...res.list]);
setLoadingMore(false);
} else {
setTotalList(res.list);
setLoading(false);
}
totalCountRef.current = res.total || 0;
let hasMoreData = false;
if (res.total !== undefined && res.total !== null) {
const loadedCount = isLoadMore ?
(totalList.length + receivedDataCount) : receivedDataCount;
hasMoreData = loadedCount < res.total;
} else {
hasMoreData = receivedDataCount >= pagination.pageSize;
}
setPagination(prev => ({
...prev,
current: targetPageNum,
hasMore: hasMoreData
}));
} else if (Array.isArray(res)) {
setTotalList(res);
setLoading(false);
setLoadingMore(false);
setPagination(prev => ({
...prev,
hasMore: false,
current: 1
}));
} else {
setTotalList([]);
setLoading(false);
setLoadingMore(false);
setPagination(prev => ({
...prev,
hasMore: false,
current: 1
}));
}
} catch (error) {
console.error('查询数据失败:', error);
setLoading(false);
setLoadingMore(false);
message.error('数据加载失败');
} finally {
isLoadMoreRef.current = false;
}
}, [pagination.pageSize, loading, loadingMore, totalList.length, buildSearchParams]);
// 执行查询
const handleSearch = useCallback(() => {
const currentSearchParams = buildSearchParams();
searchParamsRef.current = currentSearchParams;
setPagination(prev => ({ ...prev, current: 1, hasMore: true }));
getAlarmData(false, 1, currentSearchParams);
}, [buildSearchParams, getAlarmData]);
// 重置查询条件
const handleReset = useCallback(() => {
setUsernameInput('');
setRealNameInput('');
setSelectedRole('');
searchParamsRef.current = {};
setPagination(prev => ({ ...prev, current: 1, hasMore: true }));
setTimeout(() => {
getAlarmData(false, 1, {});
}, 0);
}, [getAlarmData]);
// 修改用户
const handleEdit = (user) => {
console.log('修改用户:', user);
setEditingUserId(user.id);
setEditingUserData(user); // 传递完整的用户数据
setDrawerVisible(true);
};
// 删除用户
const handleDelete = (user) => {
const updateData = {
'where': { id: user.id },
'update': { dr: 1 }
};
Dialog.confirm({
title: "确认删除",
content: `确定删除用户 "${user.realName || user.username}" ?`,
confirmBtn: {
content: '确定',
theme: 'danger',
},
cancelBtn: '取消',
onConfirm: async () => {
const res = await postData(URLData.updatePerson, { "updateData": updateData });
if (res === '执行成功') {
message.success('删除成功');
handleSearch();
} else {
message.error('删除失败');
}
}
});
};
// 新增用户
const handleAdd = () => {
navigate(`/useradd`)
};
// 初始加载
useEffect(() => {
setNavigationBar({ backButton: false, title: "人员管理" });
if (!initializedRef.current) {
searchParamsRef.current = {};
getAlarmData(false, 1, {});
initializedRef.current = true;
setTimeout(() => {
isFirstLoadRef.current = false;
}, 1000);
}
}, []);
// 防抖搜索
const debouncedSearchRef = useRef(
_.debounce((searchParams) => {
if (!isLoadMoreRef.current && !isFirstLoadRef.current) {
setPagination(prev => ({ ...prev, current: 1, hasMore: true }));
getAlarmData(false, 1, searchParams);
}
}, 500)
);
// 加载更多
const showMore = () => {
if (pagination.hasMore && !loadingMore && !loading) {
getAlarmData(true, pagination.current + 1, searchParamsRef.current);
}
}
useEffect(() => {
if (!isLoadMoreRef.current && initializedRef.current && !isFirstLoadRef.current) {
const currentSearchParams = buildSearchParams();
searchParamsRef.current = currentSearchParams;
debouncedSearchRef.current(currentSearchParams);
}
return () => {
debouncedSearchRef.current.cancel();
};
}, [usernameInput, realNameInput, selectedRole, buildSearchParams]);
// 处理 Drawer 关闭
const handleDrawerClose = () => {
setDrawerVisible(false);
// 延迟清空状态,确保动画期间组件不卸载
setTimeout(() => {
setEditingUserId(null);
setEditingUserData(null);
}, 300);
};
// 处理修改成功
const handleUpdateSuccess = () => {
handleDrawerClose();
handleSearch(); // 刷新列表
message.success('用户信息更新成功');
};
// 角色映射
const roleMap = {
'admin': '管理员',
'operator': '操作员',
'viewer': '查看者'
};
return (
<div className="user-content-box">
{/* 固定在顶部的查询条件和新增按钮 */}
<div className="sticky-header">
<div className="user-add-btn-container">
<Button size="small" variant="outline" onClick={handleAdd} className="user-add-btn">+新增</Button>
</div>
<div className='ueser-search-form'>
<div className='userinfo-select'>
<span className='user-search-label'>用户名:</span>
<Input
value={usernameInput}
placeholder="请输入用户名"
onChange={(e) => setUsernameInput(e.target.value)}
allowClear
style={{ width: 260 }}
/>
</div>
<div className='username-select'>
<span className='username-search-label'>姓名:</span>
<Input
value={realNameInput}
placeholder="请输入姓名"
onChange={(e) => setRealNameInput(e.target.value)}
allowClear
style={{ width: 260 }}
/>
</div>
<div className='userrole-select'>
<span className='userrole-search-label'>所属角色:</span>
<Select
allowClear
showSearch
className='userinfo-select-dom'
placeholder="请选择角色"
value={selectedRole}
onChange={setSelectedRole}
optionFilterProp="children"
filterOption={(input, option) =>
option.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
}
>
{roleOptions.map((item) => (
<Option key={item.value} value={item.value}>{item.label}</Option>
))}
</Select>
</div>
</div>
</div>
{/* 用户列表 */}
<div className='user-list-box user-card-container'>
{loading ? (
<div style={{ textAlign: 'center', padding: '50px' }}>加载中...</div>
) : totalList.length > 0 ? (
<>
<div className="user-card-list">
{totalList.map((user, index) => (
<div key={user.id || index} className="user-card">
<div className="user-card-header">
<h3 className="user-card-name">
{user.realName || '-'}
<span className={`user-card-role user-role-${user.role}`}>
{roleMap[user.role] || user.role}
</span>
</h3>
</div>
<div className="user-card-body">
<div className="user-card-info">
<div className="info-item">
<span className="user-info-label">用户名:</span>
<span className="user-info-value">{user.username || '-'}</span>
</div>
<div className="info-item">
<span className="user-info-label">部门:</span>
<span className="user-info-value">{user.department || '-'}</span>
</div>
<div className="info-item">
<span className="user-info-label">手机号:</span>
<span className="user-info-value">{user.phone || '-'}</span>
</div>
<div className="info-item">
<span className="user-info-label">邮箱:</span>
<span className="user-info-value">{user.email || '-'}</span>
</div>
</div>
</div>
<div className="user-card-actions">
<Button
variant="outline"
size="small"
onClick={() => handleEdit(user)}
icon={<EditOutlined />}
className="edit-btn"
>
修改
</Button>
<Button
variant="outline"
size="small"
onClick={() => handleDelete(user)}
className="delete-btn"
>
删除
</Button>
</div>
</div>
))}
</div>
{pagination.hasMore ? (
<div
className='load-more'
onClick={showMore}
style={{
cursor: loadingMore ? 'not-allowed' : 'pointer',
opacity: loadingMore ? 0.6 : 1
}}
>
{loadingMore ? '加载中...' : '加载更多'}
</div>
) : (
totalList.length >= pagination.pageSize && <div className='no-more'>--暂无更多数据--</div>
)}
</>
) : (
<Empty description="暂无数据" image={Empty.PRESENTED_IMAGE_SIMPLE} />
)}
</div>
{/* Drawer - 修改用户信息 */}
<Drawer
visible={drawerVisible}
onClose={handleDrawerClose}
destroyOnClose={true}
placement="right"
size="100%"
header="修改用户信息"
>
<UserUpdate/>
</Drawer>
</div>
)
};
export default Alarm;
以上代码中在Drawer引入UserUpdate子组件并未展示,应如何解决该问题