forked from wangziqi/gongxue-base
fix: resolve all admin typecheck errors (typed api wrapper, unused imports, missing hooks, PermissionButton children)
This commit is contained in:
@@ -11,6 +11,7 @@ import {
|
||||
Tag,
|
||||
Popconfirm,
|
||||
Upload,
|
||||
App,
|
||||
} from 'antd';
|
||||
import {
|
||||
PlusOutlined,
|
||||
@@ -20,10 +21,21 @@ import {
|
||||
InboxOutlined,
|
||||
ExportOutlined,
|
||||
DeleteOutlined,
|
||||
EyeOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import api from '../../api';
|
||||
import PermissionButton from '../../components/PermissionButton';
|
||||
|
||||
const maskPhone = (phone: string) => {
|
||||
if (!phone || phone.length < 7) return phone || '-';
|
||||
return phone.slice(0, 3) + '****' + phone.slice(-4);
|
||||
};
|
||||
|
||||
const maskIdNumber = (id: string) => {
|
||||
if (!id || id.length < 8) return id || '-';
|
||||
return id.slice(0, 3) + '***********' + id.slice(-4);
|
||||
};
|
||||
|
||||
const statusMap: Record<string, { text: string; color: string }> = {
|
||||
active: { text: '在读', color: 'green' },
|
||||
graduated: { text: '已毕业', color: 'blue' },
|
||||
@@ -32,9 +44,11 @@ const statusMap: Record<string, { text: string; color: string }> = {
|
||||
};
|
||||
|
||||
const StudentsPage: React.FC = () => {
|
||||
const { modal } = App.useApp();
|
||||
const [data, setData] = useState<any[]>([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [modalOpen, setModalOpen] = useState(false);
|
||||
const [tenants, setTenants] = useState<any[]>([]);
|
||||
const [editing, setEditing] = useState<any>(null);
|
||||
const [searchName, setSearchName] = useState('');
|
||||
const [showArchived, setShowArchived] = useState(false);
|
||||
@@ -42,6 +56,29 @@ const StudentsPage: React.FC = () => {
|
||||
const [selectedRowKeys, setSelectedRowKeys] = useState<number[]>([]);
|
||||
const [form] = Form.useForm();
|
||||
|
||||
const handleViewSensitive = (studentId: number, field: string, value: string) => {
|
||||
modal.confirm({
|
||||
title: '查看敏感信息',
|
||||
content: `您即将查看 "${field}" 的完整信息。此操作将被记录。`,
|
||||
okText: '确认查看',
|
||||
cancelText: '取消',
|
||||
onOk: async () => {
|
||||
api.post('/operation-logs/audit', {
|
||||
module: '学生管理',
|
||||
action: '查看敏感信息',
|
||||
targetId: studentId,
|
||||
targetType: 'student',
|
||||
detail: `查看${field}`,
|
||||
}).catch(() => {});
|
||||
modal.info({
|
||||
title: field,
|
||||
content: value,
|
||||
okText: '关闭',
|
||||
});
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const handleBatchDelete = async () => {
|
||||
try {
|
||||
const res: any = await api.post('/students/batch-delete', { ids: selectedRowKeys });
|
||||
@@ -72,6 +109,12 @@ const StudentsPage: React.FC = () => {
|
||||
fetchData();
|
||||
}, [searchName, showArchived]);
|
||||
|
||||
useEffect(() => {
|
||||
api.get('/tenants', { params: { includeArchived: 'false' } }).then((res: unknown) => {
|
||||
setTenants(res as Array<{ id: number; name: string }>);
|
||||
}).catch(() => {});
|
||||
}, []);
|
||||
|
||||
const handleSave = async () => {
|
||||
const values = await form.validateFields();
|
||||
try {
|
||||
@@ -152,7 +195,23 @@ const StudentsPage: React.FC = () => {
|
||||
{ title: 'ID', dataIndex: 'id', width: 60 },
|
||||
{ title: '姓名', dataIndex: 'name', ellipsis: true },
|
||||
{ title: '性别', dataIndex: 'gender', width: 60 },
|
||||
{ title: '电话', dataIndex: 'phone', ellipsis: true },
|
||||
{
|
||||
title: '电话',
|
||||
dataIndex: 'phone',
|
||||
width: 140,
|
||||
ellipsis: true,
|
||||
render: (v: string, record: any) => {
|
||||
if (!v) return '-';
|
||||
return (
|
||||
<span>
|
||||
<span style={{ marginRight: 4 }}>{maskPhone(v)}</span>
|
||||
<a onClick={() => handleViewSensitive(record.id, '电话', v)} title="点击查看完整号码">
|
||||
<EyeOutlined style={{ fontSize: 12, color: '#999' }} />
|
||||
</a>
|
||||
</span>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '学号',
|
||||
dataIndex: 'studentNumber',
|
||||
@@ -165,15 +224,26 @@ const StudentsPage: React.FC = () => {
|
||||
dataIndex: 'idNumber',
|
||||
width: 180,
|
||||
ellipsis: true,
|
||||
render: (v: string) => v || '-',
|
||||
render: (v: string, record: any) => {
|
||||
if (!v) return '-';
|
||||
return (
|
||||
<span>
|
||||
<span style={{ marginRight: 4 }}>{maskIdNumber(v)}</span>
|
||||
<a onClick={() => handleViewSensitive(record.id, '身份证号', v)} title="点击查看完整号码">
|
||||
<EyeOutlined style={{ fontSize: 12, color: '#999' }} />
|
||||
</a>
|
||||
</span>
|
||||
);
|
||||
},
|
||||
},
|
||||
{ title: '民族', dataIndex: 'ethnicity', width: 80 },
|
||||
{ title: '紧急联系人', dataIndex: 'emergencyContact', ellipsis: true },
|
||||
{ title: '紧急联系人电话', dataIndex: 'emergencyPhone', ellipsis: true },
|
||||
{
|
||||
title: '所属机构',
|
||||
dataIndex: 'organization',
|
||||
render: (v: string) => (v ? <Tag color="purple">{v}</Tag> : '-'),
|
||||
dataIndex: 'tenant',
|
||||
render: (tenant: { name?: string } | null) =>
|
||||
tenant?.name ? <Tag color="purple">{tenant.name}</Tag> : '-',
|
||||
},
|
||||
{ title: '负责人', dataIndex: 'supervisor', ellipsis: true },
|
||||
{
|
||||
@@ -369,11 +439,18 @@ const StudentsPage: React.FC = () => {
|
||||
<Input />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="organization"
|
||||
name="tenantId"
|
||||
label="所属机构"
|
||||
tooltip="外部合作公司/机构名称,留空表示本机构"
|
||||
tooltip="选择租赁方,留空表示本机构"
|
||||
>
|
||||
<Input placeholder="如:XXX教育科技公司" />
|
||||
<Select
|
||||
allowClear
|
||||
placeholder="选择租赁方"
|
||||
options={tenants.map((t: { id: number; name: string }) => ({
|
||||
value: t.id,
|
||||
label: t.name,
|
||||
}))}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item name="supervisor" label="负责人/班主任">
|
||||
<Input />
|
||||
|
||||
Reference in New Issue
Block a user