Files
tuiche/lib/pages/person/select_city.dart
2025-11-21 10:34:18 +08:00

1222 lines
42 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 'package:ef/ef.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:vbvs_app/common/pojo/city.dart';
import 'package:vbvs_app/common/util/FitTool.dart';
import 'package:vbvs_app/common/util/ListSearchWidget.dart';
import 'package:vbvs_app/component/tool/ClickableContainer.dart';
import 'package:vbvs_app/controller/person/person_controller.dart';
import 'package:vbvs_app/controller/theme_controller/ThemeController.dart';
import 'package:vbvs_app/language/AppLanguage.dart';
import 'package:vbvs_app/pages/common/selectDialog.dart';
CityModelController cityModelController = Get.put(CityModelController());
// 修改这个方法,返回 List<CityModel>
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) {
print('Error loading city data: $e');
return [];
}
}
Future showCitySelectionDialog(
BuildContext context, {
required CityModel selectedCity,
Function? onCityChanged,
String title = "选择城市",
required Future<List<CityModel>> cityDataFuture, // 改为required参数
}) {
ThemeController themeController = Get.find();
final bool isChinese = Get.locale?.languageCode == 'zh' ?? true;
final RxList<String> countries = <String>[].obs;
final RxList<String> provinces = <String>[].obs;
final RxList<String> cities = <String>[].obs;
final RxInt countryIndex = 0.obs;
final RxInt provinceIndex = 0.obs;
final RxInt cityIndex = 0.obs;
cityModelController.searchResults = [];
// 更新城市列表
void updateCities(List<CityModel> cityData) {
try {
if (provinces.isEmpty || countries.isEmpty) return;
final selectedCountry = countries[countryIndex.value];
final selectedProvince = provinces[provinceIndex.value];
// 在层级结构中查找对应的城市
for (var country in cityData) {
if (country.value == selectedCountry) {
for (var province in country.children ?? []) {
if (province.value == selectedProvince) {
// 安全地处理城市列表,过滤掉 null 值并转换为 String
final List<String> cityList = [];
for (var city in province.children ?? []) {
final cityName = city?.value ?? city?.city ?? '';
if (cityName.isNotEmpty) {
cityList.add(cityName);
}
}
cities.value = cityList;
// 设置默认选中城市
if ((selectedCity.value != null &&
cities.contains(selectedCity.value)) ||
(selectedCity.city != null &&
cities.contains(selectedCity.city))) {
cityIndex.value = cities
.indexOf(selectedCity.value ?? selectedCity.city ?? '');
} else {
cityIndex.value = cities.isNotEmpty ? 0 : 0;
}
return;
}
}
}
}
cities.value = [];
cityIndex.value = 0;
} catch (e) {
ef.log("获取城市数据失败:$e");
cities.value = [];
cityIndex.value = 0;
}
}
void updateProvinces(List<CityModel> cityData) {
try {
if (countries.isEmpty) return;
final selectedCountry = countries[countryIndex.value];
// 在层级结构中查找对应的省份
for (var country in cityData) {
if (country.value == selectedCountry) {
// 安全地处理省份列表,过滤掉 null 值并转换为 String
final List<String> provinceList = [];
for (var province in country.children ?? []) {
final provinceName = province?.value ?? province?.province ?? '';
if (provinceName.isNotEmpty) {
provinceList.add(provinceName);
}
}
provinces.value = provinceList;
// 设置默认选中省份
if ((selectedCity.province != null &&
provinces.contains(selectedCity.province)) ||
(selectedCity.value != null &&
provinces.contains(selectedCity.value))) {
provinceIndex.value = provinces
.indexOf(selectedCity.province ?? selectedCity.value ?? '');
} else {
provinceIndex.value = provinces.isNotEmpty ? 0 : 0;
}
updateCities(cityData);
return;
}
}
provinces.value = [];
provinceIndex.value = 0;
cities.value = [];
cityIndex.value = 0;
} catch (e) {
ef.log("获取省份数据失败:$e");
provinces.value = [];
provinceIndex.value = 0;
cities.value = [];
cityIndex.value = 0;
}
}
void initializePickerData(List<CityModel> cityData) {
try {
// 安全地处理国家列表,过滤掉 null 值并转换为 String
final List<String> countryList = [];
for (var country in cityData) {
final countryName = country.value ?? country.country ?? '';
if (countryName.isNotEmpty) {
countryList.add(countryName);
}
}
countries.value = countryList;
// 设置默认选中国家
if ((selectedCity.country != null &&
countries.contains(selectedCity.country)) ||
(selectedCity.value != null &&
countries.contains(selectedCity.value))) {
countryIndex.value =
countries.indexOf(selectedCity.country ?? selectedCity.value ?? '');
} else {
countryIndex.value = countries.isNotEmpty ? 0 : 0;
}
updateProvinces(cityData);
} catch (e) {
ef.log("初始化选择器数据失败:$e");
countries.value = [];
provinces.value = [];
cities.value = [];
countryIndex.value = 0;
provinceIndex.value = 0;
cityIndex.value = 0;
}
}
// 获取选中的完整城市数据
CityModel? getSelectedCityData(List<CityModel> cityData) {
if (countries.isEmpty || provinces.isEmpty || cities.isEmpty) return null;
final selectedCountry = countries[countryIndex.value];
final selectedProvince = provinces[provinceIndex.value];
final selectedCityName = cities[cityIndex.value];
// 在层级结构中查找对应的城市
for (var country in cityData) {
if (country.value == selectedCountry ||
country.country == selectedCountry) {
for (var province in country.children ?? []) {
if (province.value == selectedProvince ||
province.province == selectedProvince) {
for (var city in province.children ?? []) {
if (city.value == selectedCityName ||
city.city == selectedCityName) {
return city;
}
}
}
}
}
}
return null;
}
return showModalBottomSheet(
context: context,
backgroundColor: Colors.transparent,
isScrollControlled: true,
enableDrag: false,
isDismissible: true,
builder: (BuildContext context) {
return Container(
color: Colors.transparent,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
// 半透明遮罩层,点击关闭
Expanded(
child: GestureDetector(
onTap: () => Navigator.of(context).pop(),
child: Container(
color: Colors.black.withOpacity(0.5),
),
),
),
// 弹窗内容
FutureBuilder<List<CityModel>>(
future: cityDataFuture,
builder: (context, snapshot) {
// 数据加载中
if (snapshot.connectionState == ConnectionState.waiting) {
return _buildLoadingBottomSheet(themeController);
}
// 数据加载错误
if (snapshot.hasError || !snapshot.hasData) {
return _buildErrorBottomSheet(themeController, context);
}
final cityData = snapshot.data!;
// 只在第一次初始化数据
if (countries.isEmpty) {
initializePickerData(cityData);
}
return _buildCityPickerContent(
context,
themeController,
isChinese,
title,
cityData,
onCityChanged,
countries: countries,
provinces: provinces,
cities: cities,
countryIndex: countryIndex,
provinceIndex: provinceIndex,
cityIndex: cityIndex,
);
},
),
],
),
);
},
);
}
// 加载中弹窗
Widget _buildLoadingDialog(ThemeController themeController) {
return Stack(
children: [
Positioned(
bottom: 0,
left: 0,
right: 0,
child: Material(
color: Colors.transparent,
child: Dialog(
backgroundColor: themeController.currentColor.sc17,
insetPadding: EdgeInsets.zero,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(0),
),
child: Container(
width: double.infinity,
padding: EdgeInsets.fromLTRB(30.rpx, 40.rpx, 30.rpx, 90.rpx),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
CircularProgressIndicator(
color: themeController.currentColor.sc2,
),
SizedBox(height: 20.rpx),
Text(
"加载中...".tr,
style: TextStyle(
color: themeController.currentColor.sc3,
fontSize: 28.rpx,
),
),
],
),
),
),
),
),
],
);
}
// 错误弹窗
Widget _buildErrorDialog(
ThemeController themeController, BuildContext context) {
return Stack(
children: [
Positioned(
bottom: 0,
left: 0,
right: 0,
child: Material(
color: Colors.transparent,
child: Dialog(
backgroundColor: themeController.currentColor.sc17,
insetPadding: EdgeInsets.zero,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(0),
),
child: Container(
width: double.infinity,
padding: EdgeInsets.fromLTRB(30.rpx, 40.rpx, 30.rpx, 90.rpx),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(
"数据加载失败".tr,
style: TextStyle(
color: themeController.currentColor.sc3,
fontSize: 28.rpx,
),
),
SizedBox(height: 20.rpx),
ClickableContainer(
onTap: () => Navigator.of(context).pop(),
backgroundColor: Colors.transparent,
highlightColor: Colors.transparent,
padding: EdgeInsets.all(0),
child: Container(
padding: EdgeInsets.symmetric(
horizontal: 30.rpx, vertical: 15.rpx),
decoration: BoxDecoration(
color: themeController.currentColor.sc2,
borderRadius: BorderRadius.circular(8.rpx),
),
child: Text(
"关闭".tr,
style: TextStyle(
color: Colors.white,
fontSize: 28.rpx,
),
),
),
),
],
),
),
),
),
),
],
);
}
// 城市选择器弹窗
Widget _buildCityPickerDialog(
BuildContext context,
ThemeController themeController,
bool isChinese,
String title,
List<CityModel> cityData,
Function? onCityChanged, {
required RxList<String> countries,
required RxList<String> provinces,
required RxList<String> cities,
required RxInt countryIndex,
required RxInt provinceIndex,
required RxInt cityIndex,
}) {
// 内部更新方法
void updateCities() {
try {
if (provinces.isEmpty || countries.isEmpty) return;
final selectedCountry = countries[countryIndex.value];
final selectedProvince = provinces[provinceIndex.value];
for (var country in cityData) {
if (country.value == selectedCountry) {
for (var province in country.children ?? []) {
if (province.value == selectedProvince) {
// 安全地处理城市列表
final cityList = (province.children ?? [])
.map((city) => city?.value ?? city?.city ?? '')
.where((cityName) =>
(cityName as String).isNotEmpty) // 明确转换为 String
.toList()
.cast<String>();
cities.value = cityList;
cityIndex.value = cities.isNotEmpty ? 0 : 0;
return;
}
}
}
}
cities.value = [];
cityIndex.value = 0;
} catch (e) {
ef.log("更新城市列表失败:$e");
cities.value = [];
cityIndex.value = 0;
}
}
void updateProvinces() {
try {
if (countries.isEmpty) return;
final selectedCountry = countries[countryIndex.value];
for (var country in cityData) {
if (country.value == selectedCountry) {
// 安全地处理省份列表
final provinceList = (country.children ?? [])
.map((province) => province?.value ?? province?.province ?? '')
.where((provinceName) => provinceName.isNotEmpty)
.toList()
.cast<String>();
provinces.value = provinceList;
provinceIndex.value = provinces.isNotEmpty ? 0 : 0;
// 更新城市
updateCities();
return;
}
}
provinces.value = [];
provinceIndex.value = 0;
cities.value = [];
cityIndex.value = 0;
} catch (e) {
ef.log("更新省份列表失败:$e");
provinces.value = [];
provinceIndex.value = 0;
cities.value = [];
cityIndex.value = 0;
}
}
CityModel? getSelectedCityData() {
try {
if (countries.isEmpty) return null;
final selectedCountry = countries[countryIndex.value];
// 查找匹配的国家
for (var country in cityData) {
final countryName = country.value ?? country.country;
if (countryName == selectedCountry) {
// 情况1: 只有国家一级(没有省份和城市)
if ((country.children == null || country.children!.isEmpty) &&
(country.city != null || country.value != null)) {
return country; // 直接返回国家数据
}
// 情况2: 有省份但没有城市数据
if (provinces.isNotEmpty && provinceIndex.value < provinces.length) {
final selectedProvince = provinces[provinceIndex.value];
for (var province in country.children ?? []) {
final provinceName = province.value ?? province.province;
if (provinceName == selectedProvince) {
// 情况2.1: 省份有城市数据
if (cities.isNotEmpty && cityIndex.value < cities.length) {
final selectedCityName = cities[cityIndex.value];
for (var city in province.children ?? []) {
final cityName = city.value ?? city.city;
if (cityName == selectedCityName) {
return city; // 返回城市数据
}
}
}
// 情况2.2: 省份没有城市数据,但省份本身有信息
if ((province.children == null || province.children!.isEmpty) &&
(province.city != null || province.value != null)) {
return province; // 返回省份数据
}
}
}
}
// 情况3: 有省份但没有选择具体省份,返回国家数据
return country;
}
}
return null;
} catch (e) {
ef.log("获取选中城市数据失败:$e");
return null;
}
}
return Scaffold(
resizeToAvoidBottomInset: false, // 在这里也设置
backgroundColor: Colors.transparent,
body: Stack(
children: [
Positioned(
bottom: 0,
left: 0,
right: 0,
child: Material(
color: Colors.transparent,
child: Dialog(
backgroundColor: themeController.currentColor.sc17,
insetPadding: EdgeInsets.zero,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(0),
),
child: Container(
width: double.infinity,
padding: EdgeInsets.fromLTRB(30.rpx, 10.rpx, 30.rpx, 0.rpx),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
ClickableContainer(
backgroundColor: Colors.transparent,
highlightColor: Colors.transparent,
padding: EdgeInsets.zero,
onTap: () => Navigator.of(context).pop(),
child: Container(
width: 110.rpx,
height: 60.rpx,
alignment: Alignment.center,
child: Text("取消".tr,
style: TextStyle(
fontSize: 30.rpx, color: Colors.white)),
),
),
Text(
title,
style: TextStyle(
fontFamily: 'Readex Pro',
color: themeController.currentColor.sc3,
fontSize: 30.rpx,
),
),
Obx(() {
CityModelController cityModelController = Get.find();
cityModelController.tmp;
ef.log("${cityModelController.tmp.value}");
return ClickableContainer(
backgroundColor: Colors.transparent,
highlightColor: Colors.transparent,
padding: EdgeInsets.zero,
// onTap: () {
// final selectedCityData = getSelectedCityData();
// if (selectedCityData != null) {
// onCityChanged?.call(selectedCityData);
// }
// Navigator.of(context).pop();
// },
onTap: () {
final selectedCityData = getSelectedCityData();
if (selectedCityData != null) {
// 根据ID查找完整的层级数据并补全
final fullCityData = findCompleteCityDataById(
selectedCityData.id, cityData);
if (fullCityData != null) {
// 使用完整的数据
onCityChanged?.call(fullCityData);
} else {
// 如果没有找到完整数据,使用当前选中的数据
onCityChanged?.call(selectedCityData);
}
}
Navigator.of(context).pop();
},
child: Container(
width: 110.rpx,
height: 60.rpx,
alignment: Alignment.center,
child: Text("确定".tr,
style: TextStyle(
fontSize: 30.rpx,
color: themeController.currentColor.sc2,
)),
),
);
}),
],
),
Padding(
padding: EdgeInsetsDirectional.fromSTEB(0, 0.rpx, 0, 0),
child: ListSearchWidget(
keyword: cityModelController.model.keyword,
color: cityModelController.model.color,
hint: "输入国家、省份或城市".tr,
onChange: (d) {
cityModelController.model.keyword = d;
// 实时搜索
cityModelController.searchCities(d);
},
findCallback: () {
// 点击搜索按钮时搜索
cityModelController.searchCities(
cityModelController.model.keyword ?? "");
},
padding: EdgeInsets.fromLTRB(
0.rpx,
30.rpx,
0.rpx,
10.rpx,
),
showResultList: true, // 开启结果列表
searchResults:
cityModelController.searchResults, // 搜索结果
onResultTap: (result) {
// 处理选择结果
final selectedCity =
cityModelController.getCityByDisplayName(result);
if (selectedCity != null) {
final fullCityData = findCompleteCityDataById(
selectedCity.id, cityData);
// 更新选中的城市
PersonController personController = Get.find();
personController.cityModel = fullCityData;
personController.updateAll();
ef.log("选择了城市: ${selectedCity.displayName}");
// 关闭弹窗(如果是在弹窗中使用)
Navigator.of(context).pop();
}
},
),
),
SizedBox(height: 20.rpx),
Stack(
children: [
Positioned.fill(
child: IgnorePointer(
child: Center(
child: Container(
height: 90.rpx,
margin: EdgeInsets.symmetric(horizontal: 0.rpx),
decoration: BoxDecoration(
color: themeController.currentColor.sc2,
borderRadius: BorderRadius.circular(16.rpx),
),
),
),
),
),
Container(
child: Padding(
padding: EdgeInsets.fromLTRB(20.rpx, 0, 20.rpx, 0),
child: Row(
children: [
Expanded(
child: Obx(() {
CityModelController cityModelController =
Get.find();
cityModelController.tmp;
ef.log("${cityModelController.tmp.value}");
return getOnePickers(
context,
countries,
countryIndex,
unit: "",
onChanged: (_) => updateProvinces(),
);
}),
),
Expanded(
child: Obx(() {
CityModelController cityModelController =
Get.find();
cityModelController.tmp;
ef.log("${cityModelController.tmp.value}");
return getOnePickers(
context,
provinces,
provinceIndex,
unit: "",
onChanged: (_) => updateCities(),
);
}),
),
Expanded(
child: Obx(() {
CityModelController cityModelController =
Get.find();
cityModelController.tmp;
ef.log("${cityModelController.tmp.value}");
return getOnePickers(
context,
cities,
cityIndex,
unit: "",
);
}),
),
],
),
),
),
],
),
],
),
),
),
),
),
],
),
);
}
// 根据ID查找完整的城市数据包含国家、省份、城市信息
CityModel? findCompleteCityDataById(int? id, List<CityModel> cityData) {
if (id == null) return null;
try {
// 遍历三级数据结构查找匹配的ID
for (var country in cityData) {
// 检查国家节点是否有ID匹配
if (country.id == id) {
return CityModel(
id: country.id,
value: country.value,
label: country.label,
country: country.value ?? country.country,
province: null,
city: null,
UTC: country.UTC,
children: country.children,
);
}
// 检查省份节点
for (var province in country.children ?? []) {
if (province.id == id) {
return CityModel(
id: province.id,
value: province.value,
label: province.label,
country: country.value ?? country.country,
province: province.value ?? province.province,
city: null,
UTC: province.UTC,
children: province.children,
);
}
// 检查城市节点
for (var city in province.children ?? []) {
if (city.id == id) {
return CityModel(
id: city.id,
value: city.value,
label: city.label,
country: country.value ?? country.country,
province: province.value ?? province.province,
city: city.value ?? city.city,
UTC: city.UTC,
children: city.children,
);
}
}
}
}
return null;
} catch (e) {
ef.log("根据ID查找完整城市数据失败$e");
return null;
}
}
// 城市选择器内容
Widget _buildCityPickerContent(
BuildContext context,
ThemeController themeController,
bool isChinese,
String title,
List<CityModel> cityData,
Function? onCityChanged, {
required RxList<String> countries,
required RxList<String> provinces,
required RxList<String> cities,
required RxInt countryIndex,
required RxInt provinceIndex,
required RxInt cityIndex,
}) {
final bottomInsets = MediaQuery.of(context).viewInsets.bottom;
// 内部更新方法
void updateCities() {
try {
if (provinces.isEmpty || countries.isEmpty) return;
final selectedCountry = countries[countryIndex.value];
final selectedProvince = provinces[provinceIndex.value];
// 查找匹配的国家和省份
final provinceData = cityData
.firstWhere(
(country) => country.value == selectedCountry,
orElse: () => CityModel(),
)
.children
?.firstWhere(
(province) => province.value == selectedProvince,
orElse: () => CityModel(),
);
// 提取城市列表
final cityList = (provinceData?.children ?? [])
.map((city) => city?.value ?? city?.city ?? '')
.where((cityName) => cityName.toString().isNotEmpty)
.toList()
.cast<String>();
cities.value = cityList;
cityIndex.value = cities.isNotEmpty ? 0 : 0;
} catch (e) {
ef.log("更新城市列表失败:$e");
cities.value = [];
cityIndex.value = 0;
}
}
void updateProvinces() {
try {
if (countries.isEmpty) return;
final selectedCountry = countries[countryIndex.value];
for (var country in cityData) {
if (country.value == selectedCountry) {
final List<String> provinceList = [];
for (var province in country.children ?? []) {
final provinceName = province?.value ?? province?.province;
if (provinceName != null && provinceName.isNotEmpty) {
provinceList.add(provinceName);
}
}
provinces.value = provinceList;
provinceIndex.value = provinces.isNotEmpty ? 0 : 0;
updateCities();
return;
}
}
provinces.value = [];
provinceIndex.value = 0;
cities.value = [];
cityIndex.value = 0;
} catch (e) {
ef.log("获取省份数据失败:$e");
provinces.value = [];
provinceIndex.value = 0;
cities.value = [];
cityIndex.value = 0;
}
}
CityModel? getSelectedCityData() {
try {
if (countries.isEmpty) return null;
final selectedCountry = countries[countryIndex.value];
for (var country in cityData) {
final countryName = country.value ?? country.country;
if (countryName == selectedCountry) {
if ((country.children == null || country.children!.isEmpty) &&
(country.city != null || country.value != null)) {
return country;
}
if (provinces.isNotEmpty && provinceIndex.value < provinces.length) {
final selectedProvince = provinces[provinceIndex.value];
for (var province in country.children ?? []) {
final provinceName = province.value ?? province.province;
if (provinceName == selectedProvince) {
if (cities.isNotEmpty && cityIndex.value < cities.length) {
final selectedCityName = cities[cityIndex.value];
for (var city in province.children ?? []) {
final cityName = city.value ?? city.city;
if (cityName == selectedCityName) {
return city;
}
}
}
if ((province.children == null || province.children!.isEmpty) &&
(province.city != null || province.value != null)) {
return province;
}
}
}
}
return country;
}
}
return null;
} catch (e) {
ef.log("获取选中城市数据失败:$e");
return null;
}
}
return Container(
width: double.infinity,
decoration: BoxDecoration(
color: themeController.currentColor.sc17,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20.rpx),
topRight: Radius.circular(20.rpx),
),
),
constraints: BoxConstraints(
maxHeight: MediaQuery.of(context).size.height * 0.65,
),
child: Padding(
padding:
EdgeInsets.fromLTRB(30.rpx, 10.rpx, 30.rpx, bottomInsets + 10.rpx),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
ClickableContainer(
backgroundColor: Colors.transparent,
highlightColor: Colors.transparent,
padding: EdgeInsets.zero,
onTap: () => Navigator.of(context).pop(),
child: Container(
width: 110.rpx,
height: 60.rpx,
alignment: Alignment.center,
child: Text("取消".tr,
style: TextStyle(fontSize: 30.rpx, color: Colors.white)),
),
),
Text(
title,
style: TextStyle(
fontFamily: 'Readex Pro',
color: themeController.currentColor.sc3,
fontSize: 30.rpx,
),
),
Obx(() {
CityModelController cityModelController = Get.find();
cityModelController.tmp;
ef.log("${cityModelController.tmp.value}");
return ClickableContainer(
backgroundColor: Colors.transparent,
highlightColor: Colors.transparent,
padding: EdgeInsets.zero,
onTap: () {
final selectedCityData = getSelectedCityData();
if (selectedCityData != null) {
final fullCityData = findCompleteCityDataById(
selectedCityData.id, cityData);
if (fullCityData != null) {
onCityChanged?.call(fullCityData);
} else {
onCityChanged?.call(selectedCityData);
}
}
Navigator.of(context).pop();
},
child: Container(
width: 110.rpx,
height: 60.rpx,
alignment: Alignment.center,
child: Text("确定".tr,
style: TextStyle(
fontSize: 30.rpx,
color: themeController.currentColor.sc2,
)),
),
);
}),
],
),
Padding(
padding: EdgeInsetsDirectional.fromSTEB(0, 20.rpx, 0, 10.rpx),
child: ListSearchWidget(
keyword: cityModelController.model.keyword,
color: cityModelController.model.color,
hint: "输入国家、省份或城市".tr,
onChange: (d) {
cityModelController.model.keyword = d;
cityModelController.searchCities(d);
},
findCallback: () {
cityModelController
.searchCities(cityModelController.model.keyword ?? "");
},
padding: EdgeInsets.fromLTRB(0.rpx, 0.rpx, 0.rpx, 10.rpx),
showResultList: true,
searchResults: cityModelController.searchResults,
onResultTap: (result) {
final selectedCity =
cityModelController.getCityByDisplayName(result);
if (selectedCity != null) {
final fullCityData =
findCompleteCityDataById(selectedCity.id, cityData);
PersonController personController = Get.find();
personController.cityModel = fullCityData;
personController.updateAll();
Navigator.of(context).pop();
}
},
),
),
// 选择器区域
Expanded(
child: Stack(
children: [
Positioned.fill(
child: IgnorePointer(
child: Center(
child: Container(
height: 90.rpx,
margin: EdgeInsets.symmetric(horizontal: 0.rpx),
decoration: BoxDecoration(
color: themeController.currentColor.sc2,
borderRadius: BorderRadius.circular(16.rpx),
),
),
),
),
),
Container(
height: double.infinity,
child: Padding(
padding: EdgeInsets.fromLTRB(20.rpx, 0, 20.rpx, 0),
child: Row(
children: [
Expanded(
child: Obx(() {
CityModelController cityModelController =
Get.find();
cityModelController.tmp;
ef.log("${cityModelController.tmp.value}");
return getOnePickers(
context,
countries,
countryIndex,
unit: "",
onChanged: (_) => updateProvinces(),
);
}),
),
Expanded(
child: Obx(() {
CityModelController cityModelController =
Get.find();
cityModelController.tmp;
ef.log("${cityModelController.tmp.value}");
return getOnePickers(
context,
provinces,
provinceIndex,
unit: "",
onChanged: (_) => updateCities(),
);
}),
),
Expanded(
child: Obx(() {
CityModelController cityModelController =
Get.find();
cityModelController.tmp;
ef.log("${cityModelController.tmp.value}");
return getOnePickers(
context,
cities,
cityIndex,
unit: "",
);
}),
),
],
),
),
),
],
),
),
],
),
),
);
}
// 加载中 BottomSheet
Widget _buildLoadingBottomSheet(ThemeController themeController) {
return Container(
width: double.infinity,
decoration: BoxDecoration(
color: themeController.currentColor.sc17,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20.rpx),
topRight: Radius.circular(20.rpx),
),
),
padding: EdgeInsets.fromLTRB(30.rpx, 40.rpx, 30.rpx, 90.rpx),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
CircularProgressIndicator(
color: themeController.currentColor.sc2,
),
SizedBox(height: 20.rpx),
Text(
"加载中...".tr,
style: TextStyle(
color: themeController.currentColor.sc3,
fontSize: 28.rpx,
),
),
],
),
);
}
// 错误 BottomSheet
Widget _buildErrorBottomSheet(
ThemeController themeController, BuildContext context) {
return Container(
width: double.infinity,
decoration: BoxDecoration(
color: themeController.currentColor.sc17,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20.rpx),
topRight: Radius.circular(20.rpx),
),
),
padding: EdgeInsets.fromLTRB(30.rpx, 40.rpx, 30.rpx, 90.rpx),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(
"数据加载失败".tr,
style: TextStyle(
color: themeController.currentColor.sc3,
fontSize: 28.rpx,
),
),
SizedBox(height: 20.rpx),
ClickableContainer(
onTap: () => Navigator.of(context).pop(),
backgroundColor: Colors.transparent,
highlightColor: Colors.transparent,
padding: EdgeInsets.all(0),
child: Container(
padding: EdgeInsets.symmetric(horizontal: 30.rpx, vertical: 15.rpx),
decoration: BoxDecoration(
color: themeController.currentColor.sc2,
borderRadius: BorderRadius.circular(8.rpx),
),
child: Text(
"关闭".tr,
style: TextStyle(
color: Colors.white,
fontSize: 28.rpx,
),
),
),
),
],
),
);
}