/// 宠物档案展示文案的纯函数集合(列表 / 详情 / 表单共用,可单测)。 library; import 'package:patbond_flutter/core/network/api_exception.dart'; import 'package:patbond_flutter/features/pets/pet_models.dart'; String petSpeciesLabel(PetSpecies species) => switch (species) { PetSpecies.dog => '狗狗', PetSpecies.cat => '猫咪', PetSpecies.other => '其他', }; String petSexLabel(PetSex sex) => switch (sex) { PetSex.male => '男孩', PetSex.female => '女孩', PetSex.unknown => '性别未知', }; String petStatusLabel(PetStatus status) => switch (status) { PetStatus.active => '正常', PetStatus.lost => '走失中', PetStatus.deceased => '已离世', PetStatus.archived => '已归档', }; /// 品种展示:目录品种名 > 自定义品种名 > 未知(Pet 响应恰有其一非空, /// 双空为兜底)。 String petBreedLabel(Pet pet) => pet.breedDisplayName ?? pet.customBreedName ?? '品种未知'; /// 年龄:满一岁按「N 岁」、不满一岁按「N 个月」、当月新生「未满月」; /// 生日缺席或晚于今天为「年龄未知」。 String petAgeLabel(DateTime? birthDate, {DateTime? now}) { if (birthDate == null) return '年龄未知'; final today = now ?? DateTime.now(); var months = (today.year - birthDate.year) * 12 + today.month - birthDate.month; if (today.day < birthDate.day) months--; if (months < 0) return '年龄未知'; if (months == 0) return '未满月'; if (months < 12) return '$months 个月'; return '${months ~/ 12} 岁'; } /// 列表卡 / 详情头的元信息行:「柴犬 · 男孩 · 2 岁」。 String petMetaLine(Pet pet, {DateTime? now}) => '${petBreedLabel(pet)} · ${petSexLabel(pet.sex)} · ' '${petAgeLabel(pet.birthDate, now: now)}'; /// 加载失败的用户文案(一迭代三层错误模型:不可归属字段的加载错误 /// 走横幅;服务端原始 message 不上屏)。 String petLoadErrorMessage(ApiException? error) => switch (error) { ApiNetworkException _ => '网络异常,请检查网络后重试', ApiRateLimitException _ => '请求过于频繁,请稍后再试', _ => '加载失败,请稍后重试', }; /// 宠物头像写入失败的文案(T3.5-09)。按契约 v1.4.0 为 /// `PATCH /pets/{petId}` 新增的两格分层: /// /// - 404/40405:asset 不存在 / 非本人 / 已删 / **用途不符**(帖图或用户头像 /// 当宠物头像)→ 引导重新上传,而不是「宠物不存在」(40401 才是那个)。 /// - 422/42203:本人的 `pet_avatar` asset 仍在 uploading/failed → 可重试。 /// - 403/40300:viewer 改头像(入口本已按 myRole 隐藏,此处兜底防越权构造)。 /// - 409/40902:版本冲突 → 由调用方重取档案后重试。 String petAvatarSaveErrorMessage(ApiException? error) => switch (error) { ApiBusinessException(code: ApiCodes.mediaNotFound) => '头像已失效,请重新上传', ApiBusinessException(code: ApiCodes.mediaNotReady) => '头像还没上传完,请稍后重试', ApiBusinessException(code: ApiCodes.petAccessDenied) => '你没有修改该宠物头像的权限', ApiBusinessException(code: ApiCodes.versionConflict) => '档案已被更新,请重新操作', ApiNetworkException _ => '网络异常,请检查网络后重试', ApiRateLimitException _ => '请求过于频繁,请稍后再试', _ => '头像保存失败,请稍后重试', };