parent
83bbef7ceb
commit
b04a3fded2
@ -0,0 +1,28 @@
|
|||||||
|
import 'package:hive/hive.dart';
|
||||||
|
import 'package:json_annotation/json_annotation.dart';
|
||||||
|
|
||||||
|
part 'china_region_model.g.dart';
|
||||||
|
|
||||||
|
@JsonSerializable()
|
||||||
|
@HiveType(typeId: 3)
|
||||||
|
class ChinaRegionModel {
|
||||||
|
@HiveField(0)
|
||||||
|
final int id;
|
||||||
|
@HiveField(1)
|
||||||
|
final String name;
|
||||||
|
@HiveField(2)
|
||||||
|
final List<ChinaRegionModel> cityList;
|
||||||
|
|
||||||
|
factory ChinaRegionModel.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$ChinaRegionModelFromJson(json);
|
||||||
|
|
||||||
|
const ChinaRegionModel({
|
||||||
|
required this.id,
|
||||||
|
required this.name,
|
||||||
|
required this.cityList,
|
||||||
|
});
|
||||||
|
|
||||||
|
static ChinaRegionModel empty(int parentId) {
|
||||||
|
return ChinaRegionModel(id: 0, name: '', cityList: []);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,60 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'china_region_model.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// TypeAdapterGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
class ChinaRegionModelAdapter extends TypeAdapter<ChinaRegionModel> {
|
||||||
|
@override
|
||||||
|
final int typeId = 3;
|
||||||
|
|
||||||
|
@override
|
||||||
|
ChinaRegionModel read(BinaryReader reader) {
|
||||||
|
final numOfFields = reader.readByte();
|
||||||
|
final fields = <int, dynamic>{
|
||||||
|
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
|
||||||
|
};
|
||||||
|
return ChinaRegionModel(
|
||||||
|
id: fields[0] as int,
|
||||||
|
name: fields[1] as String,
|
||||||
|
cityList: (fields[2] as List).cast<ChinaRegionModel>(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void write(BinaryWriter writer, ChinaRegionModel obj) {
|
||||||
|
writer
|
||||||
|
..writeByte(3)
|
||||||
|
..writeByte(0)
|
||||||
|
..write(obj.id)
|
||||||
|
..writeByte(1)
|
||||||
|
..write(obj.name)
|
||||||
|
..writeByte(2)
|
||||||
|
..write(obj.cityList);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => typeId.hashCode;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) =>
|
||||||
|
identical(this, other) ||
|
||||||
|
other is ChinaRegionModelAdapter &&
|
||||||
|
runtimeType == other.runtimeType &&
|
||||||
|
typeId == other.typeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// JsonSerializableGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
ChinaRegionModel _$ChinaRegionModelFromJson(Map<String, dynamic> json) =>
|
||||||
|
ChinaRegionModel(
|
||||||
|
id: json['id'] as int,
|
||||||
|
name: json['name'] as String,
|
||||||
|
cityList: (json['cityList'] as List<dynamic>)
|
||||||
|
.map((e) => ChinaRegionModel.fromJson(e as Map<String, dynamic>))
|
||||||
|
.toList(),
|
||||||
|
);
|
@ -0,0 +1,20 @@
|
|||||||
|
import 'package:json_annotation/json_annotation.dart';
|
||||||
|
|
||||||
|
part 'community_model.g.dart';
|
||||||
|
|
||||||
|
@JsonSerializable()
|
||||||
|
class CommunityModel {
|
||||||
|
final int id;
|
||||||
|
final String name;
|
||||||
|
final String address;
|
||||||
|
final String addressDetails;
|
||||||
|
factory CommunityModel.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$CommunityModelFromJson(json);
|
||||||
|
|
||||||
|
const CommunityModel({
|
||||||
|
required this.id,
|
||||||
|
required this.name,
|
||||||
|
required this.address,
|
||||||
|
required this.addressDetails,
|
||||||
|
});
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'community_model.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// JsonSerializableGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
CommunityModel _$CommunityModelFromJson(Map<String, dynamic> json) =>
|
||||||
|
CommunityModel(
|
||||||
|
id: json['id'] as int,
|
||||||
|
name: json['name'] as String,
|
||||||
|
address: json['address'] as String,
|
||||||
|
addressDetails: json['addressDetails'] as String,
|
||||||
|
);
|
@ -0,0 +1,22 @@
|
|||||||
|
import 'package:aku_new_community/models/login/community_model.dart';
|
||||||
|
import 'package:aku_new_community/models/login/picked_city_model.dart';
|
||||||
|
import 'package:hive/hive.dart';
|
||||||
|
import 'package:json_annotation/json_annotation.dart';
|
||||||
|
|
||||||
|
part 'history_login_model.g.dart';
|
||||||
|
|
||||||
|
@JsonSerializable()
|
||||||
|
@HiveType(typeId: 4)
|
||||||
|
class HistoryLoginModel {
|
||||||
|
@HiveField(0)
|
||||||
|
final PickedCityModel cityModel;
|
||||||
|
@HiveField(1)
|
||||||
|
final CommunityModel communityModel;
|
||||||
|
factory HistoryLoginModel.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$HistoryLoginModelFromJson(json);
|
||||||
|
|
||||||
|
const HistoryLoginModel({
|
||||||
|
required this.cityModel,
|
||||||
|
required this.communityModel,
|
||||||
|
});
|
||||||
|
}
|
@ -0,0 +1,56 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'history_login_model.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// TypeAdapterGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
class HistoryLoginModelAdapter extends TypeAdapter<HistoryLoginModel> {
|
||||||
|
@override
|
||||||
|
final int typeId = 4;
|
||||||
|
|
||||||
|
@override
|
||||||
|
HistoryLoginModel read(BinaryReader reader) {
|
||||||
|
final numOfFields = reader.readByte();
|
||||||
|
final fields = <int, dynamic>{
|
||||||
|
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
|
||||||
|
};
|
||||||
|
return HistoryLoginModel(
|
||||||
|
cityModel: fields[0] as PickedCityModel,
|
||||||
|
communityModel: fields[1] as CommunityModel,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void write(BinaryWriter writer, HistoryLoginModel obj) {
|
||||||
|
writer
|
||||||
|
..writeByte(2)
|
||||||
|
..writeByte(0)
|
||||||
|
..write(obj.cityModel)
|
||||||
|
..writeByte(1)
|
||||||
|
..write(obj.communityModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => typeId.hashCode;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) =>
|
||||||
|
identical(this, other) ||
|
||||||
|
other is HistoryLoginModelAdapter &&
|
||||||
|
runtimeType == other.runtimeType &&
|
||||||
|
typeId == other.typeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// JsonSerializableGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
HistoryLoginModel _$HistoryLoginModelFromJson(Map<String, dynamic> json) =>
|
||||||
|
HistoryLoginModel(
|
||||||
|
cityModel:
|
||||||
|
PickedCityModel.fromJson(json['cityModel'] as Map<String, dynamic>),
|
||||||
|
communityModel: CommunityModel.fromJson(
|
||||||
|
json['communityModel'] as Map<String, dynamic>),
|
||||||
|
);
|
@ -0,0 +1,42 @@
|
|||||||
|
import 'package:aku_new_community/utils/hive_store.dart';
|
||||||
|
import 'package:json_annotation/json_annotation.dart';
|
||||||
|
|
||||||
|
import 'china_region_model.dart';
|
||||||
|
|
||||||
|
part 'picked_city_model.g.dart';
|
||||||
|
|
||||||
|
@JsonSerializable()
|
||||||
|
class PickedCityModel {
|
||||||
|
final ChinaRegionModel province;
|
||||||
|
final ChinaRegionModel city;
|
||||||
|
final ChinaRegionModel district;
|
||||||
|
factory PickedCityModel.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$PickedCityModelFromJson(json);
|
||||||
|
|
||||||
|
const PickedCityModel({
|
||||||
|
required this.province,
|
||||||
|
required this.city,
|
||||||
|
required this.district,
|
||||||
|
});
|
||||||
|
factory PickedCityModel.fromId(
|
||||||
|
{required int provinceId, required int cityId, required int distrctId}) {
|
||||||
|
var provinces =
|
||||||
|
HiveStore.chinaRegionBox!.values.cast<ChinaRegionModel>().toList();
|
||||||
|
final _province =
|
||||||
|
provinces.firstWhere((element) => element.id == provinceId);
|
||||||
|
final _city =
|
||||||
|
_province.cityList.firstWhere((element) => element.id == cityId);
|
||||||
|
final _district =
|
||||||
|
_city.cityList.firstWhere((element) => element.id == distrctId);
|
||||||
|
|
||||||
|
return PickedCityModel(
|
||||||
|
province: _province,
|
||||||
|
city: _city,
|
||||||
|
district: _district,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
String get address => province.name + city.name + district.name;
|
||||||
|
|
||||||
|
int get id => district.id;
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'picked_city_model.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// JsonSerializableGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
PickedCityModel _$PickedCityModelFromJson(Map<String, dynamic> json) =>
|
||||||
|
PickedCityModel(
|
||||||
|
province:
|
||||||
|
ChinaRegionModel.fromJson(json['province'] as Map<String, dynamic>),
|
||||||
|
city: ChinaRegionModel.fromJson(json['city'] as Map<String, dynamic>),
|
||||||
|
district:
|
||||||
|
ChinaRegionModel.fromJson(json['district'] as Map<String, dynamic>),
|
||||||
|
);
|
@ -0,0 +1,101 @@
|
|||||||
|
import 'package:aku_new_community/base/base_style.dart';
|
||||||
|
import 'package:aku_new_community/pages/sign/login/select_community.dart';
|
||||||
|
import 'package:aku_new_community/widget/bee_scaffold.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
import 'package:velocity_x/velocity_x.dart';
|
||||||
|
|
||||||
|
class LoginPage extends StatefulWidget {
|
||||||
|
const LoginPage({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_LoginPageState createState() => _LoginPageState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _LoginPageState extends State<LoginPage> {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return BeeScaffold(
|
||||||
|
title: '',
|
||||||
|
bgColor: Colors.white,
|
||||||
|
bodyColor: Colors.white,
|
||||||
|
body: SafeArea(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
44.w.heightBox,
|
||||||
|
'登录解锁更多功能'.text.size(36.sp).color(ktextPrimary).bold.make(),
|
||||||
|
144.w.heightBox,
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
Get.to(() => SelectCommunity());
|
||||||
|
},
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
'请先选择小区'.text.size(32.sp).color(Color(0xFF5096F1)).make()
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
80.w.heightBox,
|
||||||
|
'${'1547***93018'}'
|
||||||
|
.text
|
||||||
|
.size(36.sp)
|
||||||
|
.color(ktextPrimary)
|
||||||
|
.bold
|
||||||
|
.make(),
|
||||||
|
40.w.heightBox,
|
||||||
|
MaterialButton(
|
||||||
|
onPressed: () {},
|
||||||
|
elevation: 0,
|
||||||
|
height: 100.w,
|
||||||
|
minWidth: 686.w,
|
||||||
|
color: kPrimaryColor,
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(60.w)),
|
||||||
|
child: '本机号码一键登录'.text.size(32.sp).black.bold.make(),
|
||||||
|
),
|
||||||
|
24.w.heightBox,
|
||||||
|
InkWell(
|
||||||
|
onTap: () {},
|
||||||
|
child: Text(
|
||||||
|
'其他登录方式',
|
||||||
|
style: TextStyle(
|
||||||
|
color: Color(0xFF5096F1),
|
||||||
|
fontSize: 28.sp,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Spacer(),
|
||||||
|
RichText(
|
||||||
|
text: TextSpan(
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 24.sp,
|
||||||
|
color: ktextSubColor,
|
||||||
|
),
|
||||||
|
text: '注册/登记即代表同意',
|
||||||
|
children: [
|
||||||
|
WidgetSpan(
|
||||||
|
child: InkWell(
|
||||||
|
onTap: () {
|
||||||
|
//TODO:跳转隐私政策
|
||||||
|
},
|
||||||
|
child: '《小蜜蜂隐私政策及用户协议》'
|
||||||
|
.text
|
||||||
|
.size(24.sp)
|
||||||
|
.color(Color(0xFF5096F1))
|
||||||
|
.make(),
|
||||||
|
)),
|
||||||
|
])),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,148 @@
|
|||||||
|
import 'package:aku_new_community/models/login/community_model.dart';
|
||||||
|
import 'package:aku_new_community/models/login/picked_city_model.dart';
|
||||||
|
import 'package:aku_new_community/widget/bee_scaffold.dart';
|
||||||
|
import 'package:aku_new_community/widget/picker/bee_city_picker.dart';
|
||||||
|
import 'package:aku_new_community/widget/picker/bee_community_picker.dart';
|
||||||
|
import 'package:bot_toast/bot_toast.dart';
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||||
|
import 'package:velocity_x/velocity_x.dart';
|
||||||
|
|
||||||
|
class SelectCommunity extends StatefulWidget {
|
||||||
|
const SelectCommunity({
|
||||||
|
Key? key,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_SelectCommunityState createState() => _SelectCommunityState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _SelectCommunityState extends State<SelectCommunity> {
|
||||||
|
PickedCityModel? _model;
|
||||||
|
CommunityModel? _community;
|
||||||
|
|
||||||
|
String get cityName {
|
||||||
|
if (_model == null) {
|
||||||
|
return '请选择省、市、县/区';
|
||||||
|
} else {
|
||||||
|
return _model!.province.name + _model!.city.name + _model!.district.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String get communityName {
|
||||||
|
if (_community == null) {
|
||||||
|
return '请选择小区';
|
||||||
|
} else {
|
||||||
|
return _community!.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return BeeScaffold(
|
||||||
|
title: '选择登录小区',
|
||||||
|
body: ListView(
|
||||||
|
children: [
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () async {
|
||||||
|
_model = await BeeCityPicker.pick(context);
|
||||||
|
setState(() {});
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
color: Colors.white,
|
||||||
|
width: double.infinity,
|
||||||
|
height: 88.w,
|
||||||
|
padding: EdgeInsets.symmetric(vertical: 24.w, horizontal: 32.w),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
'选择城市'.text.size(28.sp).black.make(),
|
||||||
|
Spacer(),
|
||||||
|
'${cityName}'.text.black.make(),
|
||||||
|
32.w.widthBox,
|
||||||
|
Icon(
|
||||||
|
CupertinoIcons.right_chevron,
|
||||||
|
size: 20.w,
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () async {
|
||||||
|
var cancel = BotToast.showLoading();
|
||||||
|
List<CommunityModel> _communities = [];
|
||||||
|
// var base = await NetUtil().get(API.sarsApi.login.allCommunity);
|
||||||
|
// if (base.status ?? false) {
|
||||||
|
// _communities = (base.data as List)
|
||||||
|
// .map((e) => CommunityModel.fromJson(e))
|
||||||
|
// .toList();
|
||||||
|
// }
|
||||||
|
cancel();
|
||||||
|
_communities = [
|
||||||
|
CommunityModel(
|
||||||
|
id: 0,
|
||||||
|
name: '111',
|
||||||
|
address: 'address',
|
||||||
|
addressDetails: 'addressDetails'),
|
||||||
|
CommunityModel(
|
||||||
|
id: 0,
|
||||||
|
name: '2222',
|
||||||
|
address: 'address',
|
||||||
|
addressDetails: 'addressDetails'),
|
||||||
|
CommunityModel(
|
||||||
|
id: 0,
|
||||||
|
name: '3333',
|
||||||
|
address: 'address',
|
||||||
|
addressDetails: 'addressDetails'),
|
||||||
|
CommunityModel(
|
||||||
|
id: 0,
|
||||||
|
name: '444',
|
||||||
|
address: 'address',
|
||||||
|
addressDetails: 'addressDetails'),
|
||||||
|
CommunityModel(
|
||||||
|
id: 0,
|
||||||
|
name: '5555',
|
||||||
|
address: 'address',
|
||||||
|
addressDetails: 'addressDetails')
|
||||||
|
];
|
||||||
|
_community = await BeeCommunityPicker.pick(context, _communities);
|
||||||
|
setState(() {});
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
color: Colors.white,
|
||||||
|
width: double.infinity,
|
||||||
|
height: 88.w,
|
||||||
|
padding: EdgeInsets.symmetric(vertical: 24.w, horizontal: 32.w),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
'选择小区'.text.size(28.sp).black.make(),
|
||||||
|
Spacer(),
|
||||||
|
'${communityName}'.text.black.make(),
|
||||||
|
32.w.widthBox,
|
||||||
|
Icon(
|
||||||
|
CupertinoIcons.right_chevron,
|
||||||
|
size: 20.w,
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
width: double.infinity,
|
||||||
|
color: Colors.white,
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 32.w, vertical: 24.w),
|
||||||
|
child: Column(
|
||||||
|
children: [],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,165 @@
|
|||||||
|
import 'package:aku_new_community/base/base_style.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||||
|
|
||||||
|
///TextFiled
|
||||||
|
class BeeSearchTextField extends StatefulWidget implements PreferredSizeWidget {
|
||||||
|
BeeSearchTextField({
|
||||||
|
Key? key,
|
||||||
|
this.controller,
|
||||||
|
this.hintText,
|
||||||
|
this.onChanged,
|
||||||
|
this.focusNode,
|
||||||
|
this.onSubmitted,
|
||||||
|
this.margin,
|
||||||
|
this.onPressed,
|
||||||
|
this.height,
|
||||||
|
}) : button = false,
|
||||||
|
super(key: key);
|
||||||
|
|
||||||
|
///
|
||||||
|
BeeSearchTextField.button({
|
||||||
|
Key? key,
|
||||||
|
this.controller,
|
||||||
|
this.hintText,
|
||||||
|
this.onChanged,
|
||||||
|
this.focusNode,
|
||||||
|
this.onSubmitted,
|
||||||
|
this.margin,
|
||||||
|
this.onPressed,
|
||||||
|
this.height,
|
||||||
|
}) : button = true,
|
||||||
|
super(key: key);
|
||||||
|
|
||||||
|
///渲染成按钮
|
||||||
|
final bool button;
|
||||||
|
|
||||||
|
///控制器
|
||||||
|
final TextEditingController? controller;
|
||||||
|
|
||||||
|
///hint Text
|
||||||
|
final String? hintText;
|
||||||
|
|
||||||
|
///文字变化回调
|
||||||
|
final ValueChanged<String>? onChanged;
|
||||||
|
|
||||||
|
///完成输入回调
|
||||||
|
final ValueChanged<String>? onSubmitted;
|
||||||
|
|
||||||
|
///焦点
|
||||||
|
final FocusNode? focusNode;
|
||||||
|
|
||||||
|
///margin
|
||||||
|
final EdgeInsets? margin;
|
||||||
|
|
||||||
|
final VoidCallback? onPressed;
|
||||||
|
|
||||||
|
///高度
|
||||||
|
final double? height;
|
||||||
|
|
||||||
|
@override
|
||||||
|
_BeeSearchTextFieldState createState() => _BeeSearchTextFieldState();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Size get preferredSize => Size.fromHeight(this.height ?? 42.w);
|
||||||
|
}
|
||||||
|
|
||||||
|
class _BeeSearchTextFieldState extends State<BeeSearchTextField> {
|
||||||
|
get _border => OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(21.w),
|
||||||
|
borderSide: BorderSide(
|
||||||
|
color: Color(0xFF979797),
|
||||||
|
width: 1.w,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
_buildButton() {
|
||||||
|
return Padding(
|
||||||
|
padding: widget.margin ??
|
||||||
|
EdgeInsets.symmetric(
|
||||||
|
horizontal: 15.w,
|
||||||
|
vertical: 3.w,
|
||||||
|
),
|
||||||
|
child: MaterialButton(
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
|
color: Color(0xFFF8F8F8),
|
||||||
|
elevation: 0,
|
||||||
|
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(21.w),
|
||||||
|
side: BorderSide(
|
||||||
|
color: Color(0xFF979797),
|
||||||
|
width: 1.w,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.only(left: 26.w, right: 16.w),
|
||||||
|
child: Icon(
|
||||||
|
Icons.search,
|
||||||
|
size: 32.w,
|
||||||
|
color: Colors.black,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
widget.hintText ?? '',
|
||||||
|
style: TextStyle(
|
||||||
|
color: ktextSubColor,
|
||||||
|
fontSize: 28.sp,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
onPressed: widget.onPressed,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
if (widget.button) return _buildButton();
|
||||||
|
return Container(
|
||||||
|
height: 72.w,
|
||||||
|
padding: widget.margin ??
|
||||||
|
EdgeInsets.symmetric(
|
||||||
|
horizontal: 30.w,
|
||||||
|
vertical: 6.w,
|
||||||
|
),
|
||||||
|
child: TextField(
|
||||||
|
controller: widget.controller,
|
||||||
|
onChanged: widget.onChanged,
|
||||||
|
onSubmitted: widget.onSubmitted,
|
||||||
|
onTap: widget.onPressed,
|
||||||
|
focusNode: widget.focusNode,
|
||||||
|
cursorColor: kPrimaryColor,
|
||||||
|
textInputAction: TextInputAction.search,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
fillColor: Color(0xFFF8F8F8),
|
||||||
|
filled: true,
|
||||||
|
hintText: widget.hintText,
|
||||||
|
hintStyle: TextStyle(
|
||||||
|
color: ktextSubColor,
|
||||||
|
fontSize: 28.sp,
|
||||||
|
),
|
||||||
|
border: _border,
|
||||||
|
enabledBorder: _border,
|
||||||
|
focusedBorder: _border,
|
||||||
|
focusedErrorBorder: _border,
|
||||||
|
prefixIcon: Padding(
|
||||||
|
padding: EdgeInsets.only(left: 26.w, right: 16.w),
|
||||||
|
child: Icon(
|
||||||
|
Icons.search,
|
||||||
|
size: 32.w,
|
||||||
|
color: Colors.black,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
prefixIconConstraints: BoxConstraints(minWidth: 0, minHeight: 0),
|
||||||
|
contentPadding: EdgeInsets.zero,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,159 @@
|
|||||||
|
import 'package:aku_new_community/models/login/china_region_model.dart';
|
||||||
|
import 'package:aku_new_community/models/login/picked_city_model.dart';
|
||||||
|
import 'package:aku_new_community/utils/hive_store.dart';
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||||
|
|
||||||
|
import 'bee_picker_box.dart';
|
||||||
|
|
||||||
|
class BeeCityPicker extends StatefulWidget {
|
||||||
|
static Future<PickedCityModel?> pick(BuildContext context) async {
|
||||||
|
return await showModalBottomSheet(
|
||||||
|
context: context,
|
||||||
|
builder: (context) {
|
||||||
|
return BeeCityPicker();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
BeeCityPicker({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_BeeCityPickerState createState() => _BeeCityPickerState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _BeeCityPickerState extends State<BeeCityPicker> {
|
||||||
|
List<ChinaRegionModel> get provinces =>
|
||||||
|
HiveStore.chinaRegionBox!.values.cast<ChinaRegionModel>().toList();
|
||||||
|
|
||||||
|
late int _pickedProvinceIndex;
|
||||||
|
late int _pickedCityIndex;
|
||||||
|
late int _pickedDistrictIndex;
|
||||||
|
|
||||||
|
ChinaRegionModel get _pickedProvince => provinces[_pickedProvinceIndex];
|
||||||
|
|
||||||
|
ChinaRegionModel get _pickedCity => cities[_pickedCityIndex];
|
||||||
|
|
||||||
|
ChinaRegionModel get _pickedDistrict => districts.isEmpty
|
||||||
|
? ChinaRegionModel.empty(_pickedCity.id)
|
||||||
|
: districts[_pickedDistrictIndex];
|
||||||
|
|
||||||
|
List<ChinaRegionModel> get cities => _pickedProvince.cityList;
|
||||||
|
|
||||||
|
List<ChinaRegionModel> get districts => _pickedCity.cityList;
|
||||||
|
|
||||||
|
final FixedExtentScrollController _cityController =
|
||||||
|
FixedExtentScrollController();
|
||||||
|
final FixedExtentScrollController _districtController =
|
||||||
|
FixedExtentScrollController();
|
||||||
|
late PickedCityModel _pickedCityModel;
|
||||||
|
|
||||||
|
void updatePickedCity() {
|
||||||
|
pickCity();
|
||||||
|
setState(() {});
|
||||||
|
}
|
||||||
|
|
||||||
|
void pickCity() {
|
||||||
|
_pickedCityModel = PickedCityModel(
|
||||||
|
province: _pickedProvince,
|
||||||
|
city: _pickedCity,
|
||||||
|
district: _pickedDistrict,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_pickedProvinceIndex = 0;
|
||||||
|
_pickedCityIndex = 0;
|
||||||
|
_pickedDistrictIndex = 0;
|
||||||
|
pickCity();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_cityController.dispose();
|
||||||
|
_districtController.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return BeePickerBox(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.pop(context, _pickedCityModel);
|
||||||
|
},
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: CupertinoPicker(
|
||||||
|
itemExtent: 40.w,
|
||||||
|
magnification: 1.1,
|
||||||
|
offAxisFraction: -0.6,
|
||||||
|
looping: true,
|
||||||
|
onSelectedItemChanged: (index) {
|
||||||
|
_pickedProvinceIndex = index;
|
||||||
|
_cityController.jumpToItem(0);
|
||||||
|
_districtController.jumpToItem(0);
|
||||||
|
updatePickedCity();
|
||||||
|
},
|
||||||
|
children: provinces
|
||||||
|
.map((e) => Center(
|
||||||
|
child: Padding(
|
||||||
|
padding: EdgeInsets.only(left: 24.w, right: 8.w),
|
||||||
|
child: Text(e.name, textAlign: TextAlign.center),
|
||||||
|
),
|
||||||
|
))
|
||||||
|
.toList(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: CupertinoPicker(
|
||||||
|
itemExtent: 40.w,
|
||||||
|
magnification: 1.1,
|
||||||
|
looping: true,
|
||||||
|
scrollController: _cityController,
|
||||||
|
onSelectedItemChanged: (index) {
|
||||||
|
_pickedCityIndex = index;
|
||||||
|
_districtController.jumpToItem(0);
|
||||||
|
updatePickedCity();
|
||||||
|
},
|
||||||
|
children: cities
|
||||||
|
.map((e) => Center(
|
||||||
|
child: Padding(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 14.w),
|
||||||
|
child: Text(e.name, textAlign: TextAlign.center),
|
||||||
|
),
|
||||||
|
))
|
||||||
|
.toList(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: CupertinoPicker(
|
||||||
|
itemExtent: 40.w,
|
||||||
|
magnification: 1.1,
|
||||||
|
offAxisFraction: 0.6,
|
||||||
|
looping: true,
|
||||||
|
scrollController: _districtController,
|
||||||
|
onSelectedItemChanged: (index) {
|
||||||
|
_pickedDistrictIndex = index;
|
||||||
|
updatePickedCity();
|
||||||
|
},
|
||||||
|
children: districts.isEmpty
|
||||||
|
? [Container()]
|
||||||
|
: districts
|
||||||
|
.map((e) => Center(
|
||||||
|
child: Padding(
|
||||||
|
padding: EdgeInsets.only(left: 4.w, right: 20.w),
|
||||||
|
child: Text(e.name, textAlign: TextAlign.center),
|
||||||
|
),
|
||||||
|
))
|
||||||
|
.toList(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,102 @@
|
|||||||
|
import 'package:aku_new_community/models/login/community_model.dart';
|
||||||
|
import 'package:aku_new_community/widget/others/bee_search_text_field.dart';
|
||||||
|
import 'package:aku_new_community/widget/picker/bee_picker_box.dart';
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||||
|
|
||||||
|
class BeeCommunityPicker extends StatefulWidget {
|
||||||
|
static Future<CommunityModel?> pick(
|
||||||
|
BuildContext context, List<CommunityModel> communities) async {
|
||||||
|
return await showModalBottomSheet(
|
||||||
|
context: context,
|
||||||
|
builder: (context) {
|
||||||
|
return BeeCommunityPicker(
|
||||||
|
communities: communities,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<CommunityModel> communities;
|
||||||
|
|
||||||
|
const BeeCommunityPicker({Key? key, required this.communities})
|
||||||
|
: super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_BeeCommunityPickerState createState() => _BeeCommunityPickerState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _BeeCommunityPickerState extends State<BeeCommunityPicker> {
|
||||||
|
TextEditingController _searchController = TextEditingController();
|
||||||
|
CommunityModel? _pickedCommunity;
|
||||||
|
List<CommunityModel> _communities = [];
|
||||||
|
|
||||||
|
List<CommunityModel> screenList(String text) {
|
||||||
|
var list = <CommunityModel>[];
|
||||||
|
widget.communities.forEach((element) {
|
||||||
|
if (element.name.contains(text)) {
|
||||||
|
list.add(element);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
_communities = widget.communities;
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return BeePickerBox(
|
||||||
|
title: '选择小区',
|
||||||
|
confirmString: '确定',
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.pop(context, _pickedCommunity);
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
color: Colors.white,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
BeeSearchTextField(
|
||||||
|
controller: _searchController,
|
||||||
|
hintText: '请输入小区名称搜索',
|
||||||
|
onChanged: (text) {
|
||||||
|
_communities = screenList(text);
|
||||||
|
setState(() {});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: CupertinoPicker(
|
||||||
|
itemExtent: 80.w,
|
||||||
|
looping: false,
|
||||||
|
onSelectedItemChanged: (index) {
|
||||||
|
_pickedCommunity = _communities[index];
|
||||||
|
},
|
||||||
|
children: _communities.isEmpty
|
||||||
|
? [Container()]
|
||||||
|
: _communities
|
||||||
|
.map((e) => Center(
|
||||||
|
child: Padding(
|
||||||
|
padding:
|
||||||
|
EdgeInsets.only(left: 8.w, right: 40.w),
|
||||||
|
child:
|
||||||
|
Text(e.name, textAlign: TextAlign.center),
|
||||||
|
),
|
||||||
|
))
|
||||||
|
.toList(),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,69 @@
|
|||||||
|
import 'package:aku_new_community/base/base_style.dart';
|
||||||
|
import 'package:aku_new_community/widget/bee_divider.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||||
|
|
||||||
|
class BeePickerBox extends StatelessWidget {
|
||||||
|
final VoidCallback? onPressed;
|
||||||
|
final String confirmString;
|
||||||
|
final String? title;
|
||||||
|
final Widget child;
|
||||||
|
|
||||||
|
const BeePickerBox(
|
||||||
|
{Key? key,
|
||||||
|
this.onPressed,
|
||||||
|
this.confirmString = '完成',
|
||||||
|
this.title,
|
||||||
|
required this.child})
|
||||||
|
: super(key: key);
|
||||||
|
|
||||||
|
_buildButton({
|
||||||
|
required String title,
|
||||||
|
required VoidCallback? onPressed,
|
||||||
|
}) {
|
||||||
|
return SizedBox(
|
||||||
|
// height: 48.w,
|
||||||
|
child: TextButton(
|
||||||
|
onPressed: onPressed,
|
||||||
|
child: Text(title),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Material(
|
||||||
|
color: kForeGroundColor,
|
||||||
|
child: SizedBox(
|
||||||
|
height: 650.w,
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
SizedBox(
|
||||||
|
height: 88.w,
|
||||||
|
child: NavigationToolbar(
|
||||||
|
leading: _buildButton(
|
||||||
|
title: '取消',
|
||||||
|
onPressed: () => Navigator.pop(context),
|
||||||
|
),
|
||||||
|
middle: Text(
|
||||||
|
title ?? '',
|
||||||
|
style: TextStyle(
|
||||||
|
color: ktextPrimary,
|
||||||
|
fontSize: 28.sp,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
trailing: _buildButton(
|
||||||
|
title: confirmString,
|
||||||
|
onPressed: onPressed,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
BeeDivider.horizontal(),
|
||||||
|
Expanded(child: child),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in new issue