Files
tuiche/lib/common/pojo/city.dart
2025-12-01 15:41:34 +08:00

385 lines
11 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import 'dart:convert';
import 'dart:math';
import 'package:ef/base/getx/getx.dart';
import 'package:ef/ef.dart';
import 'package:flutter/services.dart';
import 'package:json_annotation/json_annotation.dart';
import 'package:vbvs_app/controller/setting/language/language_controller.dart';
import 'package:vbvs_app/language/AppLanguage.dart';
part 'city.g.dart';
@JsonSerializable()
class CityModel {
int? id; // 城市id
String? value; // 显示值(国家/省份/城市名称)
String? label; // 标签通常与value相同
String? country; // 国家名称
String? province; // 省份名称
String? city; // 城市名称
String? UTC; // 时区
List<CityModel>? children;
@JsonKey(ignore: true)
String? keyword = "";
@JsonKey(ignore: true)
Color? color = Color(0xFFFFFFFF);
CityModel({
this.id,
this.value,
this.label,
this.country,
this.province,
this.city,
this.UTC,
this.children,
});
// 从JSON反序列化时的异常处理
factory CityModel.fromJson(Map<String, dynamic> json) {
try {
return _$CityModelFromJson(json);
} catch (e) {
print('Error parsing CityModel: $e');
return CityModel(); // 返回空的CityModel
}
}
// 序列化为JSON时的异常处理
Map<String, dynamic> toJson() => _$CityModelToJson(this);
// 获取显示名称(根据层级显示)
String get displayName {
if (city != null && city!.isNotEmpty) {
// 三级:国家-省份-城市
return '${country ?? ''}-${province ?? ''}-${city ?? value ?? ''}';
} else if (province != null && province!.isNotEmpty) {
// 二级:国家-省份
return '${country ?? ''}-${province ?? value ?? ''}';
} else {
// 一级:国家
return country ?? value ?? '';
}
}
}
class CityModelController extends GetControllerEx<CityModel> {
List<CityModel> cityList = [];
LanguageController languageController = Get.find();
RxInt tmp = 1.obs;
RxBool isLoading = false.obs;
List<String>? searchResults = []; // 新增:搜索结果列表
CityModelController() {
attr = GetModel(CityModel()).obs;
}
// 加载城市数据并赋值给cityList
Future<void> loadAndSetCityData() async {
try {
isLoading.value = true;
ef.log("开始加载城市数据...");
final data = await _loadCityData();
cityList = data;
ef.log("城市数据加载完成,共${cityList.length}个国家");
if (cityList.isNotEmpty) {
// 打印前几个国家用于调试
for (var i = 0; i < min(3, cityList.length); i++) {
final country = cityList[i];
ef.log(
"国家: ${country.value}, 省份数量: ${country.children?.length ?? 0}");
}
}
update();
} catch (e) {
ef.log("加载城市数据失败:$e");
} finally {
isLoading.value = false;
}
}
// 内部加载方法
Future<List<CityModel>> _loadCityData() async {
try {
// 获取当前语言代码
String currentLanguageCode = AppLanguage().getCurrentLanguageCode();
// 根据当前语言代码构建文件名
final String fileName = 'assets/city/city_$currentLanguageCode.json';
// 读取对应语言的JSON文件
final String jsonString = await rootBundle.loadString(fileName);
// 解析JSON数据并转换为 CityModel 列表
final List<dynamic> jsonList = jsonDecode(jsonString);
// 将 Map 转换为 CityModel
return jsonList.map((json) => CityModel.fromJson(json)).toList();
} catch (e) {
ef.log("_loadCityData 失败:$e");
return [];
}
}
// 根据ID查找城市支持国家、省份、城市所有层级
CityModel? findCityById(String id) {
if (cityList.isEmpty) {
ef.log("cityList为空无法查找城市请先调用 loadAndSetCityData()");
return null;
}
final int? targetId = int.tryParse(id);
if (targetId == null) {
ef.log("ID格式错误$id");
return null;
}
ef.log("开始查找ID为 $targetId 的城市数据...");
// 遍历三级结构
for (var country in cityList) {
// 检查国家
if (country.id == targetId) {
ef.log("找到匹配的国家: ${country.value}");
return CityModel(
id: country.id,
value: country.value,
label: country.label,
country: country.value,
province: null,
city: null,
UTC: country.UTC,
);
}
// 检查省份
for (var province in country.children ?? []) {
if (province.id == targetId) {
ef.log("找到匹配的省份: ${province.value}, 国家: ${country.value}");
return CityModel(
id: province.id,
value: province.value,
label: province.label,
country: country.value,
province: province.value,
city: null,
UTC: province.UTC,
);
}
// 检查城市
for (var city in province.children ?? []) {
if (city.id == targetId) {
ef.log(
"找到匹配的城市: ${city.value}, 省份: ${province.value}, 国家: ${country.value}");
return CityModel(
id: city.id,
value: city.value,
label: city.label,
country: country.value,
province: province.value,
city: city.value,
UTC: city.UTC,
);
}
}
}
}
ef.log("未找到ID为 $targetId 的城市数据");
return null;
}
// 根据名称查找城市
CityModel? findCityByName(
String countryName, String provinceName, String cityName) {
if (cityList.isEmpty) {
ef.log("cityList为空无法查找城市");
return null;
}
for (var country in cityList) {
if (country.value == countryName) {
for (var province in country.children ?? []) {
if (province.value == provinceName) {
for (var city in province.children ?? []) {
if (city.value == cityName) {
return city;
}
}
}
}
}
}
return null;
}
// 检查是否已加载数据
bool get isDataLoaded => cityList.isNotEmpty;
// void searchCities(String keyword) {
// model.keyword = keyword;
// searchResults?.clear();
// if (keyword.isEmpty) {
// return;
// }
// final keywordLower = keyword.toLowerCase();
// // 遍历所有城市数据
// for (var country in cityList) {
// final countryName = country.value ?? country.country ?? '';
// for (var province in country.children ?? []) {
// final provinceName = province.value ?? province.province ?? '';
// for (var city in province.children ?? []) {
// final cityName = city.value ?? city.city ?? '';
// final displayName = '$countryName-$provinceName-$cityName';
// // 模糊匹配
// if (countryName.toLowerCase().contains(keywordLower) ||
// provinceName.toLowerCase().contains(keywordLower) ||
// cityName.toLowerCase().contains(keywordLower) ||
// displayName.toLowerCase().contains(keywordLower)) {
// searchResults?.add(displayName);
// }
// }
// }
// }
// }
void searchCities(String keyword) {
model.keyword = keyword;
searchResults?.clear();
if (keyword.isEmpty) {
return;
}
final keywordLower = keyword.toLowerCase();
for (var country in cityList) {
final countryName = country.value ?? country.country ?? '';
// 如果该国家没有 children一级结构
if (country.children == null || country.children!.isEmpty) {
final name = countryName;
if (name.toLowerCase().contains(keywordLower)) {
searchResults?.add(name);
}
continue;
}
// 二层循环:省份或城市
for (var province in country.children!) {
final provinceName = province.value ?? province.province ?? '';
final level2Name = '$countryName-$provinceName';
// 省本身是否匹配(适用于 国家→省 二级结构)
if (province.children == null || province.children!.isEmpty) {
if (countryName.toLowerCase().contains(keywordLower) ||
provinceName.toLowerCase().contains(keywordLower) ||
level2Name.toLowerCase().contains(keywordLower)) {
searchResults?.add(level2Name);
}
continue;
}
// 有第三级城市 → 遍历城市
for (var city in province.children!) {
final cityName = city.value ?? city.city ?? '';
final level3Name = '$countryName-$provinceName-$cityName';
if (countryName.toLowerCase().contains(keywordLower) ||
provinceName.toLowerCase().contains(keywordLower) ||
cityName.toLowerCase().contains(keywordLower) ||
level3Name.toLowerCase().contains(keywordLower)) {
searchResults?.add(level3Name);
}
}
}
}
}
// 根据显示名称获取对应的 CityModel
// CityModel? getCityByDisplayName(String displayName) {
// final parts = displayName.split('-');
// if (parts.length != 3) return null;
// final countryName = parts[0];
// final provinceName = parts[1];
// final cityName = parts[2];
// for (var country in cityList) {
// if ((country.value ?? country.country ?? '') == countryName) {
// for (var province in country.children ?? []) {
// if ((province.value ?? province.province ?? '') == provinceName) {
// for (var city in province.children ?? []) {
// if ((city.value ?? city.city ?? '') == cityName) {
// return city;
// }
// }
// }
// }
// }
// }
// return null;
// }
CityModel? getCityByDisplayName(String displayName) {
final parts = displayName.split('-');
if (parts.isEmpty) return null;
final countryName = parts[0];
final provinceName = parts.length >= 2 ? parts[1] : null;
final cityName = parts.length >= 3 ? parts[2] : null;
for (var country in cityList) {
final cName = country.value ?? country.country ?? '';
if (cName != countryName) continue;
// 一级结构:直接 return 国家
if (provinceName == null) {
return country;
}
// 如果没有 children就不可能有省或市
if (country.children == null || country.children!.isEmpty) {
return null;
}
// 二级匹配:省或城市
for (var province in country.children!) {
final pName = province.value ?? province.province ?? '';
if (pName != provinceName) continue;
// 二级结构:国家-省
if (cityName == null) {
return province;
}
// 有城市才继续
if (province.children == null || province.children!.isEmpty) {
return null;
}
// 三级结构:国家-省-市
for (var city in province.children!) {
final ciName = city.value ?? city.city ?? '';
if (ciName == cityName) {
return city;
}
}
}
}
return null;
}
}