|
|
@@ -2,116 +2,24 @@ import React, { useState, useEffect, useCallback, useRef } from 'react';
|
|
|
import { Table, Button, message, Modal, Space, Input, Image } from 'antd';
|
|
|
import { PlusOutlined, SearchOutlined, DownloadOutlined } from '@ant-design/icons';
|
|
|
import Highlighter from 'react-highlight-words';
|
|
|
-import { deviceApi } from '../api/deviceApi';
|
|
|
+import { deviceApi, testConnection } from '../api/deviceApi';
|
|
|
import ExcelImportExport from './ExcelImportExport';
|
|
|
import MemberForm from './MemberForm';
|
|
|
|
|
|
const MemberList = () => {
|
|
|
- const [members, setMembers] = useState([]);
|
|
|
- const [loading, setLoading] = useState(false);
|
|
|
- const [isModalVisible, setIsModalVisible] = useState(false);
|
|
|
- const [editingMember, setEditingMember] = useState(null);
|
|
|
- const [searchText, setSearchText] = useState('');
|
|
|
- const [searchedColumn, setSearchedColumn] = useState('');
|
|
|
- const searchInput = useRef(null);
|
|
|
-
|
|
|
- const fetchMembers = useCallback(async () => {
|
|
|
- setLoading(true);
|
|
|
- try {
|
|
|
- const data = await deviceApi.getPersonList();
|
|
|
- setMembers(data);
|
|
|
- } catch (error) {
|
|
|
- console.error('获取会友列表失败', error);
|
|
|
- message.error('获取会友列表失败,请重试');
|
|
|
- } finally {
|
|
|
- setLoading(false);
|
|
|
- }
|
|
|
- }, []);
|
|
|
+ // ... 保持其他状态和函数不变
|
|
|
|
|
|
useEffect(() => {
|
|
|
+ const checkConnection = async () => {
|
|
|
+ const isConnected = await testConnection();
|
|
|
+ if (!isConnected) {
|
|
|
+ message.error('无法连接到服务器,请检查网络连接和服务器状态');
|
|
|
+ }
|
|
|
+ };
|
|
|
+ checkConnection();
|
|
|
fetchMembers();
|
|
|
}, [fetchMembers]);
|
|
|
|
|
|
- const handleSearch = (selectedKeys, confirm, dataIndex) => {
|
|
|
- confirm();
|
|
|
- setSearchText(selectedKeys[0]);
|
|
|
- setSearchedColumn(dataIndex);
|
|
|
- };
|
|
|
-
|
|
|
- const handleReset = (clearFilters) => {
|
|
|
- clearFilters();
|
|
|
- setSearchText('');
|
|
|
- };
|
|
|
-
|
|
|
- const getColumnSearchProps = (dataIndex) => ({
|
|
|
- filterDropdown: ({ setSelectedKeys, selectedKeys, confirm, clearFilters }) => (
|
|
|
- <div style={{ padding: 8 }}>
|
|
|
- <Input
|
|
|
- ref={searchInput}
|
|
|
- placeholder={`搜索 ${dataIndex}`}
|
|
|
- value={selectedKeys[0]}
|
|
|
- onChange={(e) => setSelectedKeys(e.target.value ? [e.target.value] : [])}
|
|
|
- onPressEnter={() => handleSearch(selectedKeys, confirm, dataIndex)}
|
|
|
- style={{ width: 188, marginBottom: 8, display: 'block' }}
|
|
|
- />
|
|
|
- <Space>
|
|
|
- <Button
|
|
|
- type="primary"
|
|
|
- onClick={() => handleSearch(selectedKeys, confirm, dataIndex)}
|
|
|
- icon={<SearchOutlined />}
|
|
|
- size="small"
|
|
|
- style={{ width: 90 }}
|
|
|
- >
|
|
|
- 搜索
|
|
|
- </Button>
|
|
|
- <Button onClick={() => handleReset(clearFilters)} size="small" style={{ width: 90 }}>
|
|
|
- 重置
|
|
|
- </Button>
|
|
|
- </Space>
|
|
|
- </div>
|
|
|
- ),
|
|
|
- filterIcon: (filtered) => <SearchOutlined style={{ color: filtered ? '#1890ff' : undefined }} />,
|
|
|
- onFilter: (value, record) =>
|
|
|
- record[dataIndex] ? record[dataIndex].toString().toLowerCase().includes(value.toLowerCase()) : '',
|
|
|
- onFilterDropdownVisibleChange: (visible) => {
|
|
|
- if (visible) {
|
|
|
- setTimeout(() => searchInput.current?.select(), 100);
|
|
|
- }
|
|
|
- },
|
|
|
- render: (text) =>
|
|
|
- searchedColumn === dataIndex ? (
|
|
|
- <Highlighter
|
|
|
- highlightStyle={{ backgroundColor: '#ffc069', padding: 0 }}
|
|
|
- searchWords={[searchText]}
|
|
|
- autoEscape
|
|
|
- textToHighlight={text ? text.toString() : ''}
|
|
|
- />
|
|
|
- ) : (
|
|
|
- text
|
|
|
- ),
|
|
|
- });
|
|
|
-
|
|
|
- const handleAdd = () => {
|
|
|
- setEditingMember(null);
|
|
|
- setIsModalVisible(true);
|
|
|
- };
|
|
|
-
|
|
|
- const handleEdit = (record) => {
|
|
|
- setEditingMember(record);
|
|
|
- setIsModalVisible(true);
|
|
|
- };
|
|
|
-
|
|
|
- const handleDelete = async (personId) => {
|
|
|
- try {
|
|
|
- await deviceApi.deletePerson(personId);
|
|
|
- message.success('会友删除成功');
|
|
|
- fetchMembers();
|
|
|
- } catch (error) {
|
|
|
- console.error('删除会友失败', error);
|
|
|
- message.error('删除会友失败,请重试');
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
const handleSubmit = async (values) => {
|
|
|
try {
|
|
|
if (editingMember) {
|
|
|
@@ -129,101 +37,10 @@ const MemberList = () => {
|
|
|
}
|
|
|
};
|
|
|
|
|
|
- const handleDownloadToDevice = async (personId) => {
|
|
|
- try {
|
|
|
- await deviceApi.downloadPersonToDevice(personId);
|
|
|
- message.success('会友信息已成功下发到设备');
|
|
|
- } catch (error) {
|
|
|
- console.error('下发会友信息失败', error);
|
|
|
- message.error(`下发会友信息失败: ${error.message}`);
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- const columns = [
|
|
|
- {
|
|
|
- title: '姓名',
|
|
|
- dataIndex: 'name',
|
|
|
- key: 'name',
|
|
|
- ...getColumnSearchProps('name'),
|
|
|
- },
|
|
|
- {
|
|
|
- title: '性别',
|
|
|
- dataIndex: 'gender',
|
|
|
- key: 'gender',
|
|
|
- render: (gender) => (gender === 1 ? '男' : '女'),
|
|
|
- },
|
|
|
- {
|
|
|
- title: '年龄',
|
|
|
- dataIndex: 'age',
|
|
|
- key: 'age',
|
|
|
- },
|
|
|
- {
|
|
|
- title: '身份证号',
|
|
|
- dataIndex: 'idCard',
|
|
|
- key: 'idCard',
|
|
|
- ...getColumnSearchProps('idCard'),
|
|
|
- },
|
|
|
- {
|
|
|
- title: '人脸照片',
|
|
|
- dataIndex: 'photo',
|
|
|
- key: 'photo',
|
|
|
- render: (photo) => photo ? <Image src={`data:image/jpeg;base64,${photo}`} width={50} /> : '无照片',
|
|
|
- },
|
|
|
- {
|
|
|
- title: '所属小组组长',
|
|
|
- dataIndex: 'groupLeader',
|
|
|
- key: 'groupLeader',
|
|
|
- ...getColumnSearchProps('groupLeader'),
|
|
|
- },
|
|
|
- {
|
|
|
- title: '操作',
|
|
|
- key: 'action',
|
|
|
- render: (_, record) => (
|
|
|
- <Space size="middle">
|
|
|
- <Button onClick={() => handleEdit(record)}>编辑</Button>
|
|
|
- <Button onClick={() => handleDelete(record.personId)} danger>删除</Button>
|
|
|
- <Button
|
|
|
- onClick={() => handleDownloadToDevice(record.personId)}
|
|
|
- icon={<DownloadOutlined />}
|
|
|
- >
|
|
|
- 下发到设备
|
|
|
- </Button>
|
|
|
- </Space>
|
|
|
- ),
|
|
|
- },
|
|
|
- ];
|
|
|
+ // ... 保持其他代码不变
|
|
|
|
|
|
return (
|
|
|
- <div>
|
|
|
- <h2>会友列表</h2>
|
|
|
- <div style={{ marginBottom: 16 }}>
|
|
|
- <Button onClick={fetchMembers} type="primary" style={{ marginRight: 8 }}>
|
|
|
- 刷新列表
|
|
|
- </Button>
|
|
|
- <Button onClick={handleAdd} type="primary" icon={<PlusOutlined />}>
|
|
|
- 添加会友
|
|
|
- </Button>
|
|
|
- </div>
|
|
|
- <ExcelImportExport members={members} onImport={fetchMembers} />
|
|
|
- <Table
|
|
|
- columns={columns}
|
|
|
- dataSource={members}
|
|
|
- rowKey="personId"
|
|
|
- loading={loading}
|
|
|
- />
|
|
|
- <Modal
|
|
|
- title={editingMember ? "编辑会友" : "添加会友"}
|
|
|
- visible={isModalVisible}
|
|
|
- onCancel={() => setIsModalVisible(false)}
|
|
|
- footer={null}
|
|
|
- width={600}
|
|
|
- >
|
|
|
- <MemberForm
|
|
|
- initialValues={editingMember}
|
|
|
- onSubmit={handleSubmit}
|
|
|
- />
|
|
|
- </Modal>
|
|
|
- </div>
|
|
|
+ // ... 保持返回的 JSX 不变
|
|
|
);
|
|
|
};
|
|
|
|