You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

277 lines
6.6 KiB

import 'package:json_annotation/json_annotation.dart';
part 'channel_app_model.g.dart';
/// 渠道应用信息响应模型
@JsonSerializable()
class ChannelAppResponse {
@JsonKey(name: 'code')
final int code;
@JsonKey(name: 'data')
final ChannelAppData? data;
@JsonKey(name: 'msg')
final String msg;
const ChannelAppResponse({
required this.code,
this.data,
required this.msg,
});
factory ChannelAppResponse.fromJson(Map<String, dynamic> json) =>
_$ChannelAppResponseFromJson(json);
Map<String, dynamic> toJson() => _$ChannelAppResponseToJson(this);
}
/// 渠道应用数据模型
@JsonSerializable()
class ChannelAppData {
@JsonKey(name: 'app')
final AppInfo app;
const ChannelAppData({
required this.app,
});
factory ChannelAppData.fromJson(Map<String, dynamic> json) =>
_$ChannelAppDataFromJson(json);
Map<String, dynamic> toJson() => _$ChannelAppDataToJson(this);
}
/// 应用信息模型
@JsonSerializable()
class AppInfo {
/// 下载地址(可选)
@JsonKey(name: 'address')
final String? address;
/// 渠道标识(支持数字类型转换)
@JsonKey(
name: 'channel',
fromJson: UserChannel.fromJson,
toJson: _channelToJson,
)
final UserChannel channel;
/// 应用描述
@JsonKey(name: 'description')
final String description;
/// 最新版本号
@JsonKey(name: 'version')
final String version;
/// 是否显示游客登录。
///
/// 这是服务端算好的**结论**而非后台开关的原始值:服务端已按本机上报的版本号与
/// 「游客登录生效版本」比对过(见 comm.ChannelApp.ShowTourists),客户端直接照着显隐,
/// 不要再拿 touristsversion 自己比一遍——版本比较各端各写一遍必然出现不一致。
@JsonKey(name: 'tourists')
final bool tourists;
/// 游客登录生效版本;空 = 不限定版本。仅用于排查「为什么这一版看不到入口」,不参与判定。
@JsonKey(name: 'touristsversion')
final String? touristsversion;
/// 是否允许跳过设备绑定
@JsonKey(name: 'allowskipdevicebinding')
final bool allowskipdevicebinding;
/// 支付渠道列表。
///
/// 服务端的 json tag 是全小写的 `paychannels`(见 db.proto 的 DBChannelApp),
/// 这里两种写法都认一下:早先只认大写 `Paychannels`,实际永远解析不到。
@JsonKey(name: 'paychannels', readValue: _readPaychannels)
final String? paychannels;
/// 最低支持版本,低于它必须更新。空 = 后台没配,不参与判定。
@JsonKey(name: 'minversion')
final String? minversion;
/// 强制更新开关,配合 [minversion] 使用。
///
/// **强更判定的唯一依据就是这两个字段**(后台「渠道分发」里配)。
/// 别再拿「主版本号第一位不同」之类的土规则去猜 —— 那和后台配置完全脱节,
/// 运营勾了强更也拦不住人。
@JsonKey(name: 'forceupdate')
final bool forceupdate;
const AppInfo({
this.address,
required this.channel,
required this.description,
required this.version,
this.tourists = false,
this.touristsversion,
this.allowskipdevicebinding = false,
required this.paychannels,
this.minversion,
this.forceupdate = false,
});
factory AppInfo.fromJson(Map<String, dynamic> json) =>
_$AppInfoFromJson(json);
Map<String, dynamic> toJson() => _$AppInfoToJson(this);
}
// 辅助函数:将 UserChannel 转换为 JSON
int _channelToJson(UserChannel channel) => channel.value;
// 兼容历史大写键名的读取器:先按服务端真实的小写键取,取不到再退回大写。
Object? _readPaychannels(Map json, String key) =>
json[key] ?? json['Paychannels'];
/// 版本更新信息模型
class VersionUpdateInfo {
/// 是否有新版本
final bool hasUpdate;
/// 当前版本
final String currentVersion;
/// 最新版本
final String latestVersion;
/// 应用信息
final AppInfo? appInfo;
/// 更新类型
final UpdateType updateType;
const VersionUpdateInfo({
required this.hasUpdate,
required this.currentVersion,
required this.latestVersion,
this.appInfo,
required this.updateType,
});
}
/// 更新类型枚举
enum UpdateType {
/// 无需更新
none,
/// 可选更新
optional,
/// 强制更新
force,
}
/// 应用商店类型枚举
enum AppStoreType {
/// iOS App Store
appStore,
/// Google Play
googlePlay,
/// 华为应用市场
huawei,
/// 小米应用商店
xiaomi,
/// OPPO软件商店
oppo,
/// vivo应用商店
vivo,
/// 荣耀应用市场
honor,
/// 官网下载
official,
/// 未知
unknown,
}
// 用户渠道枚举
enum UserChannel {
UNKNOWN(0), // 未知渠道
CHINA_HUAWEI(1), // 中国-华为
CHINA_XIAOMI(2), // 中国-小米
CHINA_OPPO(3), // 中国-OPPO
CHINA_VIVO(4), // 中国-VIVO
CHINA_HONOR(5), // 中国-荣耀
OFFICIAL(100), // 官方渠道
GLOBAL_APPLE(101), // 全球-苹果
GLOBAL_GOOGLE(102); // 全球-谷歌
const UserChannel(this.value);
final int value;
// 从数字值创建枚举
static UserChannel fromValue(int value) {
return UserChannel.values.firstWhere(
(channel) => channel.value == value,
orElse: () => UserChannel.UNKNOWN,
);
}
// 从字符串名称创建枚举
static UserChannel fromName(String name) {
switch (name.toUpperCase()) {
case 'CHINA_HUAWEI':
return UserChannel.CHINA_HUAWEI;
case 'CHINA_XIAOMI':
return UserChannel.CHINA_XIAOMI;
case 'CHINA_OPPO':
return UserChannel.CHINA_OPPO;
case 'CHINA_VIVO':
return UserChannel.CHINA_VIVO;
case 'CHINA_HONOR':
return UserChannel.CHINA_HONOR;
case 'OFFICIAL':
return UserChannel.OFFICIAL;
case 'GLOBAL_APPLE':
return UserChannel.GLOBAL_APPLE;
case 'GLOBAL_GOOGLE':
return UserChannel.GLOBAL_GOOGLE;
default:
return UserChannel.UNKNOWN;
}
}
// JSON 序列化时返回数字值
int toJson() => value;
// JSON 反序列化时从数字值创建枚举
static UserChannel fromJson(dynamic json) {
if (json is int) {
return fromValue(json);
} else if (json is String) {
final intValue = int.tryParse(json);
if (intValue != null) {
return fromValue(intValue);
}
}
return UserChannel.UNKNOWN;
}
}
/// 平台信息模型
class PlatformInfo {
/// 平台类型
final String platform;
/// 应用商店类型
final AppStoreType storeType;
/// 渠道标识
final UserChannel channel;
const PlatformInfo({
required this.platform,
required this.storeType,
required this.channel,
});
}