/// APP 版本模型。 /// /// 对应后端 /device/orgGroupAppVersion/* 接口的版本实体。 class AppVersion { const AppVersion({ required this.id, required this.orgId, required this.groupId, required this.appName, required this.packageName, required this.versionCode, required this.versionName, required this.apkUrl, required this.status, required this.createTime, }); /// 版本 ID。 final String id; /// 组织 ID。 final String orgId; /// 设备分组 ID。 final String groupId; /// 应用名称。 final String appName; /// 包名。 final String packageName; /// 版本号(整数)。 final int versionCode; /// 版本名。 final String versionName; /// APK 下载地址。 final String apkUrl; /// 状态(0=正常 1=禁用)。 final int status; /// 创建时间。 final DateTime? createTime; factory AppVersion.fromJson(Map json) { return AppVersion( id: json['id']?.toString() ?? '', orgId: json['orgId']?.toString() ?? '', groupId: json['groupId']?.toString() ?? '', appName: json['appName']?.toString() ?? '', // 包名:后端可能返回 packageName / package_name(与既有 AppVersionPage 一致)。 packageName: json['packageName']?.toString() ?? json['package_name']?.toString() ?? '', versionCode: int.tryParse(json['versionCode']?.toString() ?? '0') ?? 0, versionName: json['versionName']?.toString() ?? '', // 下载地址:对齐 Web 端 normalizeAppVersion(downloadUrl/download_url), // 同时兼容移动端既有 AppVersionPage 使用的 apkUrl——后端不同部署字段名不一, // 取首个非空值,避免「立即更新」因 url 为空而失效。 apkUrl: json['apkUrl']?.toString() ?? json['downloadUrl']?.toString() ?? json['download_url']?.toString() ?? '', status: int.tryParse(json['status']?.toString() ?? '0') ?? 0, createTime: _parseDateTime(json['createTime']), ); } /// 兼容 `yyyy-MM-dd HH:mm:ss` 与 ISO 8601 两种时间格式。 static DateTime? _parseDateTime(dynamic value) { if (value == null) return null; final text = value.toString().trim(); if (text.isEmpty) return null; return DateTime.tryParse(text) ?? DateTime.tryParse(text.replaceFirst(' ', 'T')); } Map toJson() { return { 'id': id, 'orgId': orgId, 'groupId': groupId, 'appName': appName, 'packageName': packageName, 'versionCode': versionCode, 'versionName': versionName, 'apkUrl': apkUrl, 'status': status, 'createTime': createTime?.toIso8601String(), }; } }