/** 审计日志 action / target_type 中文展示(与后端 AuditLog.action 对齐) */ const ACTION_LABELS: Record = { // 通用 CRUD create: '创建', update: '更新', delete: '删除', login: '登录', logout: '登出', execute: '执行', push: '推送', // 认证 / 会话 login_success: '登录成功', login_locked: '登录锁定', login_ip_blocked: '登录 IP 被拒绝', refresh_invalid_format: '刷新令牌格式无效', refresh_admin_not_found: '刷新令牌用户不存在', refresh_version_mismatch: '刷新令牌版本失效', refresh_token_not_found: '刷新令牌会话不存在', refresh_legacy_format: '旧版刷新令牌已废弃', change_password: '修改密码', setup_totp: '初始化双因素认证', enable_totp: '启用双因素认证', disable_totp: '禁用双因素认证', webssh_token: '签发 WebSSH 令牌', // 服务器 / Agent create_server: '创建服务器', update_server: '更新服务器', delete_server: '删除服务器', import_servers: '导入服务器', generate_agent_key: '生成 Agent 密钥', install_agent: '安装 Agent', uninstall_agent: '卸载 Agent', upgrade_agent: '升级 Agent', reveal_install_cmd: '查看安装命令', batch_install_agent: '批量安装 Agent', batch_upgrade_agent: '批量升级 Agent', batch_uninstall_agent: '批量卸载 Agent', batch_detect_path: '批量检测路径', // 资产 create_platform: '创建平台', update_platform: '更新平台', delete_platform: '删除平台', create_node: '创建节点', update_node: '更新节点', delete_node: '删除节点', // 脚本 / 凭据 / 执行 create_script: '创建脚本', update_script: '更新脚本', delete_script: '删除脚本', create_credential: '创建数据库凭据', update_credential: '更新数据库凭据', delete_credential: '删除数据库凭据', execute_started: '开始执行脚本', execute_command: '执行脚本', stop_execution: '停止脚本执行', mark_stuck: '标记执行卡住', retry_execution: '重试脚本执行', server_auto_stuck: '服务器执行超时卡住', auto_stuck: '执行超时自动标记', script_job_callback: '脚本任务回调', // 终端 / WebSSH create_quick_command: '添加快捷命令', update_quick_command: '更新快捷命令', delete_quick_command: '删除快捷命令', reorder_quick_commands: '调整快捷命令顺序', webssh_connect: 'WebSSH 连接', webssh_disconnect: 'WebSSH 断开', // 系统设置 reveal_api_key: '查看 API 密钥', update_setting: '更新系统设置', create_schedule: '创建推送调度', update_schedule: '更新推送调度', delete_schedule: '删除推送调度', create_preset: '创建密码预设', update_preset: '更新密码预设', delete_preset: '删除密码预设', reveal_preset: '查看密码预设', create_ssh_key_preset: '创建 SSH 密钥预设', update_ssh_key_preset: '更新 SSH 密钥预设', delete_ssh_key_preset: '删除 SSH 密钥预设', reveal_ssh_key_preset: '查看 SSH 密钥预设', reveal_telegram_token: '查看 Telegram Token', parse_subscription: '解析订阅节点', update_ip_allowlist: '更新登录 IP 白名单', toggle_ip_allowlist: '开关登录 IP 白名单', add_manual_ips: '添加白名单 IP', remove_allowlist_ip: '移除白名单 IP', retry_job: '手动重试推送', delete_retry: '删除重试任务', // 同步 / 文件 sync_files: '文件推送', sync_preview: '推送预览', sync_cancel: '取消推送', sync_verify: '推送校验', validate_source_path: '验证源路径', sync_push: '文件推送', file_copy: '复制远程文件', file_move: '移动远程文件', file_delete: '删除远程文件', file_rename: '重命名远程文件', file_mkdir: '新建远程目录', browse_directory: '浏览远程目录', file_diff: '对比远程文件', file_upload: '上传文件到服务器', file_download: '从服务器下载文件', file_read: '读取远程文件', file_write: '写入远程文件', file_permission_change: '修改文件权限', file_compress: '压缩远程文件', file_decompress: '解压远程文件', local_file_delete: '删除本地文件', local_file_rename: '重命名本地文件', local_file_preview: '预览本地文件', upload_zip: '上传并解压 ZIP', diagnose: '服务器诊断', chmod: '修改权限', chown: '修改属主', } const TARGET_LABELS: Record = { server: '服务器', schedule: '调度', script: '脚本', credential: '数据库凭据', db_credential: '数据库凭据', admin: '管理员', setting: '系统设置', quick_command: '快捷命令', retry: '重试任务', sync: '同步', file: '文件', webssh: '终端会话', platform: '平台', node: '节点', script_execution: '脚本执行', preset: '密码预设', ssh_key_preset: 'SSH 密钥预设', } /** 常见英文片段 → 中文(用于未登记 action 的兜底) */ const TOKEN_ZH: Record = { create: '创建', update: '更新', delete: '删除', batch: '批量', reveal: '查看', install: '安装', uninstall: '卸载', upgrade: '升级', import: '导入', export: '导出', generate: '生成', execute: '执行', retry: '重试', stop: '停止', mark: '标记', auto: '自动', stuck: '卡住', server: '服务器', script: '脚本', file: '文件', sync: '同步', push: '推送', quick: '快捷', command: '命令', commands: '命令', preset: '预设', schedule: '调度', setting: '设置', platform: '平台', node: '节点', credential: '凭据', admin: '管理员', login: '登录', logout: '登出', webssh: 'WebSSH', connect: '连接', disconnect: '断开', token: '令牌', permission: '权限', change: '变更', reorder: '排序', local: '本地', remote: '远程', preview: '预览', verify: '验证', validate: '验证', browse: '浏览', directory: '目录', upload: '上传', download: '下载', read: '读取', write: '写入', copy: '复制', move: '移动', rename: '重命名', mkdir: '新建目录', compress: '压缩', decompress: '解压', diagnose: '诊断', parse: '解析', subscription: '订阅', allowlist: '白名单', manual: '手动', ips: 'IP', ip: 'IP', telegram: 'Telegram', agent: 'Agent', job: '任务', execution: '执行', started: '开始', success: '成功', locked: '锁定', blocked: '被拒绝', invalid: '无效', format: '格式', version: '版本', mismatch: '不匹配', not: '未', found: '找到', legacy: '旧版', totp: '双因素认证', password: '密码', key: '密钥', api: 'API', ssh: 'SSH', detect: '检测', path: '路径', cancel: '取消', diff: '对比', zip: 'ZIP', callback: '回调', } function fallbackActionLabel(action: string): string { const parts = action.toLowerCase().split('_').filter(Boolean) if (parts.length === 0) return '—' const zh = parts.map((p) => TOKEN_ZH[p] ?? p) return zh.join('') } export function auditActionLabel(action: string): string { if (!action) return '—' const key = action.trim() if (ACTION_LABELS[key]) return ACTION_LABELS[key] return fallbackActionLabel(key) } export function auditTargetLabel(type: string): string { if (!type) return '—' const key = type.trim() if (TARGET_LABELS[key]) return TARGET_LABELS[key] return fallbackActionLabel(key) } /** 审计页「操作类型」筛选(中文标签 + 英文 value) */ export const auditActionFilterOptions: { label: string; value: string }[] = [ { label: '登录成功', value: 'login_success' }, { label: '登出', value: 'logout' }, { label: '修改密码', value: 'change_password' }, { label: '创建服务器', value: 'create_server' }, { label: '更新服务器', value: 'update_server' }, { label: '删除服务器', value: 'delete_server' }, { label: '文件推送', value: 'sync_files' }, { label: '执行脚本', value: 'execute_command' }, { label: 'WebSSH 连接', value: 'webssh_connect' }, { label: '写入远程文件', value: 'file_write' }, { label: '更新系统设置', value: 'update_setting' }, { label: '手动重试推送', value: 'retry_job' }, ] export function auditSummary(item: { action: string resource_type?: string target_type?: string detail?: string | null }): string { const type = item.resource_type || item.target_type || '' const base = `${auditActionLabel(item.action)} · ${auditTargetLabel(type)}` const detail = (item.detail || '').trim() return detail ? `${base}(${detail})` : base }