parent
2228ae55fe
commit
5749aff1d8
File diff suppressed because it is too large
Load Diff
@ -1,46 +0,0 @@
|
|||||||
import 'package:aku_community/model/common/img_model.dart';
|
|
||||||
|
|
||||||
class GambitModel {
|
|
||||||
int? id;
|
|
||||||
String? title;
|
|
||||||
String? summary;
|
|
||||||
String? content;
|
|
||||||
List<ImgModel>? imgUrl;
|
|
||||||
int? activityNum;
|
|
||||||
|
|
||||||
GambitModel(
|
|
||||||
{this.id,
|
|
||||||
this.title,
|
|
||||||
this.summary,
|
|
||||||
this.content,
|
|
||||||
this.imgUrl,
|
|
||||||
this.activityNum});
|
|
||||||
|
|
||||||
GambitModel.fromJson(Map<String, dynamic> json) {
|
|
||||||
id = json['id'];
|
|
||||||
title = json['title'];
|
|
||||||
summary = json['summary'];
|
|
||||||
content = json['content'];
|
|
||||||
if (json['imgUrl'] != null) {
|
|
||||||
imgUrl = [];
|
|
||||||
json['imgUrl'].forEach((v) {
|
|
||||||
imgUrl!.add(new ImgModel.fromJson(v));
|
|
||||||
});
|
|
||||||
} else
|
|
||||||
imgUrl = [];
|
|
||||||
activityNum = json['activityNum'];
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<String, dynamic> toJson() {
|
|
||||||
final Map<String, dynamic> data = new Map<String, dynamic>();
|
|
||||||
data['id'] = this.id;
|
|
||||||
data['title'] = this.title;
|
|
||||||
data['summary'] = this.summary;
|
|
||||||
data['content'] = this.content;
|
|
||||||
if (this.imgUrl != null) {
|
|
||||||
data['imgUrl'] = this.imgUrl!.map((v) => v.toJson()).toList();
|
|
||||||
}
|
|
||||||
data['activityNum'] = this.activityNum;
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,76 @@
|
|||||||
|
|
||||||
|
class ProvinceModel {
|
||||||
|
int? id;
|
||||||
|
String? name;
|
||||||
|
List<City>? cityList;
|
||||||
|
|
||||||
|
ProvinceModel({this.id, this.name, this.cityList});
|
||||||
|
|
||||||
|
ProvinceModel.fromJson(Map<String, dynamic> json) {
|
||||||
|
id = json['id'];
|
||||||
|
name = json['name'];
|
||||||
|
|
||||||
|
if (json['cityList'] != null) {
|
||||||
|
cityList = (json['cityList'] as List).map((e) => City.fromJson(e)).toList();
|
||||||
|
|
||||||
|
}else
|
||||||
|
cityList = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||||
|
data['id'] = this.id;
|
||||||
|
data['name'] = this.name;
|
||||||
|
if (this.cityList != null) {
|
||||||
|
data['cityList'] = this.cityList!.map((v) => v.toJson()).toList();
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class City {
|
||||||
|
int? id;
|
||||||
|
String? name;
|
||||||
|
List<District>? districts;
|
||||||
|
|
||||||
|
City({this.id, this.name, this.districts});
|
||||||
|
|
||||||
|
City.fromJson(Map<String, dynamic> json) {
|
||||||
|
id = json['id'];
|
||||||
|
name = json['name'];
|
||||||
|
if (json['districts'] != null) {
|
||||||
|
districts = (json['districts'] as List).map((e) => District.fromJson(e)).toList();
|
||||||
|
|
||||||
|
}else
|
||||||
|
districts = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||||
|
data['id'] = this.id;
|
||||||
|
data['name'] = this.name;
|
||||||
|
if (this.districts != null) {
|
||||||
|
data['cityList'] = this.districts!.map((v) => v.toJson()).toList();
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class District {
|
||||||
|
int? id;
|
||||||
|
String? name;
|
||||||
|
|
||||||
|
District({this.id, this.name});
|
||||||
|
|
||||||
|
District.fromJson(Map<String, dynamic> json) {
|
||||||
|
id = json['id'];
|
||||||
|
name = json['name'];
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||||
|
data['id'] = this.id;
|
||||||
|
data['name'] = this.name;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,55 @@
|
|||||||
|
class AddressModel {
|
||||||
|
int?id;
|
||||||
|
String? name;
|
||||||
|
String? tel;
|
||||||
|
int? location;
|
||||||
|
String? locationName;
|
||||||
|
|
||||||
|
String? addressDetail;
|
||||||
|
int? isDefault;
|
||||||
|
|
||||||
|
String? province;
|
||||||
|
String? city;
|
||||||
|
String? district;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
AddressModel(
|
||||||
|
{this.id,
|
||||||
|
this.name,
|
||||||
|
this.tel,
|
||||||
|
this.location,
|
||||||
|
this.locationName,
|
||||||
|
this.addressDetail,
|
||||||
|
this.isDefault,
|
||||||
|
this.province = '',
|
||||||
|
this.city = '',
|
||||||
|
this.district = '',
|
||||||
|
});
|
||||||
|
|
||||||
|
AddressModel.fromJson(Map<String, dynamic> json) {
|
||||||
|
id = json['id'];
|
||||||
|
name = json['name'];
|
||||||
|
tel = json['tel'];
|
||||||
|
location = json['location'];
|
||||||
|
locationName = json['locationName'];
|
||||||
|
addressDetail = json['addressDetail'];
|
||||||
|
isDefault = json['isDefault'];
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||||
|
data['id'] = this.id;
|
||||||
|
data['name'] = this.name;
|
||||||
|
data['tel'] = this.tel;
|
||||||
|
data['location'] = this.location;
|
||||||
|
data['locationName'] = this.locationName;
|
||||||
|
data['addressDetail'] = this.addressDetail;
|
||||||
|
data['isDefault'] = this.isDefault;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
factory AddressModel.empty() {
|
||||||
|
return AddressModel(id: null,name: '',tel: '',location: null,locationName: '',addressDetail: '',isDefault: null);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,176 @@
|
|||||||
|
import 'dart:ui';
|
||||||
|
|
||||||
|
import 'package:aku_community/model/user/adress_model.dart';
|
||||||
|
import 'package:aku_community/widget/bee_scaffold.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import 'package:flutter_easyrefresh/easy_refresh.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
|
||||||
|
import 'package:aku_community/constants/api.dart';
|
||||||
|
import 'package:aku_community/model/common/img_model.dart';
|
||||||
|
import 'package:aku_community/model/community/community_topic_model.dart';
|
||||||
|
import 'package:aku_community/pages/things_page/widget/bee_list_view.dart';
|
||||||
|
import 'package:aku_community/ui/community/community_views/topic/topic_detail_page.dart';
|
||||||
|
import 'package:aku_community/utils/headers.dart';
|
||||||
|
|
||||||
|
import '../item_my_address.dart';
|
||||||
|
import '../user_func.dart';
|
||||||
|
import 'new_address_page.dart';
|
||||||
|
|
||||||
|
class AddressListPage extends StatefulWidget {
|
||||||
|
AddressListPage({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
AddressListPageState createState() => AddressListPageState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class AddressListPageState extends State<AddressListPage>
|
||||||
|
with AutomaticKeepAliveClientMixin {
|
||||||
|
EasyRefreshController _refreshController = EasyRefreshController();
|
||||||
|
bool _onload = true;
|
||||||
|
List<AddressModel> _addressModels = [];
|
||||||
|
refresh() {
|
||||||
|
_refreshController.callRefresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
_buildItem(CommunityTopicModel model) {
|
||||||
|
return MaterialButton(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 53.w, vertical: 20.w),
|
||||||
|
onPressed: () {
|
||||||
|
Get.to(() => TopicDetailPage(model: model));
|
||||||
|
},
|
||||||
|
child: Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Hero(
|
||||||
|
// tag: "${model.firstImg}_${model.id}",
|
||||||
|
tag: model.hashCode.toString(),
|
||||||
|
child: Container(
|
||||||
|
clipBehavior: Clip.antiAlias,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(8.w),
|
||||||
|
color: Colors.black12,
|
||||||
|
),
|
||||||
|
child: Stack(
|
||||||
|
children: [
|
||||||
|
FadeInImage.assetNetwork(
|
||||||
|
placeholder: R.ASSETS_IMAGES_PLACEHOLDER_WEBP,
|
||||||
|
image: API.image(ImgModel.first(model.imgUrl)),
|
||||||
|
height: 160.w,
|
||||||
|
width: 250.w,
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
),
|
||||||
|
Positioned(
|
||||||
|
bottom: 0,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
child: ClipRRect(
|
||||||
|
borderRadius: BorderRadius.vertical(
|
||||||
|
bottom: Radius.circular(8.w),
|
||||||
|
),
|
||||||
|
child: BackdropFilter(
|
||||||
|
filter: ImageFilter.blur(sigmaX: 5, sigmaY: 5),
|
||||||
|
child: ('#${model.summary}')
|
||||||
|
.text
|
||||||
|
.center
|
||||||
|
.size(28.sp)
|
||||||
|
.white
|
||||||
|
.make()
|
||||||
|
.material(color: Colors.black26),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
12.wb,
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
(model.title ?? '')
|
||||||
|
.text
|
||||||
|
.maxLines(2)
|
||||||
|
.size(28.sp)
|
||||||
|
.bold
|
||||||
|
.overflow(TextOverflow.ellipsis)
|
||||||
|
.make(),
|
||||||
|
(model.content ?? '')
|
||||||
|
.text
|
||||||
|
.maxLines(1)
|
||||||
|
.size(22.sp)
|
||||||
|
.color(Color(0xFF666666))
|
||||||
|
.overflow(TextOverflow.ellipsis)
|
||||||
|
.make(),
|
||||||
|
21.hb,
|
||||||
|
[
|
||||||
|
Spacer(),
|
||||||
|
Image.asset(
|
||||||
|
R.ASSETS_ICONS_HOT_FIRE_PNG,
|
||||||
|
height: 24.w,
|
||||||
|
width: 24.w,
|
||||||
|
),
|
||||||
|
12.wb,
|
||||||
|
'${model.activityNum}'
|
||||||
|
.text
|
||||||
|
.maxLines(1)
|
||||||
|
.size(22.sp)
|
||||||
|
.overflow(TextOverflow.ellipsis)
|
||||||
|
.make()
|
||||||
|
].row(),
|
||||||
|
],
|
||||||
|
).box.make().expand(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
super.build(context);
|
||||||
|
return BeeScaffold(
|
||||||
|
title: '我的收货地址',
|
||||||
|
bottomNavi: MaterialButton(
|
||||||
|
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||||
|
textColor: Colors.white,
|
||||||
|
child: '新增收货地址'.text.size(28.sp).make(),
|
||||||
|
onPressed: (){
|
||||||
|
Get.to(() => NewAddressPage());
|
||||||
|
},
|
||||||
|
color: Color(0xFFE52E2E),
|
||||||
|
height: 98.w,
|
||||||
|
minWidth: double.infinity,
|
||||||
|
),
|
||||||
|
body:EasyRefresh(
|
||||||
|
firstRefresh: true,
|
||||||
|
header: MaterialHeader(),
|
||||||
|
controller: _refreshController,
|
||||||
|
onRefresh: () async {
|
||||||
|
_addressModels = await Userfunc.getMyAddress();
|
||||||
|
setState(() {});
|
||||||
|
},
|
||||||
|
child: _onload
|
||||||
|
? SizedBox()
|
||||||
|
: ListView(
|
||||||
|
children: [
|
||||||
|
..._addressModels.map((e) => MyAddressItem(addressModel: e,setDefaultListener:(){},
|
||||||
|
deleteListener:(){},editListener:(){}
|
||||||
|
)).toList(),
|
||||||
|
//
|
||||||
|
// ..._newItems.map((e) => ChatCard(
|
||||||
|
// model: e,
|
||||||
|
//
|
||||||
|
// )).toList()
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool get wantKeepAlive => true;
|
||||||
|
}
|
@ -0,0 +1,355 @@
|
|||||||
|
/*
|
||||||
|
* ====================================================
|
||||||
|
* package :
|
||||||
|
* author : Created by nansi.
|
||||||
|
* time : 2019-07-17 09:41
|
||||||
|
* remark :
|
||||||
|
* ====================================================
|
||||||
|
*/
|
||||||
|
import 'package:aku_community/model/user/ProvinceModel.dart';
|
||||||
|
import 'package:aku_community/utils/text_utils.dart';
|
||||||
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
typedef AddressSelectorCallback = Function(
|
||||||
|
String province, String city, String disctrict,int? locationId);
|
||||||
|
|
||||||
|
class AddressSelector extends StatefulWidget {
|
||||||
|
final List<ProvinceModel> model;
|
||||||
|
final String province;
|
||||||
|
final String city;
|
||||||
|
final String district;
|
||||||
|
final AddressSelectorCallback callback;
|
||||||
|
|
||||||
|
const AddressSelector(
|
||||||
|
{required this.model,
|
||||||
|
this.province = "",
|
||||||
|
this.city = "",
|
||||||
|
this.district = "",
|
||||||
|
required this.callback})
|
||||||
|
: assert(model != null),
|
||||||
|
assert(callback != null);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_AddressSelectorState createState() => _AddressSelectorState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _AddressSelectorState extends State<AddressSelector>
|
||||||
|
with TickerProviderStateMixin {
|
||||||
|
late ScrollController _scrollController;
|
||||||
|
late TabController _tabController;
|
||||||
|
late List<List<String>> _items;
|
||||||
|
late List<String> _result;
|
||||||
|
late List<int?> _indexs;
|
||||||
|
late ProvinceModel _province;
|
||||||
|
late City? _city;
|
||||||
|
late District? _district;
|
||||||
|
Color _selectedColor = Colors.white;
|
||||||
|
late BuildContext _context;
|
||||||
|
late bool _tab = true;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_scrollController = ScrollController();
|
||||||
|
_items = [[], [], []];
|
||||||
|
_indexs = [null, null, null];
|
||||||
|
_result = [widget.province, widget.city, widget.district];
|
||||||
|
_filterAddress();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
_context = context;
|
||||||
|
return GestureDetector(
|
||||||
|
onTap: () {},
|
||||||
|
child: _buildBody(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_scrollController.dispose();
|
||||||
|
_tabController.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
Container _buildBody() {
|
||||||
|
return Container(
|
||||||
|
height: 750.w,
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 15),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
borderRadius: BorderRadius.vertical(top: Radius.circular(10))),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: <Widget>[_header(), _tabBar(), _list()],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Container _header() {
|
||||||
|
return Container(
|
||||||
|
margin: EdgeInsets.symmetric(vertical: 10),
|
||||||
|
child: Row(
|
||||||
|
children: <Widget>[
|
||||||
|
Text(
|
||||||
|
"配送至",
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 18 * 2.sp,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
color: Colors.black),
|
||||||
|
),
|
||||||
|
Spacer(),
|
||||||
|
GestureDetector(
|
||||||
|
onTap: (){
|
||||||
|
_dismiss();
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
padding: EdgeInsets.all(5),
|
||||||
|
decoration:BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(20)),
|
||||||
|
color: Colors.grey[200],
|
||||||
|
),
|
||||||
|
child: Icon(
|
||||||
|
Icons.delete,
|
||||||
|
color: Colors.grey[500],
|
||||||
|
size: 12,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
TabBar _tabBar() {
|
||||||
|
return TabBar(
|
||||||
|
controller: _tabController,
|
||||||
|
labelPadding: EdgeInsets.zero,
|
||||||
|
unselectedLabelColor: Colors.black,
|
||||||
|
isScrollable: true,
|
||||||
|
indicatorColor: _selectedColor,
|
||||||
|
indicatorSize: TabBarIndicatorSize.label,
|
||||||
|
indicatorPadding: EdgeInsets.only(left: 0, right: 0),
|
||||||
|
tabs: _tabItems());
|
||||||
|
}
|
||||||
|
|
||||||
|
_tabItems() {
|
||||||
|
List<Widget> list = [];
|
||||||
|
// for (int i = 0; i < _items.length; ++i) {
|
||||||
|
for (int i = 0; i < _tabController.length; ++i) {
|
||||||
|
List addressModels = _items[i];
|
||||||
|
if (addressModels == null || addressModels.length == 0) {
|
||||||
|
list.add(Container());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
list.add(Container(
|
||||||
|
margin: EdgeInsets.symmetric(horizontal: 5.w),
|
||||||
|
height: 30.w,
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: Text(
|
||||||
|
TextUtils.isEmpty(_result[i]) ? "请选择" : _result[i],
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 16 * 2.sp,
|
||||||
|
color: _tabController.index == i ? _selectedColor : Colors.black),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
Expanded _list() {
|
||||||
|
return Expanded(
|
||||||
|
child: ListView.builder(
|
||||||
|
controller: _scrollController,
|
||||||
|
itemCount: _items[_tabController.index].length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
String addr = _items[_tabController.index][index];
|
||||||
|
bool selected = addr == _result[_tabController.index];
|
||||||
|
return
|
||||||
|
GestureDetector(
|
||||||
|
onTap: (){
|
||||||
|
_itemSelected(index);
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
|
child: Container(
|
||||||
|
padding: EdgeInsets.symmetric(vertical: 6),
|
||||||
|
child: Row(children: [
|
||||||
|
Text(
|
||||||
|
addr,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 15 * 2.sp,
|
||||||
|
color: selected ? _selectedColor : Colors.black),
|
||||||
|
),
|
||||||
|
Spacer(),
|
||||||
|
Offstage(
|
||||||
|
offstage: !selected,
|
||||||
|
child: Icon(
|
||||||
|
Icons.check,
|
||||||
|
size: 16 * 2.sp,
|
||||||
|
))
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _filterAddress() {
|
||||||
|
int index = 1;
|
||||||
|
for (int i = 0; i < widget.model.length; ++i) {
|
||||||
|
ProvinceModel province = widget.model[i];
|
||||||
|
String proAddressStr = province.name??'';
|
||||||
|
_items[0].add(proAddressStr);
|
||||||
|
if (proAddressStr != widget.province) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
_indexs[0] = i;
|
||||||
|
// index++;
|
||||||
|
_province = province;
|
||||||
|
|
||||||
|
for (int m = 0; m < province.cityList!.length; ++m) {
|
||||||
|
City city = province.cityList![m];
|
||||||
|
String cityAddressStr = city.name??'';
|
||||||
|
_items[1].add(cityAddressStr);
|
||||||
|
if (cityAddressStr != widget.city) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
_city = city;
|
||||||
|
_indexs[1] = m;
|
||||||
|
index++;
|
||||||
|
|
||||||
|
for (int n = 0; n < city.districts!.length; ++n) {
|
||||||
|
District district = city.districts![n];
|
||||||
|
String disAddressStr = district.name??'';
|
||||||
|
_items[2].add(disAddressStr);
|
||||||
|
if (disAddressStr != widget.district) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
_indexs[2] = n;
|
||||||
|
index++;
|
||||||
|
_district = district;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_resetTabBar(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _resetTabBar(int index) {
|
||||||
|
if(!_tab){
|
||||||
|
_tabController.removeListener(_tabBarListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
_tabController = TabController(length: index, vsync: this);
|
||||||
|
_tab = false;
|
||||||
|
_tabController.addListener(_tabBarListener);
|
||||||
|
_tabController.index = index - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
_itemSelected(int index) {
|
||||||
|
switch (_tabController.index) {
|
||||||
|
case 0:
|
||||||
|
{
|
||||||
|
/// 选城市
|
||||||
|
ProvinceModel province = widget.model[index];
|
||||||
|
_items[1].clear();
|
||||||
|
_items[2].clear();
|
||||||
|
_province = province;
|
||||||
|
_result[0] = _province.name??'';
|
||||||
|
_result[1] = "";
|
||||||
|
_result[2] = "";
|
||||||
|
_indexs[0] = index;
|
||||||
|
_indexs[1] = null;
|
||||||
|
_indexs[2] = null;
|
||||||
|
_city = null;
|
||||||
|
|
||||||
|
/// 没有次级列表返回
|
||||||
|
if (_province.cityList!.length == 0) {
|
||||||
|
_dismiss();
|
||||||
|
widget.callback(_province.name??'', '', '',_province.id??null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
province.cityList!.forEach((City city) {
|
||||||
|
_items[1].add(city.name!);
|
||||||
|
});
|
||||||
|
_resetTabBar(2);
|
||||||
|
_scrollController.jumpTo(0);
|
||||||
|
setState(() {});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
/// 选城市
|
||||||
|
City city = _province.cityList![index];
|
||||||
|
_city = city;
|
||||||
|
_district = null;
|
||||||
|
_items[2].clear();
|
||||||
|
_result[1] = _city?.name??'';
|
||||||
|
_indexs[1] = index;
|
||||||
|
_result[2] = "";
|
||||||
|
_indexs[2] = null;
|
||||||
|
|
||||||
|
/// 没有次级列表返回
|
||||||
|
if (city.districts!.length == 0) {
|
||||||
|
_dismiss();
|
||||||
|
widget.callback(_province.name??'', _city?.name??'', '',_province.id??null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
city.districts!.forEach((District district) {
|
||||||
|
_items[2].add(district.name??'');
|
||||||
|
});
|
||||||
|
_resetTabBar(3);
|
||||||
|
setState(() {});
|
||||||
|
_scrollController.jumpTo(0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
/// 选区
|
||||||
|
District district = _city!.districts![index];
|
||||||
|
_district = district;
|
||||||
|
_result[2] = _district?.name??'';
|
||||||
|
_indexs[2] = index;
|
||||||
|
_dismiss();
|
||||||
|
widget.callback(_province.name??'', _city?.name??'', _district?.name??'',_province.id??null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_tabBarListener() {
|
||||||
|
if (_scrollController.hasClients) {
|
||||||
|
_scrollController.jumpTo(0);
|
||||||
|
setState(() {});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_dismiss() {
|
||||||
|
Navigator.maybePop(_context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class AddressSelectorHelper {
|
||||||
|
static show(BuildContext context,
|
||||||
|
{required List<ProvinceModel> models,
|
||||||
|
String? province,
|
||||||
|
String? city,
|
||||||
|
String? district, required AddressSelectorCallback callback}) {
|
||||||
|
showModalBottomSheet(
|
||||||
|
context: context,
|
||||||
|
builder: (context) {
|
||||||
|
return AddressSelector(
|
||||||
|
model: models,
|
||||||
|
province: province??'',
|
||||||
|
city: city??'',
|
||||||
|
district: district??"",
|
||||||
|
callback: callback,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,136 @@
|
|||||||
|
/*
|
||||||
|
* ====================================================
|
||||||
|
* package :
|
||||||
|
* author : Created by nansi.
|
||||||
|
* time : 2019-07-17 17:40
|
||||||
|
* remark :
|
||||||
|
* ====================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:aku_community/utils/headers.dart';
|
||||||
|
|
||||||
|
import 'input_view.dart';
|
||||||
|
|
||||||
|
typedef StringCallback = Function(String text);
|
||||||
|
|
||||||
|
class EditTile extends StatefulWidget {
|
||||||
|
final String title;
|
||||||
|
final String value;
|
||||||
|
final String? hint;
|
||||||
|
final int maxLength;
|
||||||
|
final int maxLines;
|
||||||
|
final TextStyle titleStyle;
|
||||||
|
final TextStyle textStyle;
|
||||||
|
final TextStyle hintStyle;
|
||||||
|
final StringCallback textChanged;
|
||||||
|
final Axis direction;
|
||||||
|
final BoxConstraints constraints;
|
||||||
|
|
||||||
|
const EditTile({
|
||||||
|
Key? key,
|
||||||
|
required this.title,
|
||||||
|
required this.textChanged,
|
||||||
|
required this.value,
|
||||||
|
this.hint,
|
||||||
|
this.titleStyle = const TextStyle(
|
||||||
|
color: Colors.black, fontWeight: FontWeight.w300, fontSize: 15),
|
||||||
|
this.textStyle = const TextStyle(
|
||||||
|
color: Colors.black, fontWeight: FontWeight.w500, fontSize: 14),
|
||||||
|
this.hintStyle = const TextStyle(color: Color(0xFFBDBDBD), fontSize: 14),
|
||||||
|
this.direction = Axis.horizontal,
|
||||||
|
required this.constraints,
|
||||||
|
this.maxLength = 100,
|
||||||
|
this.maxLines = 1,
|
||||||
|
}) : assert(textChanged != null);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_EditTileState createState() => _EditTileState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _EditTileState extends State<EditTile> {
|
||||||
|
late TextEditingController _controller;
|
||||||
|
FocusNode _focusNode = FocusNode();
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_controller = TextEditingController(text: widget.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
FocusScope.of(context).requestFocus(_focusNode);
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
constraints: widget.constraints,
|
||||||
|
padding: EdgeInsets.symmetric(vertical: 2, horizontal: 15),
|
||||||
|
color: Colors.white,
|
||||||
|
child:
|
||||||
|
widget.direction == Axis.horizontal ? _horizontal() : _vertical(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Row _horizontal() {
|
||||||
|
return Row(
|
||||||
|
children: <Widget>[
|
||||||
|
Container(
|
||||||
|
width: 80.w,
|
||||||
|
child: Text(
|
||||||
|
widget.title,
|
||||||
|
style: widget.titleStyle,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: InputView(
|
||||||
|
focusNode: _focusNode,
|
||||||
|
controller: _controller,
|
||||||
|
maxLength: widget.maxLength,
|
||||||
|
hintStyle: widget.hintStyle,
|
||||||
|
textStyle: widget.textStyle,
|
||||||
|
onValueChanged: (string) {
|
||||||
|
widget.textChanged(string);
|
||||||
|
},
|
||||||
|
hint: widget.hint,
|
||||||
|
)),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
_vertical() {
|
||||||
|
return Column(
|
||||||
|
children: <Widget>[
|
||||||
|
Container(
|
||||||
|
alignment: Alignment.centerLeft,
|
||||||
|
height:40.w,
|
||||||
|
child: Text(
|
||||||
|
widget.title,
|
||||||
|
style: widget.titleStyle,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: InputView(
|
||||||
|
focusNode: _focusNode,
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 3),
|
||||||
|
maxLines: widget.maxLines,
|
||||||
|
maxLength: widget.maxLength,
|
||||||
|
controller: _controller,
|
||||||
|
hintStyle: widget.hintStyle,
|
||||||
|
textStyle: widget.textStyle,
|
||||||
|
onValueChanged: (string) {
|
||||||
|
widget.textChanged(string);
|
||||||
|
},
|
||||||
|
hint: widget.hint,
|
||||||
|
)),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_controller.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,178 @@
|
|||||||
|
/*
|
||||||
|
* ====================================================
|
||||||
|
* package :
|
||||||
|
* author : Created by nansi.
|
||||||
|
* time : 2019/6/25 3:13 PM
|
||||||
|
* remark :
|
||||||
|
* ====================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
|
import 'package:aku_community/utils/headers.dart';
|
||||||
|
|
||||||
|
typedef TextInputChangeCallBack = Function(String text);
|
||||||
|
|
||||||
|
// ignore: must_be_immutable
|
||||||
|
class InputView extends StatefulWidget {
|
||||||
|
final TextEditingController controller;
|
||||||
|
|
||||||
|
final EdgeInsetsGeometry padding;
|
||||||
|
final EdgeInsetsGeometry margin;
|
||||||
|
final String? hint;
|
||||||
|
final TextStyle textStyle;
|
||||||
|
final TextStyle hintStyle;
|
||||||
|
final Color cursorColor;
|
||||||
|
final TextInputType keyboardType;
|
||||||
|
final int? maxLength;
|
||||||
|
final FocusNode? focusNode;
|
||||||
|
final TextInputChangeCallBack? onValueChanged;
|
||||||
|
final TextInputChangeCallBack? onBeginInput;
|
||||||
|
final TextInputChangeCallBack? onInputComplete;
|
||||||
|
final bool showClear;
|
||||||
|
final int maxLines;
|
||||||
|
final TextAlign textAlign;
|
||||||
|
|
||||||
|
InputView(
|
||||||
|
{required this.controller,
|
||||||
|
this.padding = const EdgeInsets.symmetric(vertical: 5, horizontal: 8),
|
||||||
|
this.margin = const EdgeInsets.symmetric(vertical: 0, horizontal: 0),
|
||||||
|
this.hint = "",
|
||||||
|
this.textStyle = const TextStyle(color: Colors.black, fontWeight: FontWeight.w300),
|
||||||
|
this.hintStyle = const TextStyle(color: Color(0xFFBDBDBD), fontSize: 16),
|
||||||
|
this.cursorColor = const Color(0xFFBDBDBD),
|
||||||
|
this.keyboardType = TextInputType.text,
|
||||||
|
this.maxLength,
|
||||||
|
this.focusNode,
|
||||||
|
this.onValueChanged,
|
||||||
|
this.showClear = true,
|
||||||
|
this.textAlign = TextAlign.start,
|
||||||
|
this.maxLines = 1,
|
||||||
|
this.onInputComplete,
|
||||||
|
this.onBeginInput});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<StatefulWidget> createState() {
|
||||||
|
return _InputViewState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _InputViewState extends State<InputView> {
|
||||||
|
late TextEditingController _controller;
|
||||||
|
late FocusNode _focusNode;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
_focusNode = widget.focusNode ?? FocusNode();
|
||||||
|
_controller = widget.controller;
|
||||||
|
|
||||||
|
_focusNode.addListener(() {
|
||||||
|
setState(() {
|
||||||
|
|
||||||
|
});
|
||||||
|
if (!_focusNode.hasFocus) {
|
||||||
|
if (widget.onInputComplete != null) {
|
||||||
|
widget.onInputComplete!(_controller.text);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (widget.onBeginInput != null) {
|
||||||
|
widget.onBeginInput!(_controller.text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return GestureDetector(
|
||||||
|
onTap: () {},
|
||||||
|
child: Container(
|
||||||
|
margin: widget.margin,
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: widget.padding.horizontal),
|
||||||
|
child: Row(
|
||||||
|
children: <Widget>[
|
||||||
|
Expanded(
|
||||||
|
child: CupertinoTextField(
|
||||||
|
placeholder: widget.hint,
|
||||||
|
placeholderStyle: widget.hintStyle,
|
||||||
|
controller: _controller,
|
||||||
|
focusNode: _focusNode,
|
||||||
|
maxLines: widget.maxLines,
|
||||||
|
keyboardType: widget.keyboardType,
|
||||||
|
style: widget.textStyle,
|
||||||
|
inputFormatters: widget.maxLength == null
|
||||||
|
? null
|
||||||
|
: [
|
||||||
|
widget.maxLength == 0 ? FilteringTextInputFormatter.digitsOnly:
|
||||||
|
LengthLimitingTextInputFormatter(widget.maxLength),
|
||||||
|
],
|
||||||
|
cursorColor: widget.cursorColor,
|
||||||
|
onChanged: widget.onValueChanged,
|
||||||
|
onEditingComplete: () {},
|
||||||
|
textAlign: widget.textAlign,
|
||||||
|
onSubmitted: (_) {
|
||||||
|
FocusScope.of(context).requestFocus(FocusNode());
|
||||||
|
},
|
||||||
|
enableInteractiveSelection: true,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
border: Border.all(
|
||||||
|
color: Colors.white.withAlpha(0),
|
||||||
|
width: 0
|
||||||
|
)
|
||||||
|
),
|
||||||
|
// decoration: InputDecoration(
|
||||||
|
// contentPadding: EdgeInsets.symmetric(vertical: widget.padding.vertical),
|
||||||
|
// border: InputBorder.none,
|
||||||
|
// hintText: widget.hint,
|
||||||
|
// hintStyle: widget.hintStyle),
|
||||||
|
),
|
||||||
|
// child: TextField(
|
||||||
|
// controller: _controller,
|
||||||
|
// focusNode: _focusNode,
|
||||||
|
// maxLines: widget.maxLines,
|
||||||
|
// keyboardType: widget.keyboardType,
|
||||||
|
// style: widget.textStyle,
|
||||||
|
// inputFormatters: widget.maxLength == null
|
||||||
|
// ? null
|
||||||
|
// : [
|
||||||
|
// LengthLimitingTextInputFormatter(widget.maxLength),
|
||||||
|
// ],
|
||||||
|
// cursorColor: widget.cursorColor,
|
||||||
|
// onChanged: widget.onValueChanged,
|
||||||
|
// onEditingComplete: () {},
|
||||||
|
// textAlign: widget.textAlign,
|
||||||
|
// onSubmitted: (_) {
|
||||||
|
// FocusScope.of(context).requestFocus(FocusNode());
|
||||||
|
// },
|
||||||
|
// enableInteractiveSelection: true,
|
||||||
|
// decoration: InputDecoration(
|
||||||
|
// contentPadding: EdgeInsets.symmetric(vertical: widget.padding.vertical),
|
||||||
|
// border: InputBorder.none,
|
||||||
|
// hintText: widget.hint,
|
||||||
|
// hintStyle: widget.hintStyle),
|
||||||
|
// ),
|
||||||
|
),
|
||||||
|
widget.showClear ? _clearButton() : Container()
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
_clearButton() {
|
||||||
|
return _focusNode.hasFocus
|
||||||
|
? GestureDetector(
|
||||||
|
child: Icon(
|
||||||
|
Icons.clear,
|
||||||
|
size: 15,
|
||||||
|
color: Colors.grey[300],
|
||||||
|
),
|
||||||
|
onTap: () {
|
||||||
|
_controller.clear();
|
||||||
|
})
|
||||||
|
: Container();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,266 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
import 'dart:ui';
|
||||||
|
|
||||||
|
import 'package:aku_community/model/user/ProvinceModel.dart';
|
||||||
|
import 'package:aku_community/model/user/adress_model.dart';
|
||||||
|
import 'package:aku_community/pages/personal/user_func.dart';
|
||||||
|
import 'package:aku_community/utils/hive_store.dart';
|
||||||
|
import 'package:aku_community/utils/text_utils.dart';
|
||||||
|
import 'package:aku_community/widget/bee_scaffold.dart';
|
||||||
|
import 'package:bot_toast/bot_toast.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
|
import 'package:flutter_easyrefresh/easy_refresh.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
|
||||||
|
import 'package:aku_community/constants/api.dart';
|
||||||
|
import 'package:aku_community/utils/headers.dart';
|
||||||
|
|
||||||
|
import 'address_selector.dart';
|
||||||
|
import 'editView.dart';
|
||||||
|
|
||||||
|
class NewAddressPage extends StatefulWidget {
|
||||||
|
final bool? isFirstAdd;
|
||||||
|
final AddressModel? addressModel;
|
||||||
|
NewAddressPage({Key? key, this.isFirstAdd, this.addressModel}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_NewAddressPageState createState() => _NewAddressPageState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _NewAddressPageState extends State<NewAddressPage>{
|
||||||
|
EasyRefreshController _refreshController = EasyRefreshController();
|
||||||
|
late AddressModel _address = AddressModel.empty();
|
||||||
|
late List<ProvinceModel> _cityJsonModels = [];
|
||||||
|
late StateSetter _addressStateSetter;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
if (widget.addressModel != null) {
|
||||||
|
_address = widget.addressModel!;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
|
||||||
|
return BeeScaffold(
|
||||||
|
title: '新建收货地址',
|
||||||
|
body:_buildBody(context),
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
_buildBody(BuildContext context) {
|
||||||
|
return GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
//FocusScope.of(context).requestFocus(new FocusNode());
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
child:ListView(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
height: 10,
|
||||||
|
),
|
||||||
|
EditTile(
|
||||||
|
constraints: BoxConstraints.tight(Size(double.infinity, 45)),
|
||||||
|
title: "收货人",
|
||||||
|
value: _address.name??'',
|
||||||
|
hint: "请填写收货人姓名",
|
||||||
|
textChanged: (value) {
|
||||||
|
_address.name = value;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
height: 3,
|
||||||
|
),
|
||||||
|
EditTile(
|
||||||
|
constraints: BoxConstraints.tight(Size(double.infinity, 45)),
|
||||||
|
title: "手机号码",
|
||||||
|
value: _address.tel??'',
|
||||||
|
hint: "请填写收货人手机号码",
|
||||||
|
maxLength: 11,
|
||||||
|
textChanged: (value) {
|
||||||
|
_address.tel = value;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
height: 3,
|
||||||
|
),
|
||||||
|
_addressView(),
|
||||||
|
Container(
|
||||||
|
height: 3,
|
||||||
|
),
|
||||||
|
EditTile(
|
||||||
|
title: "详细地址",
|
||||||
|
hint: "街道门牌号等",
|
||||||
|
value: _address.addressDetail??'',
|
||||||
|
maxLength: 100,
|
||||||
|
maxLines: 3,
|
||||||
|
direction: Axis.vertical,
|
||||||
|
constraints: BoxConstraints(maxHeight: 100),
|
||||||
|
textChanged: (value) {
|
||||||
|
_address.addressDetail = value;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
height: 30,
|
||||||
|
),
|
||||||
|
// _defaultAddressTile(),
|
||||||
|
Container(
|
||||||
|
height: 100,
|
||||||
|
),
|
||||||
|
_saveButton(context)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Container _saveButton(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
margin: EdgeInsets.symmetric(horizontal: 15),
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: (){
|
||||||
|
|
||||||
|
_saveAddress(context);
|
||||||
|
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.red,
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(8.w)),
|
||||||
|
),
|
||||||
|
height: 45.w,
|
||||||
|
padding: EdgeInsets.symmetric(vertical: 8.w),
|
||||||
|
child: Text(
|
||||||
|
"保存地址",style: TextStyle(
|
||||||
|
color: Colors.white,
|
||||||
|
fontSize: 17 * 2.sp,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
_addressView() {
|
||||||
|
return StatefulBuilder(
|
||||||
|
builder: (BuildContext context, StateSetter setSta) {
|
||||||
|
_addressStateSetter = setSta;
|
||||||
|
return GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
print('1');
|
||||||
|
if (_cityJsonModels.isEmpty) {
|
||||||
|
print('2');
|
||||||
|
getCityList().then((success) {
|
||||||
|
if (success) {
|
||||||
|
_selectAddress(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_selectAddress(context);
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
padding: EdgeInsets.symmetric(vertical: 12, horizontal: 15),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.red,
|
||||||
|
border: Border(
|
||||||
|
bottom: BorderSide(color: Colors.grey, width: 0.5))),
|
||||||
|
child: Row(
|
||||||
|
children: <Widget>[
|
||||||
|
Container(
|
||||||
|
width: 80.w,
|
||||||
|
child: Text(
|
||||||
|
"所在地区",
|
||||||
|
style:TextStyle(fontSize: 15.sp,)
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
TextUtils.isEmpty(_address.locationName??'')
|
||||||
|
? "选择地址"
|
||||||
|
: "${_address.locationName} : ""}",
|
||||||
|
textAlign: TextAlign.end,
|
||||||
|
style: TextStyle(fontSize: 14.sp, fontWeight: FontWeight.w500),
|
||||||
|
)),
|
||||||
|
Icon(
|
||||||
|
Icons.navigate_next,
|
||||||
|
size: 16,
|
||||||
|
color: Colors.black,
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// 弹出地址选择
|
||||||
|
_selectAddress(BuildContext context) {
|
||||||
|
AddressSelectorHelper.show(context,
|
||||||
|
models: _cityJsonModels,
|
||||||
|
province: _address.province,
|
||||||
|
city: _address.city,
|
||||||
|
district: _address.district,
|
||||||
|
callback: (String province, String city, String district,int? locationId) {
|
||||||
|
_address.locationName= province+city+district;
|
||||||
|
_address.id = locationId??null;
|
||||||
|
_addressStateSetter(() {});
|
||||||
|
print("$province - $city -$district");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<bool> getCityList() async {
|
||||||
|
_cityJsonModels = await HiveStore.appBox?.get('cityList')??[];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 保存地址
|
||||||
|
_saveAddress(BuildContext context) async {
|
||||||
|
if (TextUtils.isEmpty(_address.name??"")) {
|
||||||
|
BotToast.showText(text: '收货人不能为空');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TextUtils.isEmpty(_address.tel??'') ||
|
||||||
|
!TextUtils.verifyPhone(_address.tel)) {
|
||||||
|
BotToast.showText(text: '手机号格式不正确');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TextUtils.isEmpty(_address.province??'')) {
|
||||||
|
BotToast.showText(text: '所在地区不能为空');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TextUtils.isEmpty(_address.addressDetail??'')) {
|
||||||
|
BotToast.showText(text: '详细地址不能为空');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (_address.id != null) {
|
||||||
|
Userfunc.insertAddress( _address.name??'', _address.tel??'',
|
||||||
|
_address.location??null, _address.addressDetail??'', _address.isDefault??null);
|
||||||
|
} else {
|
||||||
|
Userfunc.updateAddress(_address.id!, _address.name??'', _address.tel??'',
|
||||||
|
_address.location??null, _address.addressDetail??'', _address.isDefault??null);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Navigator.maybePop<dynamic>(context, _address);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,121 @@
|
|||||||
|
/*
|
||||||
|
* ====================================================
|
||||||
|
* package :
|
||||||
|
* author : Created by nansi.
|
||||||
|
* time : 2019/6/24 4:05 PM
|
||||||
|
* remark :
|
||||||
|
* ====================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
import 'package:aku_community/base/base_style.dart';
|
||||||
|
import 'package:aku_community/model/user/adress_model.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:aku_community/utils/headers.dart';
|
||||||
|
|
||||||
|
|
||||||
|
// ignore: must_be_immutable
|
||||||
|
class MyAddressItem extends StatelessWidget {
|
||||||
|
final AddressModel addressModel;
|
||||||
|
final VoidCallback setDefaultListener;
|
||||||
|
final VoidCallback deleteListener;
|
||||||
|
final VoidCallback editListener;
|
||||||
|
|
||||||
|
Color _titleColor = Colors.black;
|
||||||
|
|
||||||
|
MyAddressItem(
|
||||||
|
{required this.addressModel,
|
||||||
|
required this.deleteListener,
|
||||||
|
required this.editListener,
|
||||||
|
required this.setDefaultListener})
|
||||||
|
: assert(addressModel != null);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
color: Colors.white,
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: <Widget>[
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
GestureDetector(
|
||||||
|
onTap: (){
|
||||||
|
this.setDefaultListener;
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
child: Image.asset(R.ASSETS_ICONS_ICON_MY_SETTING_PNG,width: 40.w,height: 40.w,),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
Padding(
|
||||||
|
padding:
|
||||||
|
EdgeInsets.symmetric(horizontal: 20.w, vertical:6.w),
|
||||||
|
child: Text(
|
||||||
|
addressModel.locationName??'',
|
||||||
|
style:TextStyle(fontSize: 24.sp,color: ktextPrimary)
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding:
|
||||||
|
EdgeInsets.symmetric(horizontal: 20.w, vertical:6.w),
|
||||||
|
child: Text(
|
||||||
|
addressModel.addressDetail??'',
|
||||||
|
style:TextStyle(fontSize: 32.sp,color: ktextPrimary)
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 20.w),
|
||||||
|
child: Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
|
children: <Widget>[
|
||||||
|
Text(
|
||||||
|
addressModel.name??'',
|
||||||
|
style: TextStyle(fontSize: 24.sp,color: ktextPrimary)
|
||||||
|
),
|
||||||
|
30.wb,
|
||||||
|
Text(
|
||||||
|
addressModel.tel??'',
|
||||||
|
style: TextStyle(fontSize: 24.sp,color: ktextPrimary)
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
GestureDetector(
|
||||||
|
child: Container(
|
||||||
|
child: Image.asset(R.ASSETS_ICONS_ICON_MY_SETTING_PNG,width: 40.w,height: 40.w,),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
|
||||||
|
|
||||||
|
Container(
|
||||||
|
height: 1,
|
||||||
|
color: Colors.grey[200],
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
children: <Widget>[
|
||||||
|
Text(
|
||||||
|
addressModel.isDefault == 0 ? "" : "默认地址",
|
||||||
|
style: TextStyle(fontSize: 28.sp,color: ktextSubColor),
|
||||||
|
),
|
||||||
|
Spacer(),
|
||||||
|
GestureDetector(
|
||||||
|
onTap: (){
|
||||||
|
this.setDefaultListener;
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
child:Text(
|
||||||
|
"删除",
|
||||||
|
style: TextStyle(fontSize: 28.sp,color: ktextSubColor),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,117 @@
|
|||||||
|
import 'package:aku_community/constants/api.dart';
|
||||||
|
import 'package:aku_community/model/community/activity_item_model.dart';
|
||||||
|
import 'package:aku_community/model/community/board_model.dart';
|
||||||
|
import 'package:aku_community/model/community/community_topic_model.dart';
|
||||||
|
import 'package:aku_community/model/community/hot_news_model.dart';
|
||||||
|
import 'package:aku_community/model/community/swiper_model.dart';
|
||||||
|
import 'package:aku_community/model/user/adress_model.dart';
|
||||||
|
import 'package:aku_community/models/market/goods_classification.dart';
|
||||||
|
import 'package:aku_community/models/market/goods_popular_model.dart';
|
||||||
|
import 'package:aku_community/models/market/order/goods_home_model.dart';
|
||||||
|
import 'package:aku_community/utils/network/base_list_model.dart';
|
||||||
|
import 'package:aku_community/utils/network/base_model.dart';
|
||||||
|
import 'package:aku_community/utils/network/net_util.dart';
|
||||||
|
|
||||||
|
class Userfunc {
|
||||||
|
|
||||||
|
///查询爆款推荐
|
||||||
|
static Future<List<AddressModel>> getMyAddress(
|
||||||
|
) async {
|
||||||
|
BaseModel model = await NetUtil().get(
|
||||||
|
API.user.myAddressList,
|
||||||
|
);
|
||||||
|
if (model.data!.length == 0)
|
||||||
|
return [];
|
||||||
|
return (model.data as List)
|
||||||
|
.map((e) => AddressModel.fromJson(e))
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
///添加收货地址
|
||||||
|
static Future<bool> insertAddress(String name,String tel,int? location,
|
||||||
|
String addressDetail,int? isDefault) async {
|
||||||
|
BaseModel model = await NetUtil().get(
|
||||||
|
API.user.insertAddress,
|
||||||
|
params: {'name':name,'tel':tel,'location':location,
|
||||||
|
'addressDetail':addressDetail,'isDefault':isDefault},
|
||||||
|
showMessage: true
|
||||||
|
);
|
||||||
|
if (model.message! == "请求成功")
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
///修改收货地址
|
||||||
|
static Future<bool> updateAddress(int id,String name,String tel,int? location,
|
||||||
|
String addressDetail,int? isDefault) async {
|
||||||
|
BaseModel model = await NetUtil().get(
|
||||||
|
API.user.updateAddress,
|
||||||
|
params: {'id': id,'name':name,'tel':tel,'location':location,
|
||||||
|
'addressDetail':addressDetail,'isDefault':isDefault},
|
||||||
|
showMessage: true
|
||||||
|
);
|
||||||
|
if (model.message! == "请求成功")
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
///删除收货地址
|
||||||
|
static Future<bool> deleteAddress(int addressId) async {
|
||||||
|
BaseModel model = await NetUtil().get(
|
||||||
|
API.user.deleteAddress,
|
||||||
|
params: {'addressId': addressId},
|
||||||
|
showMessage: true
|
||||||
|
);
|
||||||
|
if (model.message! == "请求成功")
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///查询SKU总数
|
||||||
|
static Future<String> getSkuTotal() async {
|
||||||
|
BaseModel model = await NetUtil().get(
|
||||||
|
API.market.skuTotal,
|
||||||
|
);
|
||||||
|
if (model.data! == null)
|
||||||
|
return '0';
|
||||||
|
return (model.data as int).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static Future<List<BoardItemModel>> board() async {
|
||||||
|
BaseListModel model = await NetUtil().getList(
|
||||||
|
API.community.boardList,
|
||||||
|
params: {'pageNum': 1, 'size': 5},
|
||||||
|
);
|
||||||
|
if (model.tableList!.length == 0) return [];
|
||||||
|
return model.tableList!.map((e) => BoardItemModel.fromJson(e)).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future<List<SwiperModel>> swiper() async {
|
||||||
|
BaseModel model = await NetUtil().get(
|
||||||
|
API.community.getSwiper,
|
||||||
|
);
|
||||||
|
if (model.data!.length == 0)
|
||||||
|
return [];
|
||||||
|
return (model.data as List)
|
||||||
|
.map((e) => SwiperModel.fromJson(e))
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,76 @@
|
|||||||
|
/*
|
||||||
|
* ====================================================
|
||||||
|
* package :
|
||||||
|
* author : Created by nansi.
|
||||||
|
* time : 2019-07-16 15:21
|
||||||
|
* remark :
|
||||||
|
* ====================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:path_provider/path_provider.dart';
|
||||||
|
|
||||||
|
typedef ReadFileCallback = Function(bool success, File file, String msg);
|
||||||
|
typedef WriteFileCallback = Function(bool success, File file, String msg);
|
||||||
|
|
||||||
|
class FileOperationResult {
|
||||||
|
Object? data;
|
||||||
|
String msg;
|
||||||
|
bool success;
|
||||||
|
|
||||||
|
FileOperationResult(this.data, this.msg, this.success);
|
||||||
|
}
|
||||||
|
|
||||||
|
class FileUtils {
|
||||||
|
static Future<String> tempPath() async {
|
||||||
|
try {
|
||||||
|
var tempDir = await getTemporaryDirectory();
|
||||||
|
String tempPath = tempDir.path;
|
||||||
|
return tempPath;
|
||||||
|
} catch (err) {
|
||||||
|
print(err);
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future<String> appDocPath() async {
|
||||||
|
try {
|
||||||
|
var appDocDir = await getApplicationDocumentsDirectory();
|
||||||
|
String appDocPath = appDocDir.path;
|
||||||
|
return appDocPath;
|
||||||
|
} catch (err) {
|
||||||
|
print(err);
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 读取 json 数据
|
||||||
|
static Future<FileOperationResult> readJSON(String path) async {
|
||||||
|
try {
|
||||||
|
String filePath = await appDocPath();
|
||||||
|
final File file = await localFile(filePath+path);
|
||||||
|
String str = await file.readAsString();
|
||||||
|
return FileOperationResult(str, "读取成功", true);
|
||||||
|
} catch (err) {
|
||||||
|
return FileOperationResult(null, err.toString(), false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 写入 json 数据
|
||||||
|
static Future<FileOperationResult> writeJSON(String path, String jsonStr) async {
|
||||||
|
try {
|
||||||
|
String filePath = await appDocPath();
|
||||||
|
final File file = await localFile(filePath+path);
|
||||||
|
await file.writeAsString(jsonStr);
|
||||||
|
return FileOperationResult(file, "写入成功", true);
|
||||||
|
} catch (err) {
|
||||||
|
return FileOperationResult(null, err.toString(), false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static localFile(path) async {
|
||||||
|
print('文件目录: ' + path);
|
||||||
|
return new File(path);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in new issue