feat(q1): 前端类型安全治理完成 — any 83→40, P0 全部 done
- types/monitor.ts: 新增 6 个运行时记录类型(AlertEventRecord/AlertRuleRecord/ AgentHostRecord/CronJobRecord/CertExpiryRecord/ApprovalWorkflowStepRecord) - types/common.ts: 新增 OptionItem 通用下拉类型 - 组件级 any 清理 43 处: - AlertEventsTab/AlertRulesTab/AlertChannelDialog/alertShared (19处) - AuditOperationsTab normalizeLog + 筛选器 (8处) - CronJobManager 任务列表/编辑/操作 (6处) - AgentMonitor 主机列表/命令执行 (5处) - DashboardRecent 5 张卡片组件 (5处) - AlertManager 状态类型对齐 (联动修复) - Dashboard.tsx 调用端类型对齐 (联动修复) - AlertChannel 接口新增 test_status 字段 - ESLint any: 83→40 (<50 目标达成) - tsc -b / tsc --noEmit: 零错误 - npm run build: ✓ built in 17.11s - 9/9 核心 API 回归通过
This commit is contained in:
1 parent
0535f30c87
commit
bb2b91ebe0
15 files changed
+259
-93
No files matched your search
@@ -22,22 +22,22 @@ import {
|
||||
import { auditApi } from '@/api';
|
||||
import { useAuditLogs } from '@/hooks/api';
|
||||
import { useConfirm } from '@/components/ui/confirm-dialog';
|
||||
import type { OperationLog } from '@/types';
|
||||
import type { OperationLog, OptionItem } from '@/types';
|
||||
|
||||
// Normalize backend log to frontend type
|
||||
function normalizeLog(raw: any): OperationLog {
|
||||
function normalizeLog(raw: Record<string, unknown>): OperationLog {
|
||||
return {
|
||||
id: String(raw.id ?? ''),
|
||||
userId: String(raw.user_id ?? raw.userId ?? ''),
|
||||
username: raw.username ?? '',
|
||||
module: raw.module ?? raw.resource ?? '',
|
||||
action: raw.action ?? '',
|
||||
resource: raw.resource ?? '',
|
||||
ip: raw.ip ?? '',
|
||||
userAgent: raw.user_agent ?? raw.userAgent ?? '',
|
||||
username: String(raw.username ?? ''),
|
||||
module: String(raw.module ?? raw.resource ?? ''),
|
||||
action: String(raw.action ?? ''),
|
||||
resource: String(raw.resource ?? ''),
|
||||
ip: String(raw.ip ?? ''),
|
||||
userAgent: String(raw.user_agent ?? raw.userAgent ?? ''),
|
||||
result: raw.result === 'failure' ? 'failure' : 'success',
|
||||
message: raw.message ?? raw.detail ?? '',
|
||||
createdAt: raw.createdAt ?? raw.created_at ?? '',
|
||||
message: String(raw.message ?? raw.detail ?? ''),
|
||||
createdAt: String(raw.createdAt ?? raw.created_at ?? ''),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -70,8 +70,8 @@ export function AuditOperationsTab() {
|
||||
() => (auditData?.list || []).map((raw) => normalizeLog(raw)),
|
||||
[auditData],
|
||||
);
|
||||
const [modules, setModules] = useState<string[]>([]);
|
||||
const [actions, setActions] = useState<string[]>([]);
|
||||
const [modules, setModules] = useState<OptionItem[]>([]);
|
||||
const [actions, setActions] = useState<OptionItem[]>([]);
|
||||
|
||||
// Detail modal
|
||||
const [detailLog, setDetailLog] = useState<OperationLog | null>(null);
|
||||
@@ -84,8 +84,10 @@ export function AuditOperationsTab() {
|
||||
const fetchOptions = useCallback(async () => {
|
||||
try {
|
||||
const [modRes, actRes] = await Promise.all([auditApi.getModules(), auditApi.getActions()]);
|
||||
setModules((modRes as any)?.list ?? (modRes as any) ?? []);
|
||||
setActions((actRes as any)?.list ?? (actRes as any) ?? []);
|
||||
const modData = modRes as { list?: OptionItem[] } | OptionItem[];
|
||||
const actData = actRes as { list?: OptionItem[] } | OptionItem[];
|
||||
setModules(Array.isArray(modData) ? modData : (modData?.list ?? []));
|
||||
setActions(Array.isArray(actData) ? actData : (actData?.list ?? []));
|
||||
} catch {
|
||||
/* noop */
|
||||
}
|
||||
@@ -120,7 +122,7 @@ export function AuditOperationsTab() {
|
||||
|
||||
const handleExport = async () => {
|
||||
try {
|
||||
const params: any = {};
|
||||
const params: Record<string, string> = {};
|
||||
if (moduleFilter) params.module = moduleFilter;
|
||||
if (actionFilter) params.action = actionFilter;
|
||||
await auditApi.exportLogs(params);
|
||||
@@ -167,7 +169,7 @@ export function AuditOperationsTab() {
|
||||
className="h-9 px-3 text-sm rounded-md bg-slate-800/50 border border-slate-700 text-slate-300 focus:outline-none focus:border-blue-500"
|
||||
>
|
||||
<option value="">全部模块</option>
|
||||
{modules.map((m: any) => (
|
||||
{modules.map((m) => (
|
||||
<option key={m.value} value={m.value}>
|
||||
{m.label}
|
||||
</option>
|
||||
@@ -181,7 +183,7 @@ export function AuditOperationsTab() {
|
||||
className="h-9 px-3 text-sm rounded-md bg-slate-800/50 border border-slate-700 text-slate-300 focus:outline-none focus:border-blue-500"
|
||||
>
|
||||
<option value="">全部操作</option>
|
||||
{actions.map((a: any) => (
|
||||
{actions.map((a) => (
|
||||
<option key={a.value} value={a.value}>
|
||||
{a.label}
|
||||
</option>
|
||||
|
||||
Reference in new issue
Block a user