// routing_profile.dart — 可配置分流档案(GET/POST /v1/me/routing)。 // // 对齐后端契约(server/internal/httpapi 分流端点): // {mode, builtin:{china_direct,lan_direct,private_via_tunnel}, rules:[...], final}。 // 手写 fromJson/toJson(项目无 json_serializable,仿 lib/models/me.dart)。 /// 分流模式。 /// 'rule' = 按规则(内置 + 自定义) | 'global' = 全局代理 | 'direct' = 全局直连。 typedef RoutingMode = String; /// 规则匹配类型。 const kRuleTypes = [ 'domain', 'domain_suffix', 'domain_keyword', 'ip_cidr', 'geoip', 'geosite', ]; /// 规则命中动作。 const kRuleActions = ['direct', 'proxy', 'reject']; /// 内置分流开关(与自定义规则叠加,内置项在服务端渲染时排在自定义规则前/后由服务端决定)。 class Builtin { const Builtin({ this.chinaDirect = true, this.lanDirect = true, this.privateViaTunnel = true, }); final bool chinaDirect; final bool lanDirect; final bool privateViaTunnel; factory Builtin.fromJson(Map m) => Builtin( chinaDirect: m['china_direct'] as bool? ?? true, lanDirect: m['lan_direct'] as bool? ?? true, privateViaTunnel: m['private_via_tunnel'] as bool? ?? true, ); Map toJson() => { 'china_direct': chinaDirect, 'lan_direct': lanDirect, 'private_via_tunnel': privateViaTunnel, }; Builtin copyWith({ bool? chinaDirect, bool? lanDirect, bool? privateViaTunnel, }) => Builtin( chinaDirect: chinaDirect ?? this.chinaDirect, lanDirect: lanDirect ?? this.lanDirect, privateViaTunnel: privateViaTunnel ?? this.privateViaTunnel, ); } /// 单条自定义分流规则。 /// /// **enabled 语义**(计划裁决):构造默认 `true`;[toJson] 恒输出 `enabled` 字段 /// (服务端不修正缺省值,契约靠客户端保证);[fromJson] 缺失时容错默认 `true`。 class RoutingRule { const RoutingRule({ required this.type, required this.value, required this.action, this.note, this.enabled = true, }); /// domain | domain_suffix | domain_keyword | ip_cidr | geoip | geosite final String type; final String value; /// direct | proxy | reject final String action; final String? note; final bool enabled; factory RoutingRule.fromJson(Map m) => RoutingRule( type: m['type'] as String? ?? '', value: m['value'] as String? ?? '', action: m['action'] as String? ?? 'proxy', note: m['note'] as String?, enabled: m['enabled'] as bool? ?? true, ); Map toJson() => { 'type': type, 'value': value, 'action': action, if (note != null) 'note': note, 'enabled': enabled, }; RoutingRule copyWith({ String? type, String? value, String? action, String? note, bool? enabled, }) => RoutingRule( type: type ?? this.type, value: value ?? this.value, action: action ?? this.action, note: note ?? this.note, enabled: enabled ?? this.enabled, ); } /// 分流档案(账户级,单份)。 class RoutingProfile { const RoutingProfile({ this.mode = 'rule', this.builtin = const Builtin(), this.rules = const [], this.finalAction = 'proxy', }); final RoutingMode mode; final Builtin builtin; final List rules; /// 兜底动作(JSON key 为保留字 `final`,Dart 侧改名)。'proxy' | 'direct'。 final String finalAction; factory RoutingProfile.fromJson(Map m) => RoutingProfile( mode: m['mode'] as String? ?? 'rule', builtin: m['builtin'] != null ? Builtin.fromJson(m['builtin'] as Map) : const Builtin(), rules: ((m['rules'] as List?) ?? const []) .map((e) => RoutingRule.fromJson(e as Map)) .toList(), finalAction: m['final'] as String? ?? 'proxy', ); Map toJson() => { 'mode': mode, 'builtin': builtin.toJson(), 'rules': rules.map((r) => r.toJson()).toList(), 'final': finalAction, }; RoutingProfile copyWith({ RoutingMode? mode, Builtin? builtin, List? rules, String? finalAction, }) => RoutingProfile( mode: mode ?? this.mode, builtin: builtin ?? this.builtin, rules: rules ?? this.rules, finalAction: finalAction ?? this.finalAction, ); }