282 lines
7.9 KiB
Dart
282 lines
7.9 KiB
Dart
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);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 根据显示名称获取对应的 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;
|
||
}
|
||
}
|