MemberList.tsx 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. import React, { useState, useEffect } from 'react';
  2. import { Table, Button, Input } from 'antd';
  3. import { PlusOutlined, EditOutlined, DeleteOutlined, DownloadOutlined } from '@ant-design/icons';
  4. import MemberForm from './MemberForm';
  5. interface Member {
  6. id: number;
  7. name: string;
  8. gender: string;
  9. age: number;
  10. birthDate: string;
  11. contact: string;
  12. occupation: string;
  13. servicePosition: string;
  14. isBaptized: boolean;
  15. baptismDate?: string;
  16. notes?: string;
  17. }
  18. const MemberList: React.FC = () => {
  19. const [members, setMembers] = useState<Member[]>([]);
  20. const [isModalVisible, setIsModalVisible] = useState(false);
  21. const [editingMember, setEditingMember] = useState<Member | null>(null);
  22. const [searchTerm, setSearchTerm] = useState('');
  23. useEffect(() => {
  24. // 这里应该从API获取会员数据
  25. // 暂时使用模拟数据
  26. const mockMembers: Member[] = [
  27. {
  28. id: 1,
  29. name: '张三',
  30. gender: '男',
  31. age: 30,
  32. birthDate: '1994-01-01',
  33. contact: '13800138000',
  34. occupation: '工程师',
  35. servicePosition: '主日学老师',
  36. isBaptized: true,
  37. baptismDate: '2020-05-01',
  38. notes: '热心服侍'
  39. },
  40. // ... 更多模拟数据
  41. ];
  42. setMembers(mockMembers);
  43. }, []);
  44. const columns = [
  45. {
  46. title: '姓名',
  47. dataIndex: 'name',
  48. key: 'name',
  49. },
  50. {
  51. title: '性别',
  52. dataIndex: 'gender',
  53. key: 'gender',
  54. },
  55. {
  56. title: '年龄',
  57. dataIndex: 'age',
  58. key: 'age',
  59. },
  60. {
  61. title: '联系方式',
  62. dataIndex: 'contact',
  63. key: 'contact',
  64. },
  65. {
  66. title: '操作',
  67. key: 'action',
  68. render: (text: string, record: Member) => (
  69. <span>
  70. <Button icon={<EditOutlined />} onClick={() => handleEdit(record)}>编辑</Button>
  71. <Button icon={<DeleteOutlined />} onClick={() => handleDelete(record.id)}>删除</Button>
  72. </span>
  73. ),
  74. },
  75. ];
  76. const handleAdd = () => {
  77. setEditingMember(null);
  78. setIsModalVisible(true);
  79. };
  80. const handleEdit = (member: Member) => {
  81. setEditingMember(member);
  82. setIsModalVisible(true);
  83. };
  84. const handleDelete = (id: number) => {
  85. setMembers(members.filter(member => member.id !== id));
  86. };
  87. const handleSave = (member: Member) => {
  88. if (editingMember) {
  89. setMembers(members.map(m => m.id === member.id ? member : m));
  90. } else {
  91. setMembers([...members, { ...member, id: members.length + 1 }]);
  92. }
  93. setIsModalVisible(false);
  94. };
  95. const handleSearch = (value: string) => {
  96. setSearchTerm(value);
  97. };
  98. const filteredMembers = members.filter(member =>
  99. member.name.toLowerCase().includes(searchTerm.toLowerCase()) ||
  100. member.contact.includes(searchTerm)
  101. );
  102. return (
  103. <div>
  104. <div style={{ marginBottom: 16 }}>
  105. <Button icon={<PlusOutlined />} onClick={handleAdd}>添加会员</Button>
  106. <Button icon={<DownloadOutlined />}>导出Excel</Button>
  107. <Input.Search
  108. placeholder="搜索姓名或联系方式"
  109. onSearch={handleSearch}
  110. style={{ width: 200, float: 'right' }}
  111. />
  112. </div>
  113. <Table
  114. columns={columns}
  115. dataSource={filteredMembers}
  116. rowKey="id"
  117. pagination={{
  118. total: filteredMembers.length,
  119. showTotal: (total) => `共 ${total} 条记录`,
  120. }}
  121. />
  122. <MemberForm
  123. visible={isModalVisible}
  124. onCancel={() => setIsModalVisible(false)}
  125. onSave={handleSave}
  126. member={editingMember}
  127. />
  128. </div>
  129. );
  130. };
  131. export default MemberList;