Skip to content

Data Models

Seeker32 edited this page Aug 11, 2026 · 3 revisions

数据模型

所有模型 JSON 序列化 camelCase,时间戳为 Unix 毫秒。前后端类型一一对应(Rust serde ↔ TS types)。

AppErrorInfo(跨边界错误 payload)

{ code: string; detail: string | null }

稳定英文错误码(AppError::code()):SshConnectionError / AuthenticationError / SessionNotFound / InvalidHostConfig / StorageError / IoError / SshProtocolError / SecureStoreError / CredentialNotFound / SftpChannelError / SftpPermissionDenied / SftpPathNotFound / SftpTransferError。detail 为语言无关诊断,前端按当前语言本地化展示。

HostConfig(主机配置,不含明文凭据)

{
  id: string;                 // UUID
  name: string;               // 展示名
  host: string;               // 主机地址
  port: number;               // SSH 端口
  username: string;
  authType: 'Password' | 'PrivateKey';
  passwordRef: string | null;       // 安全存储引用键,非明文
  privateKeyPath: string | null;
  passphraseRef: string | null;     // 私钥口令引用键
  remark: string | null;
  group: string;              // 分组名,空串 = "未分组"
}

SaveHostRequest 为前端提交形态:额外含 password / passphrase 明文字段,仅存在于请求中,后端落盘前清除。host.rs 模型带 #[serde(alias = "auth_type")] 等 legacy 兼容。

SessionInfo(真实会话,与 UI 标签解耦)

{
  sessionId: string;
  hostId: string;
  host: string;
  port: number;
  username: string;
  status: 'Connecting' | 'Connected' | 'AuthFailed' | 'Disconnected' | 'Timeout' | 'Error';
  createdAt: number;          // 毫秒时间戳
}

MonitorSnapshot(监控快照,单 payload 全量)

{
  sessionId: string;
  timestamp: number;          // 采集时间
  cpuUsage: number;           // 0.0 ~ 100.0(/proc/stat 增量计算)
  memoryUsage: number;        // 0.0 ~ 100.0
  diskUsage: number;          // 0.0 ~ 100.0(根分区)
  diskAvailableBytes: number; // 根分区剩余容量
  diskTotalBytes: number;     // 根分区总容量
  network: NetworkSnapshot;
}

NetworkSnapshot / NetworkInterface(网络采集)

interface NetworkSnapshot {
  available: boolean;         // /proc/net/dev 是否成功读取并解析(区分失败与无候选接口)
  interfaces: NetworkInterface[]; // 不含 lo 的候选网卡,按远端返回顺序
}
interface NetworkInterface {
  name: string;               // 网卡接口名
  receiveBytesPerSecond: number | null;   // 下行速率;首次采样或计数异常时为 null
  transmitBytesPerSecond: number | null;  // 上行速率;首次采样或计数异常时为 null
}

TaskInfo(长任务,monitor 使用)

{
  taskId: string;
  taskType: string;
  sessionId: string | null;
  status: 'Pending' | 'Running' | 'Done' | 'Failed';
  createdAt: number;
  error?: AppErrorInfo | null; // Failed 时存在
}

TransferTask(SFTP 传输任务)

{
  taskId: string;             // UUID v4
  sessionId: string;
  transferType: 'Upload' | 'Download';
  remotePath: string;
  localPath: string;
  fileName: string;           // 从路径提取,用于 UI
  totalBytes: number;
  transferredBytes: number;
  speedBps: number;
  status: 'Pending' | 'Running' | 'Done' | 'Failed' | 'Cancelled';
  error: AppErrorInfo | null; // Failed 时记录结构化原因;Cancelled 为 null
  createdAt: number;
}

RemoteEntry(SFTP 目录条目)

{
  name: string;               // 不含路径
  path: string;               // 完整绝对路径
  isDir: boolean;
  size: number;               // bytes,目录为 0
  modifiedAt: number;         // 毫秒时间戳
  permissions: string;        // 如 "rwxr-xr-x"
}

事件 Payload

API.md:SessionStatusEvent、ConnectionProgressEvent、TerminalDataEvent、SftpProgressEvent、SftpTaskStatusEvent、TaskStatusEvent(错误字段均为 error: AppErrorInfo | null)。

序列化约定

  • Rust 侧统一 #[serde(rename_all = "camelCase")]
  • 旧字段兼容:#[serde(alias = "snake_case")](host.rs 的 auth_type / password_ref / private_key_path / passphrase_ref)
  • 校验(proptest 属性测试):毫秒时间戳必须 >= 1_000_000_000_000(2001-09-09);百分比字段 0.0~100.0;端口 1~65535

Clone this wiki locally