/// 绑定关系条目,对应服务端 `ClientController#bindingView`。 /// /// 与 Android 端 `network/model/BindingItem` 字段保持一致。 class BindingItem { final String? bindingId; /// 被控端设备唯一标识,即连接时的目标设备 ID。 final String deviceUid; final String? userId; /// OWNER / MEMBER。 final String? role; final String? alias; /// ACTIVE / REVOKED。 final String? status; /// 被控端当前是否在线(信令网络中存在活跃会话)。 final bool online; const BindingItem({ this.bindingId, required this.deviceUid, this.userId, this.role, this.alias, this.status, this.online = false, }); factory BindingItem.fromJson(Map json) => BindingItem( bindingId: json['bindingId'] as String?, deviceUid: (json['deviceUid'] ?? json['deviceId'] ?? '').toString(), userId: json['userId'] as String?, role: json['role'] as String?, alias: json['alias'] as String?, status: json['status'] as String?, online: json['online'] == true, ); /// 将服务端返回的列表字段解析为绑定条目集合。 static List listFrom(dynamic raw) { if (raw is! List) return const []; return raw .whereType() .map((e) => BindingItem.fromJson(Map.from(e))) .where((e) => e.deviceUid.isNotEmpty) .toList(); } /// 是否为设备所有者。 bool get isOwner => role == 'OWNER'; /// 列表展示名称:有别名时优先展示别名,否则展示设备 ID。 String get name => (alias != null && alias!.trim().isNotEmpty) ? alias! : deviceUid; /// 下拉展示文案:有别名时附带设备 ID。 String displayName() { if (alias != null && alias!.trim().isNotEmpty) { return '$alias ($deviceUid)'; } return deviceUid; } BindingItem copyWith({bool? online}) => BindingItem( bindingId: bindingId, deviceUid: deviceUid, userId: userId, role: role, alias: alias, status: status, online: online ?? this.online, ); }