fix: 全局权限优化 — 7 项问题修复

1. 菜单权限修复:补充 10 个菜单的 permission 字段 + 修复 menu_service
   回退逻辑(admin 直接跳过过滤,非 admin 无关联则不显示)+ 收紧前端过滤
2. 管理员重置密码:新增 POST /users/{id}/reset-password 端点 + 前端按钮
3. 告警处理人姓名:AlertResponse 添加 acknowledged_by_name 字段
4. Tab 权限过滤:PatientDetail 6 个 Tab 按权限过滤 + 状态字段 Tooltip
5. 消息中心 UI:添加 Popconfirm/AuthButton,移除 inline isDark
This commit is contained in:
iven
2026-05-15 19:00:48 +08:00
parent 9319203e09
commit 8763e10d6e
17 changed files with 451 additions and 69 deletions

View File

@@ -14,8 +14,10 @@ import {
DatePicker,
message,
Spin,
Tooltip,
} from 'antd';
import { ArrowLeftOutlined, EditOutlined } from '@ant-design/icons';
import { ArrowLeftOutlined, EditOutlined, InfoCircleOutlined } from '@ant-design/icons';
import { useAuthStore } from '../../stores/auth';
import { patientApi } from '../../api/health/patients';
import { AuthButton } from '../../components/AuthButton';
import { CopilotBadge } from '../../components/Copilot';
@@ -57,6 +59,22 @@ export default function PatientDetail() {
const [editModalOpen, setEditModalOpen] = useState(false);
const [form] = Form.useForm();
const isDark = useThemeMode();
const permissions = useAuthStore((s) => s.permissions);
/** Tab 权限映射:无权限码的 tab 始终可见 */
const TAB_PERMISSIONS: Record<string, string | undefined> = {
info: undefined,
family: 'health.patient.manage',
health: 'health.health-data.list',
followup: 'health.follow-up.list',
points: 'health.points.list',
ai: 'ai.analysis.list',
};
const hasPermission = (code: string | undefined): boolean => {
if (!code) return true;
return permissions.includes(code);
};
// --- 加载患者基本信息 ---
const fetchPatient = useCallback(async () => {
@@ -268,10 +286,24 @@ export default function PatientDetail() {
<Descriptions.Item label="身份证号">
{patient.id_number || '-'}
</Descriptions.Item>
<Descriptions.Item label="状态">
<Descriptions.Item label={
<Space size={4}>
<span></span>
<Tooltip title="active=活跃 | inactive=停诊 | deceased=已故。停诊/已故会触发对应业务事件。">
<InfoCircleOutlined style={{ color: 'var(--ant-color-text-quaternary)', fontSize: 12 }} />
</Tooltip>
</Space>
}>
<StatusTag status={patient.status} />
</Descriptions.Item>
<Descriptions.Item label="认证状态">
<Descriptions.Item label={
<Space size={4}>
<span></span>
<Tooltip title="pending=待认证 | verified=已认证 | rejected=已驳回。已认证会触发 PATIENT_VERIFIED 事件。">
<InfoCircleOutlined style={{ color: 'var(--ant-color-text-quaternary)', fontSize: 12 }} />
</Tooltip>
</Space>
}>
<StatusTag status={patient.verification_status} />
</Descriptions.Item>
<Descriptions.Item label="来源">
@@ -351,7 +383,7 @@ export default function PatientDetail() {
</Space>
) : null,
},
]}
].filter((tab) => hasPermission(TAB_PERMISSIONS[tab.key]))}
/>
</Card>

View File

@@ -173,7 +173,7 @@ export function AlertDetailPanel({
{alert.acknowledged_by && (
<Descriptions.Item label="处理人" span={2}>
<Typography.Text style={{ fontSize: 12 }}>
{alert.acknowledged_by}
{alert.acknowledged_by_name || `${alert.acknowledged_by.slice(0, 8)}...`}
</Typography.Text>
</Descriptions.Item>
)}