Commit 3235a999 authored by 杜欣's avatar 杜欣

Merge branch 'test' into featrue/duxin

# Conflicts:
#	lib/ClueModel/ClueRouter.dart
#	lib/ClueModel/ClueRouterImpl.dart
#	lib/MainRouter/page/test/TestPage.dart
parents 91caf80a 59af1797
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Flutter",
"request": "launch",
"type": "dart"
}
]
}
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -3,14 +3,21 @@
* @date 2020/6/24
**/
import 'package:flutter/cupertino.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_common/Annotations/RouterBaser.dart';
import 'package:flutter_common/Annotations/anno/Router.dart';
import 'package:flutter_common/Annotations/anno/RouterCenter.dart';
import 'package:gm_flutter/ClueModel/ClueRouterImpl.dart';
@Router("ClueRouter", ClueRouterImpl, true)
abstract class ClueRouter implements RouterBaser {
Widget getProjectDetailsPage();
Widget getPlansCompareFeed();
Widget getLevelOnePage();
Widget getLevelTwoPage();
Widget getPlanPage();
Widget getPlanCompareDetailPage();
}
......@@ -4,16 +4,40 @@
**/
import 'package:flutter/src/widgets/framework.dart';
import 'package:gm_flutter/ClueModel/ClueRouter.dart';
import 'package:gm_flutter/ClueModel/page/PlansCompareFeed/PlansCompareFeedPage.dart';
import 'package:gm_flutter/ClueModel/page/ProjectDetails/ProjectDetailsPage.dart';
import 'package:gm_flutter/ClueModel/page/levelOne/LevelOnePage.dart';
import 'package:gm_flutter/ClueModel/page/levelTwo/LevelTwoPage.dart';
import 'package:gm_flutter/ClueModel/page/plan/PlanPage.dart';
import 'package:gm_flutter/ClueModel/page/PlanCompareDetail/PlanCompareDetailPage.dart';
class ClueRouterImpl implements ClueRouter {
@override
Widget getProjectDetailsPage() {
return ProjectDetailsPage();
}
@override
Widget getLevelOnePage() {
return LevelOnePage();
}
@override
Widget getLevelTwoPage() {
return LevelTwoPage();
}
@override
Widget getPlansCompareFeed() {
return PlansCompareFeedPage();
}
@override
Widget getPlanPage() {
return PlanPage();
}
Widget getPlanCompareDetailPage() {
return PlanCompareDetailPage();
}
}
/*
* @Author: zx
* @Date: 2020-06-30 17:43:13
* @Last Modified by: zx
* @Last Modified time: 2020-07-01 20:04:23
*/
import 'package:flutter_common/commonModel/live/BaseModel.dart';
import 'package:flutter_common/commonModel/live/LiveData.dart';
import 'package:gm_flutter/ClueModel/server/api/ClueApi.serv.dart';
import 'package:gm_flutter/ClueModel/server/entity/PlanCompareDetail.dart';
import 'package:gm_flutter/commonModel/GMBase.dart';
import 'package:gm_flutter/commonModel/rx/RxDispose.dart';
class PlanCompareDetailModel extends BaseModel {
LiveData<PlanCompareDetail> detailLive = LiveData();
RxDispose rxDispose = RxDispose();
void init() {
ClueApiImpl.getInstance()
.getPlanCompareDetail(DioUtil.getInstance().getDio(), [1,2])
.listen((event) {
if (event.error == 0) {
detailLive.notifyView(event);
}
})
.addToDispose(rxDispose)
.onError((err) {});
}
@override
void dispose() {
detailLive.dispost();
}
}
\ No newline at end of file
/*
* @Author: zx
* @Date: 2020-06-30 17:40:43
* @Last Modified by: zx
* @Last Modified time: 2020-07-01 22:11:20
*/
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:gm_flutter/ClueModel/page/PlanCompareDetail/PlanCompareDetailModel.dart';
import 'package:gm_flutter/ClueModel/server/entity/PlanCompareDetail.dart';
import 'package:gm_flutter/ClueModel/view/FiveStarView.dart';
import 'package:gm_flutter/commonModel/base/BaseComponent.dart';
import 'package:gm_flutter/commonModel/base/BaseState.dart';
class PlanCompareDetailPage extends StatefulWidget {
@override
State<StatefulWidget> createState() => PlanCompareDetailPageState();
}
class PlanCompareDetailPageState extends BaseState<PlanCompareDetailPage> {
PlanCompareDetailModel _model = new PlanCompareDetailModel();
PageController pageController = new PageController();
double screenWidth;
List<Widget> viewList = new List();
@override
void initState() {
super.initState();
pageController.addListener(() {
});
Groups groups;
viewList.add(planNormalEffectiveAttrsView(groups));
viewList.add(planNormalEffectiveAttrsView(groups));
viewList.add(planNormalEffectiveAttrsView(groups));
}
@override
void dispose() {
_model.dispose();
pageController.dispose();
pageController.dispose();
super.dispose();
}
@override
Widget buildItem(BuildContext context) {
screenWidth = MediaQuery.of(context).size.width;
return Scaffold(
appBar: baseAppBar(
title: "对比详情",
centerTitle: true,
backClick: () {
Navigator.pop(context);
}),
body: Container(
child:
// planPopularityView()
// planNormalEffectiveAttrsView()
// setupHome([], []),
reloadPage(),
)
);
}
Widget reloadPage () {
return StreamBuilder(
stream: _model.detailLive.stream,
initialData: PlanCompareDetail(),
builder: (c, data) {
PlanCompareDetail detail = data.data;
if (detail == null || detail.data == null || detail.data.groups == null) {
return loadingItem();
}
return setupHome(detail.data.plansInfo, detail.data.groups);
},
);
}
Widget setupHome(List<PlansInfo> plansInfo, List<Groups> groups) {
return Column(
children: <Widget>[
Expanded(
child: Stack(
children: <Widget>[
head(plansInfo),
Expanded (
child: Container(
margin: EdgeInsets.fromLTRB(15, 105, 15, 0),
child:
// ListView.builder(
// itemBuilder: (BuildContext context, int index) {
// Groups group = groups[index];
// switch (group.groupType) {
// case 'hot':
// return planPopularityView(group);
// break;
// case 'normal_attrs':
// return planNormalEffectiveAttrsView(group);
// break;
// case 'effective_attrs':
// return planNormalEffectiveAttrsView(group);
// break;
// default:
// return planNormalEffectiveAttrsView(group);
// }
// },
// itemCount: groups.length,
// )
CustomScrollView(
slivers: <Widget>[
SliverList(
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return viewList[index];
},
childCount: viewList.length,
),
),
],
),
)
),
],
),
)
],
);
}
Widget head(List<PlansInfo> plansInfo) {
PlansInfo plan;
return Container(
// key: keyTop,
color: Colors.yellow,
width: screenWidth,
height: 105,
alignment: Alignment.topLeft,
margin: EdgeInsets.fromLTRB(9.5, 0, 9.5, 0),
child: Row(children: <Widget>[
// 根据 flex系数,分配剩余空间
Expanded(
flex:1,
child: headItem(plan)
),
Expanded(
flex: 1,
child: headItem(plan)
)
]
),
);
}
Widget headItem(PlansInfo plan) {
return Container(
child: Stack(
children: <Widget>[
Positioned(
child: Container(
margin: EdgeInsets.fromLTRB(5.5, 15, 5.5, 15),
width: (screenWidth - 41) / 2.0,
// child: Text('1111111'),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(7.0),
image:
DecorationImage(
fit: BoxFit.cover,
image: NetworkImage(
"https://pic.igengmei.com/2018/09/11/1513/b7e825a4e4c1-w")
)
)
),
),
Positioned(
left: 17.5,
top: 31,
child: baseText('11111', 15, Color(0xff333333),
bold: true),
),
Positioned(
left: 17.5,
bottom: 31,
child: baseText('¥¥¥¥¥¥¥¥¥¥', 14, Colors.red,
bold: true),
),
]
)
);
}
Widget titleView() {
return Container(
height: 81,
width: screenWidth,
color: Colors.cyan,
margin: EdgeInsets.fromLTRB(0, 30, 0, 13),
alignment: Alignment.topCenter,
child: Container(
child: baseText('基础属性', 21, Colors.black, bold: true),
),
);
}
Widget planPopularityView() {
return Container(
color: Colors.green,
height: 265,
child: Container (
child: Column(
children: <Widget>[
titleView(),
Row(
children: <Widget>[
Expanded(
flex:1,
child: planPopularityLeftItem()
),
Expanded(
flex: 1,
child: planPopularityRightItem()
)
]
)
]
)
),
);
}
Widget planPopularityLeftItem() {
return Container(
color: Colors.red,
// height: 80,
child:
Expanded(
child: Stack(
children: <Widget>[
Positioned(
right: 20,
top: 12,
child: baseText('99%', 21, Color(0xffF25874),
bold: true)
),
Positioned(
right: 20,
top: 33,
// bottom: 12,
child: baseText('好评率', 12, Color(0xff666666),
bold: false),
),
Positioned(
right: 20,
top: 55,
// bottom: 12,
child: FiveStarView(3,5),
),
Positioned(
right: 20,
top: 98,
bottom: 12,
child: baseText('13679个', 21, Color(0xffF25874),
bold: true),
),
Positioned(
right: 20,
top: 112,
bottom: 12,
child: baseText('销量', 12, Color(0xff666666),
bold: false),
),
Positioned(
right: 20,
top: 132,
bottom: 12,
child: baseText('', 12, Color(0xff666666),
bold: false),
),
]
)
)
);
}
Widget planPopularityRightItem() {
return Container(
color: Colors.red,
// height: 80,
child:
Expanded(
child: Stack(
children: <Widget>[
Positioned(
left: 20,
top: 12,
child: baseText('99%', 21, Color(0xffF25874),
bold: true)
),
Positioned(
left: 20,
top: 33,
// bottom: 12,
child: baseText('好评率', 12, Color(0xff666666),
bold: false),
),
Positioned(
left: 20,
top: 55,
// bottom: 12,
child: FiveStarView(3,5),
),
Positioned(
left: 20,
top: 98,
bottom: 12,
child: baseText('13679个', 21, Color(0xffF25874),
bold: true),
),
Positioned(
left: 20,
top: 112,
bottom: 12,
child: baseText('销量', 12, Color(0xff666666),
bold: false),
),
Positioned(
left: 20,
top: 132,
bottom: 12,
child: baseText('', 12, Color(0xff666666),
bold: false),
),
]
)
)
);
}
Widget planNormalEffectiveAttrsView(Groups groups) {
return Container(
color: Colors.green,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Expanded(
child: Stack(
children: <Widget>[
titleView(),
Expanded (
child: Container(
margin: EdgeInsets.fromLTRB(0, 68, 0, 0),
child:
ListView.builder(
itemBuilder: (c, index) {
return planBaseAttrsView();
},
itemCount: 5,
)
)
)
]
)
)
]
)
);
}
Widget planBaseAttrsView() {
return Container(
color: Colors.red,
height: 80,
child: Row(
children: <Widget>[
Expanded(
flex:1,
child: planBaseAttrsLeftView()
),
Expanded(
flex: 1,
child: planBaseAttrsRightView()
)
]
)
);
}
Widget planBaseAttrsLeftView() {
return Container(
color: Colors.red,
height: 80,
child: Stack(
children: <Widget>[
Positioned(
right: 20,
top: 12,
child: baseText('嘻嘻嘻嘻嘻嘻', 14, Color(0xff3FB5AF),
bold: true)
),
Positioned(
right: 20,
// top: 12,
bottom: 12,
child: baseText('哈哈哈哈', 12, Color(0xff666666),
bold: false),
),
]
)
);
}
Widget planBaseAttrsRightView() {
return Container(
color: Colors.red,
height: 80,
child: Stack(
children: <Widget>[
Positioned(
left: 20,
top: 12,
child: baseText('嘻嘻嘻嘻嘻嘻', 14, Color(0xffF25874),
bold: true)
),
Positioned(
left: 20,
// top: 12,
bottom: 12,
child: baseText('哈哈哈哈', 12, Color(0xff666666),
bold: false),
),
]
)
);
}
}
\ No newline at end of file
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:gm_flutter/ClueModel/server/entity/PlansCompareFeed.dart';
class PlansCompareFeedItemView extends StatelessWidget {
Plans plan;
int groupValue = 1;
PlansCompareFeedItemView(this.plan);
@override
Widget build(BuildContext context) {
return Container(child: getItem());
}
getItem() {
if (plan.planType == 1) {
return getFirstLevelItem();
} else {
return getSecondLevelItem();
}
}
getFirstLevelItem() {
Container(
margin: EdgeInsets.all(4.0),
child: Row(
children: <Widget>[
Radio(
value: 1,
groupValue: groupValue,
onChanged: (value) {
groupValue = value;
}),
ClipRRect(
borderRadius: BorderRadius.circular(2.0),
child: Image.network(
plan.projectImage,
width: 50,
height: 50,
fit: BoxFit.fill,
),
),
Expanded(
child: Container(
margin: EdgeInsets.only(left: 8.0),
height: 50,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Row(
children: <Widget>[
Text(
plan.name,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 14,
color: Color(0xFF282828)),
maxLines: 1,
),
Text(
"好评率 ",
style: TextStyle(fontSize: 11, color: Color(0xFF282828)),
maxLines: 1,
),
Text(
plan.positiveRate,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 14,
color: Color(0xFFFF5963)),
maxLines: 1,
),
],
),
Row(
children: <Widget>[
Text(
'¥${plan.minPrice}-${plan.maxPrice})',
style: TextStyle(fontSize: 13, color: Color(0xFFFF5963)),
),
Text(
"销量${plan.salesCount}",
style: TextStyle(fontSize: 11, color: Color(0xFF282828)),
maxLines: 1,
)
],
)
],
),
))
],
),
);
}
getSecondLevelItem() {
Container(
margin: EdgeInsets.all(4.0),
child: Row(
children: <Widget>[
Radio(
value: 1,
groupValue: groupValue,
onChanged: (value) {
groupValue = value;
}),
Expanded(
child: Container(
margin: EdgeInsets.only(left: 8.0),
height: 50,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
plan.name,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 14,
color: Color(0xFF282828)),
maxLines: 1,
),
Row(
children: <Widget>[
Text(
'¥${plan.minPrice}-${plan.maxPrice})',
style: TextStyle(fontSize: 13, color: Color(0xFFFF5963)),
),
Text(
"指导价:¥${plan.guidePrice}",
style: TextStyle(fontSize: 11, color: Color(0xFF282828)),
maxLines: 1,
)
],
)
],
),
))
],
),
);
}
}
import 'package:flutter_common/commonModel/live/BaseModel.dart';
import 'package:flutter_common/commonModel/live/LiveData.dart';
import 'package:gm_flutter/ClueModel/server/api/ClueApi.serv.dart';
import 'package:gm_flutter/ClueModel/server/entity/PlansCompareFeed.dart';
import 'package:gm_flutter/commonModel/net/DioUtil.dart';
import 'package:gm_flutter/commonModel/rx/RxDispose.dart';
class PlansCompareFeedModel extends BaseModel {
LiveData<PlansCompareFeed> liveData = LiveData();
RxDispose rxDispose = RxDispose();
void init() {
ClueApiImpl.getInstance()
.getPlansCompareFeed(DioUtil.getInstance().getDio(), 123, 1)
.listen((event) {
if (event.error == 0) {
liveData.notifyView(event);
}
})
.addToDispose(rxDispose)
.onError((err) {});
}
@override
void dispose() {
liveData.dispost();
rxDispose.dispose();
}
}
/*
* @author zcc
* @date 2020-07-01
* 方案对比
**/
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:gm_flutter/ClueModel/page/PlansCompareFeed/PlansCompareFeedModel.dart';
import 'package:gm_flutter/ClueModel/server/entity/PlansCompareFeed.dart';
import 'package:gm_flutter/commonModel/base/BaseComponent.dart';
import 'package:gm_flutter/commonModel/base/BaseState.dart';
import 'PlansCompareFeedItemView.dart';
class PlansCompareFeedPage extends StatefulWidget {
@override
State<StatefulWidget> createState() => PlansCompareFeedState();
}
class PlansCompareFeedState extends BaseState<PlansCompareFeedPage> {
PlansCompareFeedModel _model = new PlansCompareFeedModel();
@override
void initState() {
super.initState();
_model.init();
}
@override
void dispose() {
_model.dispose();
super.dispose();
}
@override
Widget buildItem(BuildContext context) {}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("方案对比"),
),
body: Center(
child: getBody(),
),
);
}
getList(List<Plans> plans) {
return Stack(alignment: Alignment.bottomCenter, //指定未定位或部分定位widget的对齐方式
children: <Widget>[
ListView.builder(
itemCount: plans.length,
itemBuilder: (BuildContext context, int position) {
return PlansCompareFeedItemView(plans[position]);
}),
GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () {},
child: Container(
margin:
EdgeInsets.only(left: 15, right: 15, top: 7.5, bottom: 7.5),
width: double.maxFinite,
height: 40,
decoration: BoxDecoration(
color: Color(0xff51CDC7),
borderRadius: BorderRadius.circular(20)),
alignment: Alignment.center,
child: baseText("对比", 14, Colors.white, bold: true),
))
]);
}
getBody() {
return StreamBuilder(
stream: _model.liveData.stream,
initialData: PlansCompareFeed(),
builder: (c, data) {
PlansCompareFeed item = data.data;
if (item == null || item.data == null || item.data.plans == null) {
return loadingItem();
}
return getList(item.data.plans);
},
);
}
}
/*
* @author zcc
* @date 2020-07-01
* 项目说明
**/
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:gm_flutter/ClueModel/server/entity/ProjectDetailsItem.dart';
class ProjectDetailsItemView extends StatelessWidget {
Groups listData;
ProjectDetailsItemView(this.listData);
@override
Widget build(BuildContext context) {
List<Widget> tiles = [];
for (var item in listData.attrs) {
tiles.add(getItem(item));
}
var row = Row(
children: <Widget>[
Container(
padding: EdgeInsets.only(top: 8.0, bottom: 8.0, left: 20),
child: Text(
listData.name,
style: TextStyle(
color: Color(0xFF000000),
fontSize: 15.0,
),
),
),
Column(
children: tiles,
)
],
);
return Container(
margin: EdgeInsets.only(bottom: 5, left: 20),
child: row,
);
}
getItem(Attrs attrs) {
var row = Container(
margin: EdgeInsets.only(bottom: 25),
child: Row(
children: <Widget>[
Text(
attrs.attrName,
style: TextStyle(
color: Color(0xFF999999),
fontSize: 13.0,
),
),
Text(
attrs.attrValue,
style: TextStyle(
color: Color(0xFF282828),
fontSize: 14.0,
),
maxLines: 1,
),
],
),
);
return Container(
child: row,
);
}
}
/*
* @author zcc
* @date 2020-07-01
* 项目说明
**/
import 'package:flutter_common/commonModel/live/BaseModel.dart';
import 'package:flutter_common/commonModel/live/LiveData.dart';
import 'package:gm_flutter/ClueModel/server/api/ClueApi.serv.dart';
import 'package:gm_flutter/commonModel/GMBase.dart';
import 'package:gm_flutter/commonModel/rx/RxDispose.dart';
import 'package:gm_flutter/commonModel/util/PrintUtil.dart';
import '../../server/entity/ProjectDetailsItem.dart';
class ProjectDetailsModel extends BaseModel {
LiveData<ProjectDetailsItem> liveData = LiveData();
RxDispose rxDispose = RxDispose();
void init() {
ClueApiImpl.getInstance()
.getProjectDetails(DioUtil.getInstance().getDio(), 123)
.listen((event) {
print(event);
if (event.error == 0) {
liveData.notifyView(event);
}
})
.addToDispose(rxDispose)
.onError((err) {
PrintUtil.printBug(err);
});
}
@override
void dispose() {
liveData.dispost();
rxDispose.dispose();
}
}
/*
* @author zcc
* @date 2020-07-01
* 项目说明
**/
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:gm_flutter/ClueModel/page/ProjectDetails/ProjectDetailsItemView.dart';
import 'package:gm_flutter/ClueModel/page/ProjectDetails/ProjectDetailsModel.dart';
import 'package:gm_flutter/commonModel/base/BaseComponent.dart';
import 'package:gm_flutter/commonModel/base/BaseState.dart';
import '../../server/entity/ProjectDetailsItem.dart';
class ProjectDetailsPage extends StatefulWidget {
@override
State<StatefulWidget> createState() => ProjectDetailsState();
}
class ProjectDetailsState extends BaseState<ProjectDetailsPage> {
ProjectDetailsModel _model = new ProjectDetailsModel();
@override
void initState() {
super.initState();
_model.init();
}
@override
void dispose() {
_model.dispose();
super.dispose();
}
@override
Widget buildItem(BuildContext context) {}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: baseAppBar(title: "项目说明",
centerTitle: true,
backClick: (){
Navigator.pop(context);
}),
body: Center(
child: getBody(),
),
);
}
getBody() {
return StreamBuilder(
stream: _model.liveData.stream,
initialData: ProjectDetailsItem(),
builder: (c, data) {
ProjectDetailsItem item = data.data;
if (item == null || item.data == null || item.data.groups == null) {
return loadingItem();
}
return ListView.builder(
itemCount: item.data.groups.length,
itemBuilder: (BuildContext context, int position) {
return ProjectDetailsItemView(item.data.groups[position]);
});
},
);
}
}
......@@ -167,7 +167,7 @@ class LevelOneItem extends StatelessWidget {
Positioned(
left: 57,
top: 43.5,
child: FiveStarView(cards.hospital.star, 5),
child: FiveStarView(int.parse(cards.hospital.star), 5),
)
],
),
......
......@@ -10,6 +10,7 @@ import 'package:gm_flutter/ClueModel/server/entity/LevelOneFeedList.dart';
import 'package:gm_flutter/commonModel/GMBase.dart';
import 'package:gm_flutter/commonModel/bean/Pair.dart';
import 'package:gm_flutter/commonModel/rx/RxDispose.dart';
import 'package:gm_flutter/commonModel/util/PrintUtil.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart';
class LevelOneModel extends BaseModel {
......@@ -57,17 +58,19 @@ class LevelOneModel extends BaseModel {
cardsLive.notifyView(Pair(ENDLOADING, data));
});
// int index = currentIndex;
// if (clear) {
// data.clear();
// pageList = [1, 1, 1, 1];
// }
// ClueApiImpl.getInstance()
// .getLevelOneList(
// DioUtil.getInstance().getDio(), 123, list[index], pageList[index])
// .listen((event) {})
// .addToDispose(rxDispose)
// .onError((err) {});
int index = currentIndex;
if (clear) {
data.clear();
pageList = [1, 1, 1, 1];
}
ClueApiImpl.getInstance()
.getLevelOneList(
DioUtil.getInstance().getDio(), 123, list[index], pageList[index])
.listen((event) {})
.addToDispose(rxDispose)
.onError((err) {
PrintUtil.printBug(err);
});
}
int currentIndex = 0;
......@@ -96,5 +99,7 @@ class LevelOneModel extends BaseModel {
}
}
void loadMore() {}
void loadMore() {
}
}
......@@ -42,10 +42,10 @@ class LevelOneState extends BaseState<LevelOnePage>
@override
void initState() {
super.initState();
Future.delayed(Duration(seconds: 3), () {
_model.loadingLive.notifyView(false);
_model.refreshView(true);
});
// Future.delayed(Duration(seconds: 3), () {
// _model.loadingLive.notifyView(false);
// _model.refreshView(true);
// });
pageController.addListener(() {
if (screenWidth != null) {
_model.topScrollLive.notifyView(
......@@ -485,13 +485,12 @@ class LevelOneState extends BaseState<LevelOnePage>
height);
}
return Container(
color: Colors.yellow,
width: double.maxFinite,
height: height,
child: PageView.builder(
itemBuilder: (c, pageIndex) {
if (data.data.first == FAIL) {
return errorItem(() {
return errorItem(MediaQuery.of(context).size.width, height, () {
_model.refreshView(true);
});
}
......@@ -501,7 +500,7 @@ class LevelOneState extends BaseState<LevelOnePage>
}
if (data.data.second.length == 0) {
if (_model.pageList[pageIndex] == 1) {
return emptyItem();
return emptyItem(MediaQuery.of(context).size.width, height);
} else {
_refreshController.loadNoData();
}
......
/*
* @author lsy
* @date 2020/7/1
**/
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:gm_flutter/ClueModel/page/plan/PlanProgressBar.dart';
import 'package:gm_flutter/commonModel/base/BaseComponent.dart';
import 'package:gm_flutter/commonModel/util/DartUtil.dart';
class FilterView extends StatelessWidget {
final Function(int high, int low) call;
FilterView(this.call);
int min = 0;
int max = 0;
@override
Widget build(BuildContext context) {
return Container(
color: Colors.white,
height: 186,
child: Stack(
children: <Widget>[
Positioned(
bottom: 74.5,
left: 15,
child: Container(
width: MediaQuery.of(context).size.width - 30,
child: PlanProgressBar(0, 5, 0, 10,padding: 15,),
),
),
Positioned(
top: 54.5,
right: 15,
child: baseText("无限", 12, Color(0xff3FB5AF)),
),
Positioned(
top: 54.5,
left: 15,
child: baseText("¥0", 12, Color(0xff3FB5AF)),
),
Positioned(
top: 25,
left: 15,
child: baseText("价格区间:", 13, Color(0xff666666)),
),
Positioned(
bottom: 0,
child: Container(
width: MediaQuery.of(context).size.width,
height: 44.5,
child: Row(
children: <Widget>[
Expanded(
child: Container(
child: baseText("重置", 16, Color(0xff3FB5AF)),
alignment: Alignment.center,
).gestureDetector(() {
//TODO
}),
),
Expanded(
child: Container(
color: Color(0xff3FB5AF),
alignment: Alignment.center,
child: baseText("确定", 16, Colors.white),
).gestureDetector(() {
call(max, min);
}),
)
],
),
),
)
],
),
);
}
}
/*
* @author lsy
* @date 2020-01-02
**/
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:flutter_common/flutter_common.dart';
import 'package:gm_flutter/commonModel/base/BaseComponent.dart';
class PlanBarView extends StatelessWidget {
final LiveData<List> managerLive;
final Function(int showIndex) managerListener;
final ChangeNotifier notifier;
int showIndex = -1;
List normalData = ["全部项目", "智能排序", "筛选"];
PlanBarView(this.managerLive, this.managerListener, this.notifier) {
if (!notifier?.hasListeners) {
notifier?.addListener(() {
showIndex = -1;
managerListener(-1);
managerLive.notifyView(managerLive.data ?? normalData);
});
}
}
@override
Widget build(BuildContext context) {
return managerTop(context);
}
managerTop(BuildContext context) {
return Container(
width: double.maxFinite,
height: 45,
child: StreamBuilder<List>(
stream: managerLive.stream,
initialData: managerLive.data ?? normalData,
builder: (c, data) {
if (data.data.length != 3) {
return Container();
}
return Row(
children: <Widget>[
item(data.data[0], 0),
item(data.data[1], 1),
item(data.data[2], 2),
],
);
},
));
}
Widget item(String text, int index) {
return Expanded(
child: GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () {
if (index == showIndex) {
showIndex = -1;
} else {
showIndex = index;
}
managerListener(showIndex);
managerLive.notifyView(managerLive.data ?? normalData);
},
child: Container(
alignment: Alignment.center,
child: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
baseText(text, 14,
index == showIndex ? Color(0xff3FB5AF) : Color(0xff666666)),
Container(
width: 10,
height: 10,
padding: EdgeInsets.only(top: 3),
alignment: Alignment.topCenter,
child: Container(
width: 6,
height: 3.5,
child: index == showIndex
? Image.asset("assets/top_arrow.png")
: Image.asset("assets/bottom_arrow.png"),
),
)
],
),
),
),
);
}
}
/*
* @author lsy
* @date 2020/7/1
**/
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:gm_flutter/ClueModel/server/entity/PlanFeedBean.dart';
import 'package:gm_flutter/commonModel/base/BaseComponent.dart';
class PlanItem extends StatelessWidget {
final Plans plans;
PlanItem(this.plans);
@override
Widget build(BuildContext context) {
return Container(
margin: EdgeInsets.only(top: 10, left: 10, right: 10),
child: Container(
height: 90,
decoration: BoxDecoration(
color: Colors.white, borderRadius: BorderRadius.circular(4)),
child: Stack(
children: <Widget>[
Positioned(
top: 10,
left: 10,
child: Container(
width: 70,
height: 70,
child: ClipRRect(
borderRadius: BorderRadius.circular(4),
child: CachedNetworkImage(
imageUrl: "",
fit: BoxFit.cover,
),
),
),
),
Positioned(
left: 92,
top: 14,
child: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
baseText(plans.name, 14, Color(0xff282828)),
Container(
margin: EdgeInsets.only(left: 4),
child: Container(
width: 28,
height: 15,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(2),
color: Color(0xffF0F9F7)),
alignment: Alignment.center,
child: baseText("??", 11, Color(0xff3FB5AF)),
),
)
],
),
),
Positioned(
top: 13,
right: 10,
child: Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
baseText("好评率", 11, Color(0xff282828)),
Container(
width: 4,
),
baseText(plans.positiveRate, 14, Color(0xffFF5963))
],
),
),
Positioned(
bottom: 14,
right: 10,
child: baseText("销量${plans.salesCount}", 11, Color(0xff282828)),
),
Positioned(
left: 91,
bottom: 14,
child: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
baseText("¥", 10, Color(0xffFF5963)),
baseText("${plans.minPrice}-${plans.maxPrice}", 13,
Color(0xffFF5963)),
],
),
),
Positioned(
left: 92,
top: 36,
child: baseText("TODO", 11, Color(0xff999999)),
)
],
),
),
);
}
}
/*
* @author lsy
* @date 2020/6/30
**/
import 'package:flutter/foundation.dart';
import 'package:flutter_common/commonModel/live/BaseModel.dart';
import 'package:flutter_common/commonModel/live/LiveData.dart';
import 'package:flutter_common/commonModel/toast/NativeToast.dart';
import 'package:gm_flutter/ClueModel/page/plan/PlanTest.dart';
import 'package:gm_flutter/ClueModel/server/api/ClueApi.serv.dart';
import 'package:gm_flutter/ClueModel/server/entity/PlanBean.dart';
import 'package:gm_flutter/ClueModel/server/entity/PlanFeedBean.dart';
import 'package:gm_flutter/commonModel/GMBase.dart';
import 'package:gm_flutter/commonModel/bean/Pair.dart';
import 'package:gm_flutter/commonModel/rx/RxDispose.dart';
import 'package:gm_flutter/commonModel/util/PrintUtil.dart';
class PlanModel extends BaseModel {
LiveData<List> managerLive = new LiveData();
LiveData<List<double>> posLive = new LiveData();
LiveData<List<double>> backLive = new LiveData();
LiveData<List<Ranks>> picLive = LiveData();
LiveData<int> stateLive = LiveData();
double menuBottom;
int menuIndex = -1;
bool needChangBack = true;
LiveData<Pair<int, List<Plans>>> feedsLive = LiveData();
List<Plans> feedDatas = [];
List<Tags> projectData = [];
List<Orders> sortList = [];
RxDispose rxDispose = RxDispose();
String tag_id = "";
String order_by = "";
String current_city_id = "";
String min_price = "";
String max_price = "";
String rank_type = "";
int page = 1;
int sortPos = 0;
void init() {
ClueApiImpl.getInstance()
.getPlan(DioUtil.getInstance().getDio())
.listen((event) {
if (event.error == 0) {
projectData = event.data.tags;
sortList = event.data.orders;
picLive.notifyView(event.data.ranks);
stateLive.notifyView(ENDLOADING);
refreshFeed(true);
} else {
stateLive.notifyView(FAIL);
NativeToast.showNativeToast(event.message);
}
})
.addToDispose(rxDispose)
.onError((err) {
PrintUtil.printBug(err);
stateLive.notifyView(FAIL);
});
}
void projectClick(String id) {
if (tag_id == id) {
return;
}
tag_id = id;
feedsLive.notifyView(Pair(LOADING, null));
refreshFeed(true);
}
void refreshFeed(bool clear) {
if (clear) {
feedDatas.clear();
}
ClueApiImpl.getInstance()
.getPlanFeed(DioUtil.getInstance().getDio(), tag_id, order_by,
current_city_id, min_price, max_price, rank_type, page)
.listen((event) {
if (event.error == 0) {
if (event.data.plans == null || event.data.plans.isEmpty) {
feedsLive.notifyView(Pair(ENDLOADING, []));
} else {
feedDatas.addAll(event.data.plans);
feedsLive.notifyView(Pair(ENDLOADING, feedDatas));
}
} else {
NativeToast.showNativeToast(event.message);
feedsLive.notifyView(Pair(FAIL, null));
}
})
.addToDispose(rxDispose)
.onError((err) {
PrintUtil.printBug(err);
feedsLive.notifyView(Pair(FAIL, null));
});
}
@override
void dispose() {
stateLive.dispost();
picLive.dispost();
rxDispose.dispose();
managerLive.dispost();
posLive.dispost();
backLive.dispost();
feedsLive.dispost();
}
void backProgress(double pro, int index) {
if (needChangBack || menuIndex == -1) {
backLive.notifyView([0.0, menuBottom, pro]);
}
}
void loadMore() {
page++;
refreshFeed(false);
}
void sortClick(int index) {
if (index == sortPos) {
return;
}
sortPos = index;
order_by = sortList[index].id.toString();
refreshFeed(true);
}
void filterClick(int max, int min) {
if (max_price == max.toString() && min_price == min.toString()) {
return;
}
max_price = max.toString();
min_price = min.toString();
refreshFeed(true);
}
}
/*
* @author lsy
* @date 2020/6/30
**/
import 'dart:io';
import 'dart:math';
import 'dart:ui';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:gm_flutter/ClueModel/page/plan/FilterView.dart';
import 'package:gm_flutter/ClueModel/page/plan/PlanBar.dart';
import 'package:gm_flutter/ClueModel/page/plan/PlanItem.dart';
import 'package:gm_flutter/ClueModel/page/plan/SortView.dart';
import 'package:gm_flutter/ClueModel/server/entity/PlanBean.dart';
import 'package:gm_flutter/ClueModel/server/entity/PlanFeedBean.dart';
import 'package:gm_flutter/ClueModel/util/PosUtil.dart';
import 'package:gm_flutter/commonModel/base/BaseComponent.dart';
import 'package:gm_flutter/commonModel/base/BaseState.dart';
import 'package:gm_flutter/commonModel/bean/Pair.dart';
import 'package:gm_flutter/commonModel/popMenu/BaseMenuListener.dart';
import 'package:gm_flutter/commonModel/popMenu/BasePopMenu.dart';
import 'package:gm_flutter/commonModel/util/DartUtil.dart';
import 'package:gm_flutter/commonModel/util/WidgetUtil.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart';
import 'PlanModel.dart';
import 'ProjectView.dart';
class PlanPage extends StatefulWidget {
@override
State<StatefulWidget> createState() => PlanState();
}
class PlanState extends BaseState<PlanPage> {
PlanModel _model = PlanModel();
TextEditingController _editingController = TextEditingController();
FocusNode focusNode = FocusNode();
RefreshController refreshController = RefreshController();
List<Widget> planList = List();
BaseMenuListener projectMenuListener = BaseMenuListener();
BaseMenuListener sortMenuListener = BaseMenuListener();
BaseMenuListener filterMenuListener = BaseMenuListener();
ChangeNotifier hideAllMenuListener = new ChangeNotifier();
GlobalKey globalKey = GlobalKey();
PlanBarView planBarView;
@override
void initState() {
super.initState();
_model.init();
planBarView =
PlanBarView(_model.managerLive, clickIndex, hideAllMenuListener);
planList.add(towPic());
planList.add(planBar());
planList.add(pages());
}
@override
void dispose() {
hideAllMenuListener.dispose();
projectMenuListener.dispose();
sortMenuListener.dispose();
filterMenuListener.dispose();
_model.dispose();
focusNode.dispose();
refreshController.dispose();
_editingController.dispose();
super.dispose();
}
@override
Widget buildItem(BuildContext context) {
return Scaffold(
body: MediaQuery.removePadding(
removeTop: true,
context: context,
child: SafeArea(
top: false,
child: Stack(
children: <Widget>[
Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
child: Column(
children: <Widget>[
head(),
Expanded(
child: Stack(
children: <Widget>[
Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height - 86,
child: child(),
),
StreamBuilder<List<double>>(
stream: _model.backLive.stream,
initialData: [0.0, 0.0, 0.0],
builder: (c, data) {
return Positioned(
left: 0.0,
top: 0.0,
child: Visibility(
visible: data.data[2] > 0.1,
child: Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
child: Column(
children: <Widget>[
Container(
height: data.data[1] - 45,
color: Colors.transparent,
),
Container(
height: 45,
child: Row(
children: <Widget>[
Expanded(
child: Container()
.gestureDetector(() {
clickIndexOther(0);
}),
),
Expanded(
child: Container()
.gestureDetector(() {
clickIndexOther(1);
}),
),
Expanded(
child: Container()
.gestureDetector(() {
clickIndexOther(2);
}),
),
],
),
),
Expanded(
child: Container(
color: Color.fromARGB(
(data.data[2] * 153).toInt(),
0,
0,
0),
).gestureDetector(() {
hideAllMenuListener
.notifyListeners();
}),
)
],
),
),
),
);
}),
StreamBuilder<List<double>>(
stream: _model.posLive.stream,
initialData: [0.0, 0.0],
builder: (c, data) {
return BasePopMenu(
leftPos: data.data[0],
topPos: data.data[1],
width: MediaQuery.of(context).size.width,
maxHeight: 450,
listener: projectMenuListener,
child: ProjectView(_model.projectData, (id) {
clickIndexOther(0);
_model.projectClick(id);
}),
proListener: (pro) {
_model.backProgress(pro, 0);
},
);
}),
StreamBuilder<List<double>>(
stream: _model.posLive.stream,
initialData: [0.0, 0.0],
builder: (c, data) {
return BasePopMenu(
leftPos: data.data[0],
topPos: data.data[1],
width: MediaQuery.of(context).size.width,
maxHeight: 272,
listener: sortMenuListener,
child: SortView(_model.sortList, _model.sortPos,
(index) {
clickIndexOther(1);
_model.sortClick(index);
}),
proListener: (pro) {
_model.backProgress(pro, 1);
},
);
},
),
StreamBuilder<List<double>>(
stream: _model.posLive.stream,
initialData: [0.0, 0.0],
builder: (c, data) {
return BasePopMenu(
leftPos: data.data[0],
topPos: data.data[1],
width: MediaQuery.of(context).size.width,
maxHeight: 186,
listener: filterMenuListener,
child: FilterView((max, min) {
clickIndexOther(2);
_model.filterClick(max, min);
}),
proListener: (pro) {
_model.backProgress(pro, 2);
},
);
}),
],
),
)
],
),
),
StreamBuilder(
stream: _model.stateLive.stream,
initialData: _model.stateLive.data ?? LOADING,
builder: (c, data) {
if (data.data == LOADING) {
return Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
color: Colors.white,
child: loadingItem(),
);
} else if (data.data == FAIL) {
return errorItem(
MediaQuery.of(context).size.width,
MediaQuery.of(context).size.height,
() {
_model.stateLive.notifyView(LOADING);
_model.init();
},
);
} else {
return Container(
width: 0,
height: 0,
);
}
},
)
],
),
),
));
}
Widget head() {
return Container(
height: 86,
child: Container(
margin: EdgeInsets.only(top: 48, left: 15, right: 15),
width: double.maxFinite,
height: 32,
child: TextField(
cursorColor: Color(0xff20BDBB),
style: TextStyle(fontSize: 12, color: Color(0xff999999)),
decoration: InputDecoration(
isDense: true,
prefixIcon: Container(
child: Container(
margin: EdgeInsets.only(left: 12, right: 6),
width: 13,
height: 13,
child: Image.asset("assets/search.png"),
),
),
prefixIconConstraints:
BoxConstraints(maxWidth: 31, minWidth: 31, maxHeight: 13),
suffixIconConstraints:
BoxConstraints(maxWidth: 56.5, maxHeight: 32),
suffixIcon: Container(
decoration: BoxDecoration(
color: Color(0xff51CDC7),
borderRadius: BorderRadius.circular(16),
),
alignment: Alignment.center,
child: baseText("搜索", 14, Colors.white),
).gestureDetector(() {
//TODO
}),
contentPadding:
const EdgeInsets.symmetric(horizontal: 12.0, vertical: 10.0),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(19.5),
borderSide: BorderSide.none),
filled: true,
fillColor: Color(0xffF7F6FA),
hintStyle: TextStyle(fontSize: 12, color: Color(0xff999999)),
hintText: "切开双眼皮"),
maxLines: 1,
enableInteractiveSelection: true,
focusNode: focusNode,
autocorrect: false,
autofocus: false,
textInputAction: Platform.isAndroid
? TextInputAction.newline
: TextInputAction.send,
controller: _editingController,
minLines: null,
onEditingComplete: () {},
onSubmitted: (text) {},
),
),
);
}
Widget child() {
return baseRefreshView(
refreshController,
() {
_model.refreshFeed(true);
},
Container(
width: 0,
height: 0,
),
SliverList(
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return planList[index];
},
childCount: planList.length,
),
),
onLoading: () {
_model.loadMore();
},
pullUp: true);
}
Widget towPic() {
return Container(
height: 90,
margin: EdgeInsets.only(left: 15, right: 15, top: 15, bottom: 10),
child: Row(
children: <Widget>[
Expanded(
child: Container(
child: StreamBuilder<List<Ranks>>(
stream: _model.picLive.stream,
initialData: _model.picLive.data ?? null,
builder: (c, data) {
return ClipRRect(
borderRadius: BorderRadius.circular(3),
child: CachedNetworkImage(
imageUrl:
data.data == null ? "" : data.data[0].icon ?? "",
fit: BoxFit.cover,
)).gestureDetector(() {
//TODO
});
},
),
),
),
Container(
width: 10,
),
Expanded(
child: Container(
child: StreamBuilder<List<Ranks>>(
stream: _model.picLive.stream,
initialData: _model.picLive.data ?? null,
builder: (c, data) {
return ClipRRect(
borderRadius: BorderRadius.circular(3),
child: CachedNetworkImage(
imageUrl:
data.data == null ? "" : data.data[1].icon ?? "",
fit: BoxFit.cover,
)).gestureDetector(() {
//TODO
});
},
),
),
)
],
),
);
}
Widget planBar() {
return Container(
key: globalKey,
child: planBarView,
);
}
void clickIndexOther(int index) {
if (index == planBarView.showIndex) {
planBarView.showIndex = -1;
} else {
planBarView.showIndex = index;
}
_model.managerLive
.notifyView(_model.managerLive.data ?? planBarView.normalData);
clickIndex(planBarView.showIndex);
}
void clickIndex(int index) {
double bottom =
WidgetUtil.buttonLeftMenuPosition(globalKey.currentContext).top - 86;
_model.menuBottom = bottom;
if (_model.menuIndex == index || _model.menuIndex == -1) {
_model.needChangBack = true;
} else {
_model.needChangBack = false;
}
_model.menuIndex = index;
_model.posLive.notifyView([0.0, bottom]);
if (index == -1) {
projectMenuListener.hide();
sortMenuListener.hide();
filterMenuListener.hide();
} else if (index == 0) {
projectMenuListener.show();
sortMenuListener.hide();
filterMenuListener.hide();
} else if (index == 1) {
projectMenuListener.hide();
sortMenuListener.show();
filterMenuListener.hide();
} else if (index == 2) {
projectMenuListener.hide();
sortMenuListener.hide();
filterMenuListener.show();
}
}
Widget pages() {
return StreamBuilder<Pair<int, List<Plans>>>(
stream: _model.feedsLive.stream,
initialData: _model.feedsLive.data ?? Pair(LOADING, null),
builder: (c, data) {
double height = MediaQuery.of(context).size.height - 131;
if (_model.feedDatas != null && _model.feedDatas.length > 0) {
height = max(_model.feedDatas.length * 100.0, height);
}
return Container(
width: double.maxFinite,
height: height,
child: ListView.builder(
physics: NeverScrollableScrollPhysics(),
itemBuilder: (c, index) {
if (data.data.first == FAIL) {
return errorItem(MediaQuery.of(context).size.width, height,
() {
_model.refreshFeed(true);
});
}
if (data.data.first == LOADING) {
return loadingItem();
}
if (data.data.second.length == 0) {
if (_model.page == 1) {
return emptyItem(MediaQuery.of(context).size.width, height);
} else {
refreshController.loadNoData();
}
} else {
refreshController.loadComplete();
}
return PlanItem(_model.feedDatas[index]);
},
itemCount: _model.feedDatas.length,
));
},
);
}
}
/*
* @author lsy
* @date 2020/7/1
**/
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:gm_flutter/commonModel/base/BaseComponent.dart';
class PlanProgressBar extends StatefulWidget {
int low;
int high;
int maxlow;
int maxHigh;
int padding;
PlanProgressBar(this.low, this.high, this.maxlow, this.maxHigh,
{this.padding});
@override
State<StatefulWidget> createState() => PlanProgressBarState();
}
class PlanProgressBarState extends State<PlanProgressBar> {
double distance;
double leftStarPosPercent;
double leftPosTempPercent;
double rightStarPosPercent;
double rightPosTempPercent;
double leftDowPos;
double rightDowPos;
double scrollDistance;
double leftPos;
double textLeft = -1;
bool isLeftMove = true;
@override
void initState() {
super.initState();
distance = widget.maxHigh - widget.maxlow - 0.0;
leftStarPosPercent = (widget.low / distance);
leftPosTempPercent = leftStarPosPercent;
rightStarPosPercent = (widget.high / distance);
rightPosTempPercent = rightStarPosPercent;
}
@override
Widget build(BuildContext context) {
double totle = MediaQuery.of(context).size.width - widget.padding * 2 - 8;
scrollDistance = 0.05;
double textL = textLeft * totle - 67.5 / 2 + 9;
if (textL < 0) {
textL = 0;
} else if (textL + 67.5 > totle) {
textL = totle - 67.5;
}
return Container(
width: double.maxFinite,
height: 65,
child: Stack(
children: <Widget>[
Positioned(
bottom: 7.5,
left: 4,
child: Container(
width: totle,
height: 4,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(50),
color: Color(0xffD5D5D5)),
),
),
Positioned(
left: leftPosTempPercent * totle + 5,
bottom: 7.5,
child: Container(
height: 4,
width: (rightPosTempPercent - leftPosTempPercent) * totle,
color: Color(0xff51CDC7),
),
),
Positioned(
left: textL,
bottom: 23,
child: Visibility(
visible: textLeft >= 0,
child: Container(
width: 67.5,
height: 42,
color: Color(0x66000000),
alignment: Alignment.center,
child: Column(
children: <Widget>[
baseText(
"${(widget.maxlow + (isLeftMove?leftPosTempPercent:rightPosTempPercent+0.03) * distance).toInt()}",
13,
Colors.white)
],
),
),
),
),
Positioned(
bottom: 0,
left: leftPosTempPercent * totle,
child: Listener(
onPointerDown: (p) {
leftDowPos = p.localPosition.dx;
isLeftMove = true;
},
onPointerMove: (p) {
var d = p.localPosition.dx - leftDowPos;
leftPosTempPercent = leftStarPosPercent + (d / totle);
if (leftPosTempPercent < 0.0) {
leftPosTempPercent = 0;
} else if (leftPosTempPercent >
rightPosTempPercent - scrollDistance) {
leftPosTempPercent = rightPosTempPercent - scrollDistance;
}
textLeft = leftPosTempPercent;
setState(() {});
},
onPointerUp: (p) {
textLeft = -1;
leftStarPosPercent = leftPosTempPercent;
setState(() {});
},
child: Container(
width: 19,
height: 19,
alignment: Alignment.centerLeft,
child: Image.asset(
"assets/progress_inner.png",
),
),
)),
Positioned(
bottom: 0,
left: rightPosTempPercent * totle,
child: Listener(
onPointerDown: (p) {
rightDowPos = p.localPosition.dx;
isLeftMove = false;
},
onPointerMove: (p) {
var d = p.localPosition.dx - rightDowPos;
rightPosTempPercent = rightStarPosPercent + (d / totle);
if (rightPosTempPercent <
leftPosTempPercent + scrollDistance) {
rightPosTempPercent = leftPosTempPercent + scrollDistance;
} else if (rightPosTempPercent > 1.0 - 0.03) {
rightPosTempPercent = 1.0 - 0.03;
}
textLeft = rightPosTempPercent;
setState(() {});
},
onPointerUp: (p) {
textLeft = -1;
rightStarPosPercent = rightPosTempPercent;
setState(() {});
},
child: Container(
width: 19,
height: 19,
alignment: Alignment.centerLeft,
child: Image.asset(
"assets/progress_inner.png",
),
),
)),
],
),
);
}
}
/*
* @author lsy
* @date 2020/7/1
**/
const PLAN_TEST_JSON = """
{
"error": 0,
"message": "",
"extra": null,
"error_extra": null,
"user_type": {},
"data": {
"ranks": [
{
"name": "方案好评榜",
"gm_url": "xxxxx",
"icon": "https://heras.igengmei.com/2020/02/16/9327baec41"
},
{
"name": "热门榜",
"gm_url": "xxxxx",
"icon": "https://heras.igengmei.com/2020/02/16/9327baec41"
}
],
"areas": [
{
"is_located": true,
"name": "中国",
"groups": [
{
"is_hot": true,
"initial": "热",
"cities": [
{
"city_name": "beijing",
"id": 328,
"name": "北京"
},
{
"city_name": "shanghai",
"id": 592,
"name": "上海"
},
{
"city_name": "guangzhou",
"id": 409,
"name": "广州"
},
{
"city_name": "shenzhen",
"id": 604,
"name": "深圳"
},
{
"city_name": "chengdu",
"id": 352,
"name": "成都"
},
{
"city_name": "chongqing",
"id": 359,
"name": "重庆"
},
{
"city_name": "wuhan",
"id": 662,
"name": "武汉"
},
{
"city_name": "changsha",
"id": 343,
"name": "长沙"
},
{
"city_name": "xian",
"id": 675,
"name": "西安"
},
{
"city_name": "zhengzhou",
"id": 744,
"name": "郑州"
},
{
"city_name": "hangzhou",
"id": 425,
"name": "杭州"
},
{
"city_name": "nanjing",
"id": 542,
"name": "南京"
}
],
"title": "热门城市"
},
{
"initial": "*",
"cities": [
{
"city_name": "worldwide",
"id": "worldwide",
"name": "全部城市"
}
],
"title": "*"
},
{
"is_hot": false,
"initial": "A",
"cities": [
{
"city_name": "ankang",
"id": 304,
"name": "安康"
},
{
"city_name": "anqing",
"id": 306,
"name": "安庆"
}
],
"title": "A"
},
{
"is_hot": false,
"initial": "B",
"cities": [
{
"city_name": "baoding",
"id": 317,
"name": "保定"
},
{
"city_name": "baoji",
"id": 318,
"name": "宝鸡"
},
{
"city_name": "baotou",
"id": 321,
"name": "包头"
},
{
"city_name": "beijing",
"id": 328,
"name": "北京"
},
{
"city_name": "bengbu",
"id": 329,
"name": "蚌埠"
},
{
"city_name": "bijie",
"id": 331,
"name": "毕节"
},
{
"city_name": "bozhou",
"id": 335,
"name": "亳州"
}
],
"title": "B"
},
{
"is_hot": false,
"initial": "C",
"cities": [
{
"city_name": "cangzhou",
"id": 336,
"name": "沧州"
},
{
"city_name": "changchun",
"id": 337,
"name": "长春"
},
{
"city_name": "changsha",
"id": 343,
"name": "长沙"
},
{
"city_name": "changzhou",
"id": 347,
"name": "常州"
},
{
"city_name": "chengde",
"id": 351,
"name": "承德"
},
{
"city_name": "chengdu",
"id": 352,
"name": "成都"
},
{
"city_name": "chenzhou",
"id": 355,
"name": "郴州"
},
{
"city_name": "chongqing",
"id": 359,
"name": "重庆"
},
{
"city_name": "chuxiong",
"id": 361,
"name": "楚雄"
}
],
"title": "C"
},
{
"is_hot": false,
"initial": "D",
"cities": [
{
"city_name": "dali",
"id": 364,
"name": "大理"
},
{
"city_name": "dalian",
"id": 365,
"name": "大连"
},
{
"city_name": "dandong",
"id": 366,
"name": "丹东"
},
{
"city_name": "daqing",
"id": 369,
"name": "大庆"
},
{
"city_name": "datong",
"id": 370,
"name": "大同"
},
{
"city_name": "dazhou",
"id": 373,
"name": "达州"
},
{
"city_name": "deyang",
"id": 376,
"name": "德阳"
},
{
"city_name": "dongguan",
"id": 382,
"name": "东莞"
},
{
"city_name": "dongyang",
"id": 384,
"name": "东阳"
},
{
"city_name": "dongying",
"id": 385,
"name": "东营"
}
],
"title": "D"
},
{
"is_hot": false,
"initial": "E",
"cities": [
{
"city_name": "enshi",
"id": 387,
"name": "恩施"
}
],
"title": "E"
},
{
"is_hot": false,
"initial": "F",
"cities": [
{
"city_name": "foshan",
"id": 395,
"name": "佛山"
},
{
"city_name": "fuyang",
"id": 399,
"name": "阜阳"
},
{
"city_name": "fuzhou",
"id": 400,
"name": "福州"
}
],
"title": "F"
},
{
"is_hot": false,
"initial": "G",
"cities": [
{
"city_name": "ganzhou",
"id": 403,
"name": "赣州"
},
{
"city_name": "guangzhou",
"id": 409,
"name": "广州"
},
{
"city_name": "guilin",
"id": 411,
"name": "桂林"
},
{
"city_name": "guiyang",
"id": 412,
"name": "贵阳"
}
],
"title": "G"
},
{
"is_hot": false,
"initial": "H",
"cities": [
{
"city_name": "haerbin",
"id": 415,
"name": "哈尔滨"
},
{
"city_name": "haikou",
"id": 419,
"name": "海口"
},
{
"city_name": "handan",
"id": 423,
"name": "邯郸"
},
{
"city_name": "hangzhou",
"id": 425,
"name": "杭州"
},
{
"city_name": "hefei",
"id": 430,
"name": "合肥"
},
{
"city_name": "hengshui",
"id": 434,
"name": "衡水"
},
{
"city_name": "hengyang",
"id": 435,
"name": "衡阳"
},
{
"city_name": "heyuan",
"id": 437,
"name": "河源"
},
{
"city_name": "huaian",
"id": 441,
"name": "淮安"
},
{
"city_name": "huaibei",
"id": 442,
"name": "淮北"
},
{
"city_name": "huangshan",
"id": 449,
"name": "黄山"
},
{
"city_name": "huangshi",
"id": 450,
"name": "黄石"
},
{
"city_name": "huhehaote",
"id": 451,
"name": "呼和浩特"
},
{
"city_name": "huizhou",
"id": 452,
"name": "惠州"
},
{
"city_name": "huludao",
"id": 453,
"name": "葫芦岛"
},
{
"city_name": "huzhou",
"id": 455,
"name": "湖州"
}
],
"title": "H"
},
{
"is_hot": false,
"initial": "J",
"cities": [
{
"city_name": "jiamusi",
"id": 457,
"name": "佳木斯"
},
{
"city_name": "jian",
"id": 458,
"name": "吉安"
},
{
"city_name": "jiangmen",
"id": 460,
"name": "江门"
},
{
"city_name": "jiaozuo",
"id": 462,
"name": "焦作"
},
{
"city_name": "jiaxing",
"id": 463,
"name": "嘉兴"
},
{
"city_name": "jilin1",
"id": 467,
"name": "吉林"
},
{
"city_name": "jinan",
"id": 468,
"name": "济南"
},
{
"city_name": "jingzhou",
"id": 474,
"name": "荆州"
},
{
"city_name": "jinhua",
"id": 475,
"name": "金华"
},
{
"city_name": "jining",
"id": 476,
"name": "济宁"
},
{
"city_name": "jinzhong",
"id": 479,
"name": "晋中"
},
{
"city_name": "jinzhou",
"id": 480,
"name": "锦州"
}
],
"title": "J"
},
{
"is_hot": false,
"initial": "K",
"cities": [
{
"city_name": "kunming",
"id": 493,
"name": "昆明"
}
],
"title": "K"
},
{
"is_hot": false,
"initial": "L",
"cities": [
{
"city_name": "langfang",
"id": 497,
"name": "廊坊"
},
{
"city_name": "lanzhou",
"id": 498,
"name": "兰州"
},
{
"city_name": "lasa",
"id": 499,
"name": "拉萨"
},
{
"city_name": "leshan",
"id": 501,
"name": "乐山"
},
{
"city_name": "lianyungang",
"id": 504,
"name": "连云港"
},
{
"city_name": "linyi",
"id": 514,
"name": "临沂"
},
{
"city_name": "liupanshui",
"id": 518,
"name": "六盘水"
},
{
"city_name": "liuzhou",
"id": 519,
"name": "柳州"
},
{
"city_name": "luohe",
"id": 524,
"name": "漯河"
},
{
"city_name": "luoyang",
"id": 525,
"name": "洛阳"
},
{
"city_name": "luzhou",
"id": 526,
"name": "泸州"
}
],
"title": "L"
},
{
"is_hot": false,
"initial": "M",
"cities": [
{
"city_name": "maoming",
"id": 529,
"name": "茂名"
},
{
"city_name": "meishan",
"id": 530,
"name": "眉山"
},
{
"city_name": "mianyang",
"id": 533,
"name": "绵阳"
}
],
"title": "M"
},
{
"is_hot": false,
"initial": "N",
"cities": [
{
"city_name": "nanchang",
"id": 538,
"name": "南昌"
},
{
"city_name": "nanchong",
"id": 539,
"name": "南充"
},
{
"city_name": "nanjing",
"id": 542,
"name": "南京"
},
{
"city_name": "nanning",
"id": 543,
"name": "南宁"
},
{
"city_name": "nantong",
"id": 545,
"name": "南通"
},
{
"city_name": "nanyang",
"id": 547,
"name": "南阳"
},
{
"city_name": "neijiang",
"id": 549,
"name": "内江"
},
{
"city_name": "ningbo",
"id": 550,
"name": "宁波"
}
],
"title": "N"
},
{
"is_hot": false,
"initial": "P",
"cities": [
{
"city_name": "panzhihua",
"id": 555,
"name": "攀枝花"
},
{
"city_name": "putian",
"id": 564,
"name": "莆田"
},
{
"city_name": "puyang",
"id": 565,
"name": "濮阳"
}
],
"title": "P"
},
{
"is_hot": false,
"initial": "Q",
"cities": [
{
"city_name": "qingdao",
"id": 572,
"name": "青岛"
},
{
"city_name": "qingyuan",
"id": 575,
"name": "清远"
},
{
"city_name": "qinhuangdao",
"id": 576,
"name": "秦皇岛"
},
{
"city_name": "qiqihaer",
"id": 580,
"name": "齐齐哈尔"
},
{
"city_name": "quanzhou",
"id": 582,
"name": "泉州"
},
{
"city_name": "qujing",
"id": 583,
"name": "曲靖"
}
],
"title": "Q"
},
{
"is_hot": false,
"initial": "R",
"cities": [
{
"city_name": "rizhao",
"id": 586,
"name": "日照"
}
],
"title": "R"
},
{
"is_hot": false,
"initial": "S",
"cities": [
{
"city_name": "sanya",
"id": 591,
"name": "三亚"
},
{
"city_name": "shanghai",
"id": 592,
"name": "上海"
},
{
"city_name": "shangqiu",
"id": 594,
"name": "商丘"
},
{
"city_name": "shangrao",
"id": 595,
"name": "上饶"
},
{
"city_name": "shantou",
"id": 597,
"name": "汕头"
},
{
"city_name": "shaoguan",
"id": 599,
"name": "韶关"
},
{
"city_name": "shaoxing",
"id": 600,
"name": "绍兴"
},
{
"city_name": "shaoyang",
"id": 601,
"name": "邵阳"
},
{
"city_name": "shengzhou",
"id": 7401,
"name": "嵊州"
},
{
"city_name": "shenyang",
"id": 603,
"name": "沈阳"
},
{
"city_name": "shenzhen",
"id": 604,
"name": "深圳"
},
{
"city_name": "shijiazhuang",
"id": 606,
"name": "石家庄"
},
{
"city_name": "suining",
"id": 620,
"name": "遂宁"
},
{
"city_name": "suizhou",
"id": 621,
"name": "随州"
},
{
"city_name": "suzhou",
"id": 623,
"name": "苏州"
}
],
"title": "S"
},
{
"is_hot": false,
"initial": "T",
"cities": [
{
"city_name": "taian",
"id": 626,
"name": "泰安"
},
{
"city_name": "taiyuan",
"id": 631,
"name": "太原"
},
{
"city_name": "taizhou",
"id": 633,
"name": "泰州"
},
{
"city_name": "taizhou1",
"id": 634,
"name": "台州"
},
{
"city_name": "tangshan",
"id": 636,
"name": "唐山"
},
{
"city_name": "tianjin",
"id": 638,
"name": "天津"
},
{
"city_name": "tongren",
"id": 648,
"name": "铜仁"
}
],
"title": "T"
},
{
"is_hot": false,
"initial": "W",
"cities": [
{
"city_name": "weifang",
"id": 655,
"name": "潍坊"
},
{
"city_name": "weihai",
"id": 656,
"name": "威海"
},
{
"city_name": "weinan",
"id": 657,
"name": "渭南"
},
{
"city_name": "wenzhou",
"id": 660,
"name": "温州"
},
{
"city_name": "wuhan",
"id": 662,
"name": "武汉"
},
{
"city_name": "wuhu",
"id": 663,
"name": "芜湖"
},
{
"city_name": "wulumuqi",
"id": 666,
"name": "乌鲁木齐"
},
{
"city_name": "wuwei",
"id": 669,
"name": "武威"
},
{
"city_name": "wuxi",
"id": 670,
"name": "无锡"
}
],
"title": "W"
},
{
"is_hot": false,
"initial": "X",
"cities": [
{
"city_name": "xiamen",
"id": 674,
"name": "厦门"
},
{
"city_name": "xian",
"id": 675,
"name": "西安"
},
{
"city_name": "xiangtan",
"id": 678,
"name": "湘潭"
},
{
"city_name": "xiangyang",
"id": 676,
"name": "襄阳"
},
{
"city_name": "xianyang",
"id": 682,
"name": "咸阳"
},
{
"city_name": "xingtai",
"id": 686,
"name": "邢台"
},
{
"city_name": "xining",
"id": 687,
"name": "西宁"
},
{
"city_name": "xinxiang",
"id": 689,
"name": "新乡"
},
{
"city_name": "xishuangbanna",
"id": 695,
"name": "西双版纳"
},
{
"city_name": "xuzhou",
"id": 699,
"name": "徐州"
}
],
"title": "X"
},
{
"is_hot": false,
"initial": "Y",
"cities": [
{
"city_name": "yancheng",
"id": 703,
"name": "盐城"
},
{
"city_name": "yangzhou",
"id": 706,
"name": "扬州"
},
{
"city_name": "yantai",
"id": 709,
"name": "烟台"
},
{
"city_name": "yibin",
"id": 710,
"name": "宜宾"
},
{
"city_name": "yichang",
"id": 711,
"name": "宜昌"
},
{
"city_name": "yinchuan",
"id": 716,
"name": "银川"
},
{
"city_name": "yingtan",
"id": 718,
"name": "鹰潭"
},
{
"city_name": "yiwu",
"id": 297,
"name": "义乌"
},
{
"city_name": "yiyang",
"id": 719,
"name": "益阳"
},
{
"city_name": "yuncheng",
"id": 727,
"name": "运城"
},
{
"city_name": "yuxi",
"id": 732,
"name": "玉溪"
}
],
"title": "Y"
},
{
"is_hot": false,
"initial": "Z",
"cities": [
{
"city_name": "zaozhuang",
"id": 733,
"name": "枣庄"
},
{
"city_name": "zhangjiakou",
"id": 737,
"name": "张家口"
},
{
"city_name": "zhanjiang",
"id": 741,
"name": "湛江"
},
{
"city_name": "zhaoqing",
"id": 742,
"name": "肇庆"
},
{
"city_name": "zhengzhou",
"id": 744,
"name": "郑州"
},
{
"city_name": "zhenjiang",
"id": 745,
"name": "镇江"
},
{
"city_name": "zhongshan",
"id": 746,
"name": "中山"
},
{
"city_name": "zhoukou",
"id": 749,
"name": "周口"
},
{
"city_name": "zhoushan",
"id": 750,
"name": "舟山"
},
{
"city_name": "zhuhai",
"id": 751,
"name": "珠海"
},
{
"city_name": "zhumadian",
"id": 752,
"name": "驻马店"
},
{
"city_name": "zhuzhou",
"id": 753,
"name": "株洲"
},
{
"city_name": "zibo",
"id": 754,
"name": "淄博"
},
{
"city_name": "zunyi",
"id": 757,
"name": "遵义"
}
],
"title": "Z"
}
]
},
{
"is_located": false,
"name": "国际/港澳台",
"groups": [
{
"is_hot": true,
"initial": "热",
"cities": [
{
"city_name": "shouer",
"id": 612,
"name": "首尔"
},
{
"city_name": "dongjing",
"id": 2669,
"name": "东京"
},
{
"city_name": "mangu",
"id": 3936,
"name": "曼谷"
},
{
"city_name": "jizhoushi",
"id": 2536,
"name": "济州岛"
},
{
"city_name": "xianggangdao",
"id": 677,
"name": "香港"
}
],
"title": "热门城市"
},
{
"initial": "*",
"cities": [
{
"city_name": "worldwide",
"id": "worldwide",
"name": "全部城市"
}
],
"title": "*"
},
{
"is_hot": false,
"initial": "D",
"cities": [
{
"city_name": "dongjing",
"id": 2669,
"name": "东京"
}
],
"title": "D"
},
{
"is_hot": false,
"initial": "J",
"cities": [
{
"city_name": "jizhoushi",
"id": 2536,
"name": "济州岛"
}
],
"title": "J"
},
{
"is_hot": false,
"initial": "M",
"cities": [
{
"city_name": "mangu",
"id": 3936,
"name": "曼谷"
}
],
"title": "M"
},
{
"is_hot": false,
"initial": "S",
"cities": [
{
"city_name": "shouer",
"id": 612,
"name": "首尔"
}
],
"title": "S"
},
{
"is_hot": false,
"initial": "T",
"cities": [
{
"city_name": "taibei",
"id": 627,
"name": "台北"
}
],
"title": "T"
},
{
"is_hot": false,
"initial": "X",
"cities": [
{
"city_name": "xianggangdao",
"id": 677,
"name": "中国香港"
}
],
"title": "X"
}
]
}
],
"tags": [
{
"id": "all",
"sub_tags": [
{
"id": "all",
"name": "全部项目"
}
],
"name": "全部项目"
},
{
"name": "眼部整形",
"sub_tags": [
{
"id": 1,
"name": "全部眼部整形"
},
{
"id": 15,
"name": "双眼皮"
},
{
"id": 16,
"name": "填充泪沟"
},
{
"id": 17,
"name": "开眼角"
},
{
"id": 18,
"name": "祛眼袋"
},
{
"id": 19,
"name": "祛黑眼圈"
},
{
"id": 63,
"name": "填充卧蚕"
},
{
"id": 64,
"name": "眼部修复"
},
{
"id": 884,
"name": "垫眉弓"
},
{
"id": 975,
"name": "眼睑"
},
{
"id": 3459,
"name": "眼部综合"
}
]
},
{
"name": "鼻部整形",
"sub_tags": [
{
"id": 2,
"name": "全部鼻部整形"
},
{
"id": 21,
"name": "隆鼻"
},
{
"id": 24,
"name": "鼻翼"
},
{
"id": 26,
"name": "鼻形矫正"
},
{
"id": 65,
"name": "鼻部修复"
},
{
"id": 896,
"name": "鼻基底"
},
{
"id": 3285,
"name": "鼻部综合"
}
]
},
{
"name": "轮廓骨骼",
"sub_tags": [
{
"id": 3,
"name": "全部轮廓骨骼"
},
{
"id": 28,
"name": "颧骨"
},
{
"id": 29,
"name": "额头"
},
{
"id": 30,
"name": "太阳穴"
},
{
"id": 45,
"name": "面颊"
},
{
"id": 46,
"name": "下巴"
},
{
"id": 81,
"name": "轮廓修复"
},
{
"id": 235,
"name": "下颌角切除术"
},
{
"id": 766,
"name": "祛颊脂垫"
},
{
"id": 812,
"name": "V-line瓜子脸手术"
},
{
"id": 898,
"name": "咬肌切除"
},
{
"id": 900,
"name": "两颚"
},
{
"id": 1136,
"name": "磨骨"
},
{
"id": 1233,
"name": "自体脂肪填充面部"
},
{
"id": 3047,
"name": "假体填充"
},
{
"id": 5060,
"name": "轮廓套餐"
},
{
"id": 6150,
"name": "手术套餐"
}
]
},
{
"name": "瘦身美体",
"sub_tags": [
{
"id": 4,
"name": "全部瘦身美体"
},
{
"id": 32,
"name": "腰腹"
},
{
"id": 33,
"name": "臀部"
},
{
"id": 38,
"name": "溶脂"
},
{
"id": 72,
"name": "中医减肥"
},
{
"id": 84,
"name": "手臂"
},
{
"id": 221,
"name": "吸脂"
},
{
"id": 892,
"name": "大腿"
},
{
"id": 893,
"name": "小腿"
},
{
"id": 894,
"name": "肩背"
},
{
"id": 5061,
"name": "瘦身套餐"
}
]
},
{
"name": "皮肤美容",
"sub_tags": [
{
"id": 5,
"name": "全部皮肤美容"
},
{
"id": 34,
"name": "祛痘祛痘印"
},
{
"id": 35,
"name": "祛斑"
},
{
"id": 41,
"name": "改善肤质"
},
{
"id": 47,
"name": "美白嫩肤"
},
{
"id": 60,
"name": "祛纹身"
},
{
"id": 78,
"name": "祛红血丝"
},
{
"id": 1387,
"name": "清洁补水"
},
{
"id": 1992,
"name": "祛痣"
},
{
"id": 2942,
"name": "祛疤"
}
]
},
{
"name": "胸部塑身",
"sub_tags": [
{
"id": 7,
"name": "全部胸部塑身"
},
{
"id": 66,
"name": "丰胸(隆胸)"
},
{
"id": 67,
"name": "乳头乳晕"
},
{
"id": 68,
"name": "副乳"
},
{
"id": 69,
"name": "胸部形态重塑"
},
{
"id": 70,
"name": "胸部修复"
},
{
"id": 5724,
"name": "胸部提升"
},
{
"id": 6144,
"name": "胸部套餐"
}
]
},
{
"name": "毛发管理",
"sub_tags": [
{
"id": 9,
"name": "全部毛发管理"
},
{
"id": 80,
"name": "毛发其他"
},
{
"id": 865,
"name": "药物脱毛"
},
{
"id": 983,
"name": "毛发移植"
},
{
"id": 2663,
"name": "激光脱毛"
},
{
"id": 2947,
"name": "光子脱毛"
}
]
},
{
"name": "私密整形",
"sub_tags": [
{
"id": 10,
"name": "全部私密整形"
},
{
"id": 955,
"name": "女性私密"
},
{
"id": 956,
"name": "男性私密"
}
]
},
{
"name": "牙齿美容",
"sub_tags": [
{
"id": 11,
"name": "全部牙齿美容"
},
{
"id": 53,
"name": "牙齿整形"
},
{
"id": 55,
"name": "美容冠"
},
{
"id": 154,
"name": "牙齿矫正"
},
{
"id": 155,
"name": "牙齿美白"
},
{
"id": 156,
"name": "烤瓷牙"
},
{
"id": 157,
"name": "洗牙"
},
{
"id": 158,
"name": "补牙"
},
{
"id": 159,
"name": "种植牙"
},
{
"id": 852,
"name": "拔牙"
},
{
"id": 2458,
"name": "瓷贴面"
}
]
},
{
"name": "口唇整形",
"sub_tags": [
{
"id": 12,
"name": "全部口唇整形"
},
{
"id": 31,
"name": "酒窝"
},
{
"id": 52,
"name": "丰唇"
},
{
"id": 903,
"name": "嘴角上提"
},
{
"id": 904,
"name": "厚唇"
},
{
"id": 907,
"name": "唇形"
}
]
},
{
"name": "抗衰紧致",
"sub_tags": [
{
"id": 922,
"name": "全部抗衰紧致"
},
{
"id": 62,
"name": "颈部"
},
{
"id": 79,
"name": "除皱"
},
{
"id": 933,
"name": "自体脂肪面部年轻化"
},
{
"id": 4422,
"name": "祛皱"
}
]
},
{
"name": "注射美容",
"sub_tags": [
{
"id": 992,
"name": "全部注射美容"
},
{
"id": 82,
"name": "微整修复"
},
{
"id": 1055,
"name": "玻尿酸注射"
},
{
"id": 2033,
"name": "瘦脸除皱"
},
{
"id": 3042,
"name": "胶原蛋白注射"
},
{
"id": 3044,
"name": "少女针"
},
{
"id": 3046,
"name": "童颜针"
},
{
"id": 5078,
"name": "微整套餐"
},
{
"id": 6147,
"name": "注射美肤"
}
]
},
{
"name": "自体脂肪",
"sub_tags": [
{
"id": 1024,
"name": "全部自体脂肪"
},
{
"id": 2112,
"name": "面部填充"
},
{
"id": 6102,
"name": "身体塑形"
},
{
"id": 7117,
"name": "脂肪其他"
}
]
},
{
"name": "半永久",
"sub_tags": [
{
"id": 1080,
"name": "全部半永久"
},
{
"id": 1370,
"name": "韩式半永久纹眉"
},
{
"id": 2054,
"name": "半永久妆"
},
{
"id": 2055,
"name": "韩式半永久飘眉"
},
{
"id": 2056,
"name": "韩式半永久雾眉"
},
{
"id": 2057,
"name": "韩式半永久纹眼线(美瞳线)"
},
{
"id": 2058,
"name": "韩式半永久漂唇"
},
{
"id": 2954,
"name": "韩式半永久纹发际线"
},
{
"id": 5079,
"name": "韩式半永久套餐"
},
{
"id": 6944,
"name": "半永久 生活美容"
}
]
},
{
"name": "其他",
"sub_tags": [
{
"id": 2214,
"name": "全部其他"
},
{
"id": 13,
"name": "耳部整形"
},
{
"id": 929,
"name": "视力矫正"
},
{
"id": 957,
"name": "祛腋臭"
},
{
"id": 971,
"name": "产后修复"
},
{
"id": 1134,
"name": "面膜"
},
{
"id": 2054,
"name": "半永久妆"
},
{
"id": 2955,
"name": "体检"
},
{
"id": 5433,
"name": "腿型矫正"
},
{
"id": 6418,
"name": "补差价"
},
{
"id": 6933,
"name": "生活美容"
},
{
"id": 7587,
"name": "大脚骨矫正"
},
{
"id": 11340,
"name": "塌鼻梁拯救计划"
},
{
"id": 11341,
"name": "Get元气初恋脸"
},
{
"id": 11342,
"name": "维密身材养成记"
},
{
"id": 11344,
"name": "电眼杀手俱乐部"
},
{
"id": 11345,
"name": "人间水蜜桃计划"
}
]
},
{
"name": "眼科",
"sub_tags": [
{
"id": 12711,
"name": "全部眼科"
},
{
"id": 932,
"name": "近视矫正"
},
{
"id": 940,
"name": "眼科其他"
}
]
}
],
"orders": [
{
"id": 0,
"name": "智能排序"
},
{
"id": 1,
"name": "价格"
},
{
"id": 2,
"name": "好评率"
},
{
"id": 3,
"name": "销量"
}
]
}
}
""";
/*
* @author lsy
* @date 2020/7/1
**/
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:gm_flutter/ClueModel/server/entity/PlanBean.dart';
import 'package:gm_flutter/commonModel/base/BaseComponent.dart';
import 'package:gm_flutter/commonModel/bean/Pair.dart';
import 'package:gm_flutter/commonModel/util/DartUtil.dart';
class ProjectView extends StatefulWidget {
final List<Tags> datas;
final Function(String id) clickCall;
ProjectView(this.datas, this.clickCall);
@override
State<StatefulWidget> createState() => ProjectViewState();
}
class ProjectViewState extends State<ProjectView> {
int selectIndex = 0;
@override
Widget build(BuildContext context) {
if (widget.datas == null || widget.datas.isEmpty) {
return Container();
}
return Container(
height: 450,
color: Colors.white,
child: Row(
children: <Widget>[
Container(
width: 75,
child: ListView.builder(
itemBuilder: (c, index) {
return Container(
height: 50,
color:
selectIndex == index ? Colors.white : Color(0xffF4F3F8),
child: Stack(
alignment: AlignmentDirectional.center,
children: <Widget>[
baseText(
widget.datas[index].name,
14,
selectIndex == index
? Color(0xff4ABAB4)
: Color(0xff464646),
bold: selectIndex == index ? true : false),
Positioned(
left: 0,
top: 17,
child: selectIndex == index
? Container(
width: 3,
height: 16,
decoration: BoxDecoration(
color: Color(0xff4ABAB4),
borderRadius: BorderRadius.circular(1.5)),
)
: Container(),
)
],
)).gestureDetector(() {
setState(() {
selectIndex = index;
});
});
},
itemCount: widget.datas.length,
),
),
Expanded(
child: ListView.builder(
itemBuilder: (c, index) {
return Container(
margin: EdgeInsets.only(left: 20, top: 18, bottom: 18),
child: baseText(widget.datas[selectIndex].subTags[index].name,
14, Color(0xff464646)),
).gestureDetector(() {
widget.clickCall(widget.datas[selectIndex].subTags[index].id);
});
},
itemCount: widget.datas[selectIndex].subTags.length,
),
)
],
),
);
}
}
/*
* @author lsy
* @date 2020/7/1
**/
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:gm_flutter/ClueModel/server/entity/PlanBean.dart';
import 'package:gm_flutter/commonModel/base/BaseComponent.dart';
import 'package:gm_flutter/commonModel/util/DartUtil.dart';
class SortView extends StatelessWidget {
final List<Orders> datas;
int selectIndex = 0;
final Function(int index) clickIndex;
SortView(this.datas, this.selectIndex, this.clickIndex);
@override
Widget build(BuildContext context) {
if (datas == null || datas.isEmpty) {
return Container();
}
return Container(
color: Colors.white,
child: ListView.builder(
itemBuilder: (c, index) {
return Container(
margin: EdgeInsets.only(left: 15, right: 15),
width: double.maxFinite,
height: 45,
child: Stack(
children: <Widget>[
Positioned(
top: 16,
child: baseText(
datas[index].name,
13,
selectIndex == index
? Color(0xff4ABAB4)
: Color(0xff464646)),
),
Positioned(
right: 0,
top: 15,
child: selectIndex == index
? Container(
width: 15,
height: 15,
child: Image.asset("assets/yes.png"),
)
: Container(),
),
Positioned(
bottom: 0,
child: Container(
height: 0.5,
width: MediaQuery.of(context).size.width - 30,
color: Color(0xffE5E5E5),
),
)
],
),
).gestureDetector(() {
clickIndex(index);
});
},
itemCount: datas.length,
));
}
}
......@@ -6,10 +6,38 @@ import 'package:flutter_common/Annotations/anno/Get.dart';
import 'package:flutter_common/Annotations/anno/Query.dart';
import 'package:flutter_common/Annotations/anno/ServiceCenter.dart';
import 'package:gm_flutter/ClueModel/server/entity/LevelOneFeedList.dart';
import 'package:gm_flutter/ClueModel/server/entity/PlanCompareDetail.dart';
import 'package:gm_flutter/ClueModel/server/entity/PlansCompareFeed.dart';
import 'package:gm_flutter/ClueModel/server/entity/ProjectDetailsItem.dart';
import 'package:gm_flutter/ClueModel/server/entity/PlanBean.dart';
import 'package:gm_flutter/ClueModel/server/entity/PlanFeedBean.dart';
@ServiceCenter()
abstract class ClueApi {
@Get("/api/janus/plans/plan_detail")
ProjectDetailsItem getProjectDetails(@Query("plan_id") int plan_id);
@Get("/api/janus/plans/compare_feed")
PlansCompareFeed getPlansCompareFeed(
@Query("plan_id") int plan_id, @Query("plan_type") int plan_type);
@Get("api/janus/plans/plan_feed")
LevelOneFeedList getLevelOneList(@Query("plan_id") int plan_id,
@Query("tab_type") String tab_type, @Query("page") int page);
@Get("api/janus/plans/compare")
PlanCompareDetail getPlanCompareDetail(@Query("plan_ids") List<int> plan_ids);
@Get("api/janus/plans/options")
PlanBean getPlan();
@Get("api/janus/plans/feed")
PlanFeedBean getPlanFeed(
@Query("tag_id")String tag_id,
@Query("order_by")String order_by,
@Query("current_city_id")String current_city_id,
@Query("min_price")String min_price,
@Query("max_price")String max_price,
@Query("rank_type")String rank_type,
@Query("page")int page,
);
}
......@@ -14,7 +14,12 @@ import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
import 'package:gm_flutter/ClueModel/server/entity/ProjectDetailsItem.dart';
import 'package:gm_flutter/ClueModel/server/entity/PlansCompareFeed.dart';
import 'package:gm_flutter/ClueModel/server/entity/LevelOneFeedList.dart';
import 'package:gm_flutter/ClueModel/server/entity/PlanCompareDetail.dart';
import 'package:gm_flutter/ClueModel/server/entity/PlanBean.dart';
import 'package:gm_flutter/ClueModel/server/entity/PlanFeedBean.dart';
const bool inProduction = const bool.fromEnvironment("dart.vm.product");
......@@ -32,6 +37,36 @@ class ClueApiImpl {
return _instance;
}
Stream<ProjectDetailsItem> getProjectDetails(Dio _dio, int plan_id) {
return Stream.fromFuture(get(_dio, '/api/janus/plans/plan_detail', data: {
'plan_id': plan_id,
})).flatMap((value) {
if (value != null &&
(value.statusCode >= 200 && value.statusCode < 300)) {
return Stream.fromFuture(
compute(parseProjectDetailsItem, value.toString()));
} else {
throw Exception("--未知网络错误--");
}
});
}
Stream<PlansCompareFeed> getPlansCompareFeed(
Dio _dio, int plan_id, int plan_type) {
return Stream.fromFuture(get(_dio, '/api/janus/plans/compare_feed', data: {
'plan_id': plan_id,
'plan_type': plan_type,
})).flatMap((value) {
if (value != null &&
(value.statusCode >= 200 && value.statusCode < 300)) {
return Stream.fromFuture(
compute(parsePlansCompareFeed, value.toString()));
} else {
throw Exception("--未知网络错误--");
}
});
}
Stream<LevelOneFeedList> getLevelOneList(
Dio _dio, int plan_id, String tab_type, int page) {
return Stream.fromFuture(get(_dio, 'api/janus/plans/plan_feed', data: {
......@@ -49,6 +84,61 @@ class ClueApiImpl {
});
}
Stream<PlanCompareDetail> getPlanCompareDetail(Dio _dio, List<int> plan_ids) {
return Stream.fromFuture(get(_dio, 'api/janus/plans/compare', data: {
'plan_ids': plan_ids,
})).flatMap((value) {
if (value != null &&
(value.statusCode >= 200 && value.statusCode < 300)) {
return Stream.fromFuture(
compute(parsePlanCompareDetail, value.toString()));
} else {
throw Exception("--未知网络错误--");
}
});
}
Stream<PlanBean> getPlan(
Dio _dio,
) {
return Stream.fromFuture(get(_dio, 'api/janus/plans/options'))
.flatMap((value) {
if (value != null &&
(value.statusCode >= 200 && value.statusCode < 300)) {
return Stream.fromFuture(compute(parsePlanBean, value.toString()));
} else {
throw Exception("--未知网络错误--");
}
});
}
Stream<PlanFeedBean> getPlanFeed(
Dio _dio,
String tag_id,
String order_by,
String current_city_id,
String min_price,
String max_price,
String rank_type,
int page) {
return Stream.fromFuture(get(_dio, 'api/janus/plans/feed', data: {
'tag_id': tag_id,
'order_by': order_by,
'current_city_id': current_city_id,
'min_price': min_price,
'max_price': max_price,
'rank_type': rank_type,
'page': page,
})).flatMap((value) {
if (value != null &&
(value.statusCode >= 200 && value.statusCode < 300)) {
return Stream.fromFuture(compute(parsePlanFeedBean, value.toString()));
} else {
throw Exception("--未知网络错误--");
}
});
}
///==================base method==================
Future<Response> get(Dio _dio, url, {data, options, cancelToken}) async {
......@@ -186,6 +276,26 @@ class ClueApiImpl {
}
}
ProjectDetailsItem parseProjectDetailsItem(String value) {
return ProjectDetailsItem.fromJson(json.decode(value));
}
PlansCompareFeed parsePlansCompareFeed(String value) {
return PlansCompareFeed.fromJson(json.decode(value));
}
LevelOneFeedList parseLevelOneFeedList(String value) {
return LevelOneFeedList.fromJson(json.decode(value));
}
PlanCompareDetail parsePlanCompareDetail(String value) {
return PlanCompareDetail.fromJson(json.decode(value));
}
PlanBean parsePlanBean(String value) {
return PlanBean.fromJson(json.decode(value));
}
PlanFeedBean parsePlanFeedBean(String value) {
return PlanFeedBean.fromJson(json.decode(value));
}
......@@ -3,16 +3,63 @@
* @date 2020/6/29
**/
class LevelOneFeedList {
List<Cards> cards;
int error;
String message;
Null extra;
Null errorExtra;
UserType userType;
Data data;
LevelOneFeedList({this.cards});
LevelOneFeedList({this.error, this.message, this.extra, this.errorExtra, this.userType, this.data});
LevelOneFeedList.fromJson(Map<String, dynamic> json) {
error = json['error'];
message = json['message'];
extra = json['extra'];
errorExtra = json['error_extra'];
userType = json['user_type'] != null ? new UserType.fromJson(json['user_type']) : null;
data = json['data'] != null ? new Data.fromJson(json['data']) : null;
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['error'] = this.error;
data['message'] = this.message;
data['extra'] = this.extra;
data['error_extra'] = this.errorExtra;
if (this.userType != null) {
data['user_type'] = this.userType.toJson();
}
if (this.data != null) {
data['data'] = this.data.toJson();
}
return data;
}
}
class UserType {
UserType();
UserType.fromJson(Map<String, dynamic> json) {
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
return data;
}
}
class Data {
List<Cards> cards;
Data({this.cards});
Data.fromJson(Map<String, dynamic> json) {
if (json['cards'] != null) {
cards = new List<Cards>();
json['cards'].forEach((v) {
cards.add(new Cards.fromJson(v));
});
json['cards'].forEach((v) { cards.add(new Cards.fromJson(v)); });
}
}
......@@ -29,7 +76,7 @@ class Cards {
String cardType;
Plan plan;
Hospital hospital;
Hospital doctor;
Doctor doctor;
Diary diary;
Cards({this.cardType, this.plan, this.hospital, this.doctor, this.diary});
......@@ -37,11 +84,8 @@ class Cards {
Cards.fromJson(Map<String, dynamic> json) {
cardType = json['card_type'];
plan = json['plan'] != null ? new Plan.fromJson(json['plan']) : null;
hospital = json['hospital'] != null
? new Hospital.fromJson(json['hospital'])
: null;
doctor =
json['doctor'] != null ? new Hospital.fromJson(json['doctor']) : null;
hospital = json['hospital'] != null ? new Hospital.fromJson(json['hospital']) : null;
doctor = json['doctor'] != null ? new Doctor.fromJson(json['doctor']) : null;
diary = json['diary'] != null ? new Diary.fromJson(json['diary']) : null;
}
......@@ -72,19 +116,10 @@ class Plan {
String salesCount;
List<BaseAttrs> baseAttrs;
String projectImage;
String consultUrl;
String phoneAuthroize;
Plan(
{this.planName,
this.minPrice,
this.maxPrice,
this.positiveRate,
this.salesCount,
this.baseAttrs,
this.projectImage,
this.consultUrl,
this.phoneAuthroize});
String consultType;
String messageUrl;
Plan({this.planName, this.minPrice, this.maxPrice, this.positiveRate, this.salesCount, this.baseAttrs, this.projectImage, this.consultType, this.messageUrl});
Plan.fromJson(Map<String, dynamic> json) {
planName = json['plan_name'];
......@@ -94,13 +129,11 @@ class Plan {
salesCount = json['sales_count'];
if (json['base_attrs'] != null) {
baseAttrs = new List<BaseAttrs>();
json['base_attrs'].forEach((v) {
baseAttrs.add(new BaseAttrs.fromJson(v));
});
json['base_attrs'].forEach((v) { baseAttrs.add(new BaseAttrs.fromJson(v)); });
}
projectImage = json['project_image'];
consultUrl = json['consult_url'];
phoneAuthroize = json['phone_authroize'];
consultType = json['consult_type'];
messageUrl = json['message_url'];
}
Map<String, dynamic> toJson() {
......@@ -114,8 +147,8 @@ class Plan {
data['base_attrs'] = this.baseAttrs.map((v) => v.toJson()).toList();
}
data['project_image'] = this.projectImage;
data['consult_url'] = this.consultUrl;
data['phone_authroize'] = this.phoneAuthroize;
data['consult_type'] = this.consultType;
data['message_url'] = this.messageUrl;
return data;
}
}
......@@ -144,36 +177,59 @@ class Hospital {
String name;
String minPrice;
String maxPrice;
String star;
String address;
int star;
List<BaseAttrs> baseAttrs;
String consultUrl;
String phoneAuthroize;
Hospital(
{this.portrait,
this.name,
this.minPrice,
this.maxPrice,
this.baseAttrs,
this.consultUrl,
this.phoneAuthroize});
String consultType;
String messageUrl;
Hospital({this.portrait, this.name, this.minPrice, this.maxPrice, this.star, this.address, this.consultType, this.messageUrl});
Hospital.fromJson(Map<String, dynamic> json) {
portrait = json['portrait'];
name = json['name'];
minPrice = json['min_price'];
maxPrice = json['max_price'];
star = json['star'];
address = json['address'];
consultType = json['consult_type'];
messageUrl = json['message_url'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['portrait'] = this.portrait;
data['name'] = this.name;
data['min_price'] = this.minPrice;
data['max_price'] = this.maxPrice;
data['star'] = this.star;
data['address'] = this.address;
data['consult_type'] = this.consultType;
data['message_url'] = this.messageUrl;
return data;
}
}
class Doctor {
String portrait;
String name;
String minPrice;
String maxPrice;
String star;
String title;
String consultType;
String messageUrl;
Doctor({this.portrait, this.name, this.minPrice, this.maxPrice, this.star, this.title, this.consultType, this.messageUrl});
Doctor.fromJson(Map<String, dynamic> json) {
portrait = json['portrait'];
name = json['name'];
minPrice = json['min_price'];
maxPrice = json['max_price'];
if (json['base_attrs'] != null) {
baseAttrs = new List<BaseAttrs>();
json['base_attrs'].forEach((v) {
baseAttrs.add(new BaseAttrs.fromJson(v));
});
}
consultUrl = json['consult_url'];
phoneAuthroize = json['phone_authroize'];
star = json['star'];
title = json['title'];
consultType = json['consult_type'];
messageUrl = json['message_url'];
}
Map<String, dynamic> toJson() {
......@@ -182,13 +238,10 @@ class Hospital {
data['name'] = this.name;
data['min_price'] = this.minPrice;
data['max_price'] = this.maxPrice;
data['address'] = this.address;
data['star'] = this.star;
if (this.baseAttrs != null) {
data['base_attrs'] = this.baseAttrs.map((v) => v.toJson()).toList();
}
data['consult_url'] = this.consultUrl;
data['phone_authroize'] = this.phoneAuthroize;
data['title'] = this.title;
data['consult_type'] = this.consultType;
data['message_url'] = this.messageUrl;
return data;
}
}
......@@ -202,7 +255,7 @@ class Diary {
int replyNum;
int lasestTopicCreatedTime;
List<Images> images;
RelationServiceSku relationServiceSku;
UserType relationServiceSku;
String createdTime;
int latestTopicId;
int id;
......@@ -232,44 +285,7 @@ class Diary {
UserLevel userLevel;
int serviceId;
Diary(
{this.diaryNum,
this.videoUrl,
this.isIdentification,
this.isLiked,
this.titleStyleType,
this.replyNum,
this.lasestTopicCreatedTime,
this.images,
this.relationServiceSku,
this.createdTime,
this.latestTopicId,
this.id,
this.city,
this.userId,
this.title,
this.isVoted,
this.diaryId,
this.preImageList,
this.voteNum,
this.tagsNewEra,
this.content,
this.videoPic,
this.shortVideoUrl,
this.diaryAmount,
this.diaryTitle,
this.authorType,
this.tags,
this.contentLevel,
this.lastModified,
this.user,
this.isOnline,
this.date,
this.membershipLevel,
this.viewNum,
this.postImageList,
this.userLevel,
this.serviceId});
Diary({this.diaryNum, this.videoUrl, this.isIdentification, this.isLiked, this.titleStyleType, this.replyNum, this.lasestTopicCreatedTime, this.images, this.relationServiceSku, this.createdTime, this.latestTopicId, this.id, this.city, this.userId, this.title, this.isVoted, this.diaryId, this.preImageList, this.voteNum, this.tagsNewEra, this.content, this.videoPic, this.shortVideoUrl, this.diaryAmount, this.diaryTitle, this.authorType, this.tags, this.contentLevel, this.lastModified, this.user, this.isOnline, this.date, this.membershipLevel, this.viewNum, this.postImageList, this.userLevel, this.serviceId});
Diary.fromJson(Map<String, dynamic> json) {
diaryNum = json['diary_num'];
......@@ -281,13 +297,9 @@ class Diary {
lasestTopicCreatedTime = json['lasest_topic_created_time'];
if (json['images'] != null) {
images = new List<Images>();
json['images'].forEach((v) {
images.add(new Images.fromJson(v));
});
json['images'].forEach((v) { images.add(new Images.fromJson(v)); });
}
relationServiceSku = json['relation_service_sku'] != null
? new RelationServiceSku.fromJson(json['relation_service_sku'])
: null;
relationServiceSku = json['relation_service_sku'] != null ? new UserType.fromJson(json['relation_service_sku']) : null;
createdTime = json['created_time'];
latestTopicId = json['latest_topic_id'];
id = json['id'];
......@@ -300,9 +312,7 @@ class Diary {
voteNum = json['vote_num'];
if (json['tags_new_era'] != null) {
tagsNewEra = new List<TagsNewEra>();
json['tags_new_era'].forEach((v) {
tagsNewEra.add(new TagsNewEra.fromJson(v));
});
json['tags_new_era'].forEach((v) { tagsNewEra.add(new TagsNewEra.fromJson(v)); });
}
content = json['content'];
videoPic = json['video_pic'];
......@@ -312,9 +322,7 @@ class Diary {
authorType = json['author_type'];
if (json['tags'] != null) {
tags = new List<Tags>();
json['tags'].forEach((v) {
tags.add(new Tags.fromJson(v));
});
json['tags'].forEach((v) { tags.add(new Tags.fromJson(v)); });
}
contentLevel = json['content_level'];
lastModified = json['last_modified'];
......@@ -324,9 +332,7 @@ class Diary {
membershipLevel = json['membership_level'];
viewNum = json['view_num'];
postImageList = json['post_image_list'].cast<String>();
userLevel = json['user_level'] != null
? new UserLevel.fromJson(json['user_level'])
: null;
userLevel = json['user_level'] != null ? new UserLevel.fromJson(json['user_level']) : null;
serviceId = json['service_id'];
}
......@@ -396,16 +402,7 @@ class Images {
String imageHalf;
String desc;
Images(
{this.imageWide,
this.imageType,
this.image,
this.sImagePlatform,
this.imageSlimwidth,
this.smallWide,
this.imageThumb,
this.imageHalf,
this.desc});
Images({this.imageWide, this.imageType, this.image, this.sImagePlatform, this.imageSlimwidth, this.smallWide, this.imageThumb, this.imageHalf, this.desc});
Images.fromJson(Map<String, dynamic> json) {
imageWide = json['image_wide'];
......@@ -434,17 +431,6 @@ class Images {
}
}
class RelationServiceSku {
RelationServiceSku();
RelationServiceSku.fromJson(Map<String, dynamic> json) {}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
return data;
}
}
class TagsNewEra {
String type;
String name;
......@@ -479,14 +465,7 @@ class User {
String userName;
String membershipLevel;
User(
{this.city,
this.userId,
this.topicNumPosted,
this.voteNumGained,
this.portrait,
this.userName,
this.membershipLevel});
User({this.city, this.userId, this.topicNumPosted, this.voteNumGained, this.portrait, this.userName, this.membershipLevel});
User.fromJson(Map<String, dynamic> json) {
city = json['city'];
......@@ -557,3 +536,4 @@ class Tags {
return data;
}
}
/*
* @author lsy
* @date 2020/7/1
**/
class PlanBean {
int error;
String message;
String extra;
String errorExtra;
UserType userType;
Data data;
PlanBean({this.error, this.message, this.extra, this.errorExtra, this.userType, this.data});
PlanBean.fromJson(Map<String, dynamic> json) {
error = json['error'];
message = json['message'];
extra = json['extra'];
errorExtra = json['error_extra'];
userType = json['user_type'] != null ? new UserType.fromJson(json['user_type']) : null;
data = json['data'] != null ? new Data.fromJson(json['data']) : null;
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['error'] = this.error;
data['message'] = this.message;
data['extra'] = this.extra;
data['error_extra'] = this.errorExtra;
if (this.userType != null) {
data['user_type'] = this.userType.toJson();
}
if (this.data != null) {
data['data'] = this.data.toJson();
}
return data;
}
}
class UserType {
UserType();
UserType.fromJson(Map<String, dynamic> json) {
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
return data;
}
}
class Data {
List<Ranks> ranks;
List<Areas> areas;
List<Tags> tags;
List<Orders> orders;
Data({this.ranks, this.areas, this.tags, this.orders});
Data.fromJson(Map<String, dynamic> json) {
if (json['ranks'] != null) {
ranks = new List<Ranks>();
json['ranks'].forEach((v) { ranks.add(new Ranks.fromJson(v)); });
}
if (json['areas'] != null) {
areas = new List<Areas>();
json['areas'].forEach((v) { areas.add(new Areas.fromJson(v)); });
}
if (json['tags'] != null) {
tags = new List<Tags>();
json['tags'].forEach((v) { tags.add(new Tags.fromJson(v)); });
}
if (json['orders'] != null) {
orders = new List<Orders>();
json['orders'].forEach((v) { orders.add(new Orders.fromJson(v)); });
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
if (this.ranks != null) {
data['ranks'] = this.ranks.map((v) => v.toJson()).toList();
}
if (this.areas != null) {
data['areas'] = this.areas.map((v) => v.toJson()).toList();
}
if (this.tags != null) {
data['tags'] = this.tags.map((v) => v.toJson()).toList();
}
if (this.orders != null) {
data['orders'] = this.orders.map((v) => v.toJson()).toList();
}
return data;
}
}
class Ranks {
String name;
String gmUrl;
String icon;
Ranks({this.name, this.gmUrl, this.icon});
Ranks.fromJson(Map<String, dynamic> json) {
name = json['name'];
gmUrl = json['gm_url'];
icon = json['icon'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['name'] = this.name;
data['gm_url'] = this.gmUrl;
data['icon'] = this.icon;
return data;
}
}
class Areas {
bool isLocated;
String name;
List<Groups> groups;
Areas({this.isLocated, this.name, this.groups});
Areas.fromJson(Map<String, dynamic> json) {
isLocated = json['is_located'];
name = json['name'];
if (json['groups'] != null) {
groups = new List<Groups>();
json['groups'].forEach((v) { groups.add(new Groups.fromJson(v)); });
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['is_located'] = this.isLocated;
data['name'] = this.name;
if (this.groups != null) {
data['groups'] = this.groups.map((v) => v.toJson()).toList();
}
return data;
}
}
class Groups {
bool isHot;
String initial;
List<Cities> cities;
String title;
Groups({this.isHot, this.initial, this.cities, this.title});
Groups.fromJson(Map<String, dynamic> json) {
isHot = json['is_hot'];
initial = json['initial'];
if (json['cities'] != null) {
cities = new List<Cities>();
json['cities'].forEach((v) { cities.add(new Cities.fromJson(v)); });
}
title = json['title'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['is_hot'] = this.isHot;
data['initial'] = this.initial;
if (this.cities != null) {
data['cities'] = this.cities.map((v) => v.toJson()).toList();
}
data['title'] = this.title;
return data;
}
}
class Cities {
String cityName;
String id;
String name;
Cities({this.cityName, this.id, this.name});
Cities.fromJson(Map<String, dynamic> json) {
cityName = json['city_name'];
id = json['id'].toString();
name = json['name'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['city_name'] = this.cityName;
data['id'] = this.id;
data['name'] = this.name;
return data;
}
}
class Tags {
String id;
List<SubTags> subTags;
String name;
Tags({this.id, this.subTags, this.name});
Tags.fromJson(Map<String, dynamic> json) {
id = json['id'].toString();
if (json['sub_tags'] != null) {
subTags = new List<SubTags>();
json['sub_tags'].forEach((v) { subTags.add(new SubTags.fromJson(v)); });
}
name = json['name'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
if (this.subTags != null) {
data['sub_tags'] = this.subTags.map((v) => v.toJson()).toList();
}
data['name'] = this.name;
return data;
}
}
class SubTags {
String id;
String name;
SubTags({this.id, this.name});
SubTags.fromJson(Map<String, dynamic> json) {
id = json['id'].toString();
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;
}
}
class Orders {
int id;
String name;
Orders({this.id, this.name});
Orders.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;
}
}
/*
* @Author: zx
* @Date: 2020-06-30 19:31:32
* @Last Modified by: zx
* @Last Modified time: 2020-07-01 20:31:42
*/
import 'dart:convert';
class PlanCompareDetail {
int error;
String message;
Null extra;
Null errorExtra;
UserType userType;
Data data;
PlanCompareDetail({this.error, this.message, this.extra, this.errorExtra, this.userType, this.data});
PlanCompareDetail.fromJson(Map<String, dynamic> json) {
error = json['error'];
message = json['message'];
extra = json['extra'];
errorExtra = json['error_extra'];
userType = json['user_type'] != null ? new UserType.fromJson(json['user_type']) : null;
data = json['data'] != null ? new Data.fromJson(json['data']) : null;
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['error'] = this.error;
data['message'] = this.message;
data['extra'] = this.extra;
data['error_extra'] = this.errorExtra;
if (this.userType != null) {
data['user_type'] = this.userType.toJson();
}
if (this.data != null) {
data['data'] = this.data.toJson();
}
return data;
}
}
class UserType {
UserType();
UserType.fromJson(Map<String, dynamic> json) {
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
return data;
}
}
class Data {
List<PlansInfo> plansInfo;
List<Groups> groups;
Data({this.plansInfo, this.groups});
Data.fromJson(Map<String, dynamic> json) {
if (json['plans_info'] != null) {
plansInfo = new List<PlansInfo>();
json['plans_info'].forEach((v) { plansInfo.add(new PlansInfo.fromJson(v)); });
}
if (json['groups'] != null) {
groups = new List<Groups>();
json['groups'].forEach((v) { groups.add(new Groups.fromJson(v)); });
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
if (this.plansInfo != null) {
data['plans_info'] = this.plansInfo.map((v) => v.toJson()).toList();
}
if (this.groups != null) {
data['groups'] = this.groups.map((v) => v.toJson()).toList();
}
return data;
}
}
class PlansInfo {
int planId;
String planName;
String minPrice;
String maxPrice;
PlansInfo({this.planId, this.planName, this.minPrice, this.maxPrice});
PlansInfo.fromJson(Map<String, dynamic> json) {
planId = json['plan_id'];
planName = json['plan_name'];
minPrice = json['min_price'];
maxPrice = json['max_price'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['plan_id'] = this.planId;
data['plan_name'] = this.planName;
data['min_price'] = this.minPrice;
data['max_price'] = this.maxPrice;
return data;
}
}
class Groups {
String groupType;
String groupName;
List<Plans> plans;
Groups({this.groupType, this.groupName, this.plans});
Groups.fromJson(Map<String, dynamic> json) {
groupType = json['group_type'];
groupName = json['group_name'];
if (json['plans'] != null) {
plans = new List<Plans>();
json['plans'].forEach((v) { plans.add(new Plans.fromJson(v)); });
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['group_type'] = this.groupType;
data['group_name'] = this.groupName;
if (this.plans != null) {
data['plans'] = this.plans.map((v) => v.toJson()).toList();
}
return data;
}
}
class Plans {
int planId;
String positiveRate;
String salesCount;
List<Attrs> attrs;
Plans({this.planId, this.positiveRate, this.salesCount, this.attrs});
Plans.fromJson(Map<String, dynamic> json) {
planId = json['plan_id'];
positiveRate = json['positive_rate'];
salesCount = json['sales_count'];
if (json['attrs'] != null) {
attrs = new List<Attrs>();
json['attrs'].forEach((v) { attrs.add(new Attrs.fromJson(v)); });
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['plan_id'] = this.planId;
data['positive_rate'] = this.positiveRate;
data['sales_count'] = this.salesCount;
if (this.attrs != null) {
data['attrs'] = this.attrs.map((v) => v.toJson()).toList();
}
return data;
}
}
class Attrs {
String attrName;
String attrValue;
Attrs({this.attrName, this.attrValue});
Attrs.fromJson(Map<String, dynamic> json) {
attrName = json['attr_name'];
attrValue = json['attr_value'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['attr_name'] = this.attrName;
data['attr_value'] = this.attrValue;
return data;
}
}
/*
* @author lsy
* @date 2020/7/1
**/
class PlanFeedBean {
int error;
String message;
String extra;
String errorExtra;
UserType userType;
Data data;
PlanFeedBean(
{this.error,
this.message,
this.extra,
this.errorExtra,
this.userType,
this.data});
PlanFeedBean.fromJson(Map<String, dynamic> json) {
error = json['error'];
message = json['message'];
extra = json['extra'];
errorExtra = json['error_extra'];
userType = json['user_type'] != null
? new UserType.fromJson(json['user_type'])
: null;
data = json['data'] != null ? new Data.fromJson(json['data']) : null;
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['error'] = this.error;
data['message'] = this.message;
data['extra'] = this.extra;
data['error_extra'] = this.errorExtra;
if (this.userType != null) {
data['user_type'] = this.userType.toJson();
}
if (this.data != null) {
data['data'] = this.data.toJson();
}
return data;
}
}
class UserType {
UserType();
UserType.fromJson(Map<String, dynamic> json) {}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
return data;
}
}
class Data {
List<Plans> plans;
Data({this.plans});
Data.fromJson(Map<String, dynamic> json) {
if (json['plans'] != null) {
plans = new List<Plans>();
json['plans'].forEach((v) {
plans.add(new Plans.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
if (this.plans != null) {
data['plans'] = this.plans.map((v) => v.toJson()).toList();
}
return data;
}
}
class Plans {
String cardType;
String name;
String positiveRate;
String salesCount;
List<BaseAttrs> baseAttrs;
String minPrice;
String maxPrice;
String projectImage;
Plans(
{this.cardType,
this.name,
this.positiveRate,
this.salesCount,
this.baseAttrs,
this.minPrice,
this.maxPrice,
this.projectImage});
Plans.fromJson(Map<String, dynamic> json) {
cardType = json['card_type'];
name = json['name'];
positiveRate = json['positive_rate'];
salesCount = json['sales_count'];
if (json['base_attrs'] != null) {
baseAttrs = new List<BaseAttrs>();
json['base_attrs'].forEach((v) {
baseAttrs.add(new BaseAttrs.fromJson(v));
});
}
minPrice = json['min_price'];
maxPrice = json['max_price'];
projectImage = json['project_image'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['card_type'] = this.cardType;
data['name'] = this.name;
data['positive_rate'] = this.positiveRate;
data['sales_count'] = this.salesCount;
if (this.baseAttrs != null) {
data['base_attrs'] = this.baseAttrs.map((v) => v.toJson()).toList();
}
data['min_price'] = this.minPrice;
data['max_price'] = this.maxPrice;
data['project_image'] = this.projectImage;
return data;
}
}
class BaseAttrs {
int attrId;
String attrName;
String attrValue;
BaseAttrs({this.attrId, this.attrName, this.attrValue});
BaseAttrs.fromJson(Map<String, dynamic> json) {
attrId = json['attr_id'];
attrName = json['attr_name'];
attrValue = json['attr_value'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['attr_id'] = this.attrId;
data['attr_name'] = this.attrName;
data['attr_value'] = this.attrValue;
return data;
}
}
class PlansCompareFeed {
int error;
String message;
String extra;
String errorExtra;
String userType;
Data data;
PlansCompareFeed(
{this.error,
this.message,
this.extra,
this.errorExtra,
this.userType,
this.data});
PlansCompareFeed.fromJson(Map<String, dynamic> json) {
error = json['error'];
message = json['message'];
extra = json['extra'];
errorExtra = json['error_extra'];
userType = json['user_type'];
data = json['data'] != null ? new Data.fromJson(json['data']) : null;
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['error'] = this.error;
data['message'] = this.message;
data['extra'] = this.extra;
data['error_extra'] = this.errorExtra;
data['user_type'] = this.userType;
if (this.data != null) {
data['data'] = this.data.toJson();
}
return data;
}
}
class Data {
List<Plans> plans;
Data({this.plans});
Data.fromJson(Map<String, dynamic> json) {
if (json['plans'] != null) {
plans = new List<Plans>();
json['plans'].forEach((v) {
plans.add(new Plans.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
if (this.plans != null) {
data['plans'] = this.plans.map((v) => v.toJson()).toList();
}
return data;
}
}
class Plans {
int planId;
int planType;
String cardType;
String name;
String positiveRate;
String salesCount;
String minPrice;
String maxPrice;
String projectImage;
String guidePrice;
Plans(
{this.planId,
this.planType,
this.cardType,
this.name,
this.positiveRate,
this.salesCount,
this.minPrice,
this.maxPrice,
this.projectImage,
this.guidePrice});
Plans.fromJson(Map<String, dynamic> json) {
planId = json['plan_id'];
planType = json['plan_type'];
cardType = json['card_type'];
name = json['name'];
positiveRate = json['positive_rate'];
salesCount = json['sales_count'];
minPrice = json['min_price'];
maxPrice = json['max_price'];
projectImage = json['project_image'];
guidePrice = json['guide_price'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['plan_id'] = this.planId;
data['plan_type'] = this.planType;
data['card_type'] = this.cardType;
data['name'] = this.name;
data['positive_rate'] = this.positiveRate;
data['sales_count'] = this.salesCount;
data['min_price'] = this.minPrice;
data['max_price'] = this.maxPrice;
data['project_image'] = this.projectImage;
data['guide_price'] = this.guidePrice;
return data;
}
}
class ProjectDetailsItem {
int error;
String message;
String extra;
String errorExtra;
String userType;
Data data;
ProjectDetailsItem(
{this.error,
this.message,
this.extra,
this.errorExtra,
this.userType,
this.data});
ProjectDetailsItem.fromJson(Map<String, dynamic> json) {
error = json['error'];
message = json['message'];
extra = json['extra'];
errorExtra = json['error_extra'];
userType = json['user_type'];
data = json['data'] != null ? new Data.fromJson(json['data']) : null;
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['error'] = this.error;
data['message'] = this.message;
data['extra'] = this.extra;
data['error_extra'] = this.errorExtra;
data['user_type'] = this.userType;
if (this.data != null) {
data['data'] = this.data.toJson();
}
return data;
}
}
class Data {
int id;
String name;
List<Groups> groups;
Data({this.id, this.name, this.groups});
Data.fromJson(Map<String, dynamic> json) {
id = json['id'];
name = json['name'];
if (json['groups'] != null) {
groups = new List<Groups>();
json['groups'].forEach((v) {
groups.add(new Groups.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['name'] = this.name;
if (this.groups != null) {
data['groups'] = this.groups.map((v) => v.toJson()).toList();
}
return data;
}
}
class Groups {
String name;
List<Attrs> attrs;
Groups({this.name, this.attrs});
Groups.fromJson(Map<String, dynamic> json) {
name = json['name'];
if (json['attrs'] != null) {
attrs = new List<Attrs>();
json['attrs'].forEach((v) {
attrs.add(new Attrs.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['name'] = this.name;
if (this.attrs != null) {
data['attrs'] = this.attrs.map((v) => v.toJson()).toList();
}
return data;
}
}
class Attrs {
int attrId;
String attrName;
String attrValue;
Attrs({this.attrId, this.attrName, this.attrValue});
Attrs.fromJson(Map<String, dynamic> json) {
attrId = json['attr_id'];
attrName = json['attr_name'];
attrValue = json['attr_value'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['attr_id'] = this.attrId;
data['attr_name'] = this.attrName;
data['attr_value'] = this.attrValue;
return data;
}
}
......@@ -26,10 +26,24 @@ class TestState extends BaseState<TestPage> {
JumpUtil.jumpToPageRight(context, NetProxyPage());
}));
list.add(listItem("一级列表页", () {
JumpUtil.jumpToPageRight(context, RouterCenterImpl().findClueRouter().getLevelOnePage());
JumpUtil.jumpToPageRight(
context, RouterCenterImpl().findClueRouter().getLevelOnePage());
}));
list.add(listItem("二级列表页", () {
JumpUtil.jumpToPageRight(context, RouterCenterImpl().findClueRouter().getLevelTwoPage());
JumpUtil.jumpToPageRight(
context, RouterCenterImpl().findClueRouter().getLevelTwoPage());
}));
list.add(listItem("方案页面", () {
JumpUtil.jumpToPageRight(
context, RouterCenterImpl().findClueRouter().getPlanPage());
}));
list.add(listItem("对比详情页", () {
JumpUtil.jumpToPageRight(context,
RouterCenterImpl().findClueRouter().getPlanCompareDetailPage());
}));
list.add(listItem("项目说明", () {
JumpUtil.jumpToPageRight(
context, RouterCenterImpl().findClueRouter().getProjectDetailsPage());
}));
return list;
}
......
......@@ -3,6 +3,7 @@
* @date 2019-10-13
**/
import 'package:app_settings/app_settings.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
......@@ -12,6 +13,7 @@ import 'package:flutter_svg/svg.dart';
import 'package:gm_flutter/commonModel/GMBase.dart';
import 'package:gm_flutter/commonModel/util/DartUtil.dart';
import 'package:gm_flutter/commonModel/view/ImagesAnimation.dart';
import 'package:lottie/lottie.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart';
double SCREENWIDTH;
......@@ -112,72 +114,97 @@ Widget baseDivideWidth(double width, double padding) {
}
Widget loadingItem({bool needBackground = false}) {
// return
// Center(
// child: Container(
// width: 77,
// height: 77,
// decoration: BoxDecoration(
// borderRadius: BorderRadius.circular(8),
// color: needBackground ? Colors.black : Colors.transparent),
// alignment: Alignment.center,
// child: MyCupertinoActivityIndicator(
// backColor: needBackground ? Colors.white : Colors.black,
// ),
// ));
return Center(
child: Container(
width: 77,
height: 77,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
color: needBackground ? Colors.black : Colors.transparent),
alignment: Alignment.center,
child: MyCupertinoActivityIndicator(
backColor: needBackground ? Colors.white : Colors.black,
child: Container(
width: 80,
height: 80,
child: Lottie.asset("assets/smart_refresh_header.json",
repeat: true, reverse: false),
),
));
);
}
Widget netErrorItem() {}
Widget errorItem(VoidCallback retry, {String errorText, String retryText}) {
Widget errorItem(double width, double height, VoidCallback retry,
{String errorText, String retryText}) {
return Container(
width: SCREENWIDTH,
height: SCREENHEIGHT,
width: width,
height: height,
color: Colors.white,
alignment: Alignment.center,
alignment: Alignment.topCenter,
child: Container(
height: SCREENHEIGHT,
child: Container(
margin: EdgeInsets.only(top: 70),
width: 175,
height: 249,
child: Stack(
children: <Widget>[
Positioned(
left: 0,
top: 0,
child: Container(
width: 175,
height: 199,
child: Image.asset("assets/error.png"),
),
),
Positioned(
left: 0,
top: 166,
child: Container(
width: 175,
alignment: Alignment.center,
child: baseText(errorText ?? "网络错误", 15, Color(0xff666666)),
),
),
Positioned(
top: 216,
left: 12,
child: Container(
width: 150,
height: 33,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(22.5),
color: Color(0xff51CDC7)),
alignment: Alignment.center,
child: baseText(retryText ?? "重新加载", 16, Colors.white),
).gestureDetector(() {
retry();
}),
)
],
width: 180,
height: 315.5,
margin: EdgeInsets.only(top: 62),
child: Stack(
alignment: AlignmentDirectional.center,
children: <Widget>[
Positioned(
left: 0,
top: 0,
child: Container(
width: 180,
height: 186.5,
child: Image.asset("assets/error.png"),
),
),
)));
Positioned(
top: 166,
child: Container(
width: 180,
alignment: Alignment.center,
child: baseText(
errorText ?? "原谅我一看到美人就不淡定", 15, Color(0xff666666)),
),
),
Positioned(
bottom: 60,
child: Container(
width: 150,
height: 40,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
gradient: LinearGradient(
colors: [Color(0xFFFF5963), Color(0xffFF7096)],
begin: FractionalOffset(1, 0),
end: FractionalOffset(0, 1))),
alignment: Alignment.center,
child: baseText(retryText ?? "重新加载", 16, Colors.white),
).gestureDetector(() {
retry();
}),
),
Positioned(
bottom: 0,
child: Container(
width: 150,
height: 40,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
border: Border.all(color: Color(0xffFF5963), width: 0.5)),
alignment: Alignment.center,
child: baseText("检查网络设置", 16, Color(0xffFF5963)),
).gestureDetector(() {
AppSettings.openWIFISettings();
}),
)
],
),
));
}
//TODO
......@@ -271,19 +298,23 @@ Widget baseRefreshView(RefreshController refreshController,
onRefresh: refresh,
footer: CustomFooter(
builder: (BuildContext context, LoadStatus mode) {
Widget body;
print("LOAD STATUE ${mode}");
if (mode == LoadStatus.idle) {
body = baseText("上拉加载更多", 12, Color(0xff545454));
} else if (mode == LoadStatus.loading) {
body = baseText("加载中", 12, Color(0xff545454));
} else if (mode == LoadStatus.failed) {
body = baseText("加载失败", 12, Color(0xff545454));
} else if (mode == LoadStatus.noMore) {
body = baseText("没有更多数据了", 12, Color(0xff545454));
}
else {
body = Container();
Widget body = Container();
// print("LOAD STATUE ${mode}");
// if (mode == LoadStatus.idle) {
// body = baseText("上拉加载更多", 12, Color(0xff545454));
// } else if (mode == LoadStatus.loading) {
// body = baseText("加载中", 12, Color(0xff545454));
// } else if (mode == LoadStatus.failed) {
// body = baseText("加载失败", 12, Color(0xff545454));
// } else if (mode == LoadStatus.noMore) {
// body = baseText("没有更多数据了", 12, Color(0xff545454));
// }
// else {
// body = Container();
// }
if (mode == LoadStatus.loading) {
body = Lottie.asset("assets/smart_refresh_header.json",
repeat: true, reverse: false);
}
return Container(
height: 55.0,
......@@ -306,26 +337,29 @@ Widget baseRefreshView(RefreshController refreshController,
Widget normalRefreshHeader() {
return CustomHeader(
builder: (BuildContext context, RefreshStatus mode) {
Widget body;
Widget body = Container();
// if (mode == RefreshStatus.idle) {
//
// } else
if (mode == RefreshStatus.refreshing) {
body = ImagesAnimation(
w: 46,
h: 15,
durationSeconds: 1500,
entry: ImagesAnimationEntry(1, 20, "assets/ptr_header_loading"));
// body = ImagesAnimation(
// w: 46,
// h: 15,
// durationSeconds: 1500,
// entry: ImagesAnimationEntry(1, 20, "assets/ptr_header_loading"));
body = Lottie.asset("assets/smart_refresh_header.json",
repeat: true, reverse: false);
}
// else if (mode == RefreshStatus.failed) {
// body = Text("Load Failed!Click retry!");
// }
else {
body = Image.asset(
"assets/ptr_header_loading01.png",
width: 46,
height: 15,
);
// body = Image.asset(
// "assets/ptr_header_loading01.png",
// width: 46,
// height: 15,
// );
}
return Container(
height: 55.0,
......@@ -335,22 +369,30 @@ Widget normalRefreshHeader() {
);
}
Widget emptyItem({String detail}) {
return Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
height: 210,
width: 210,
color: Colors.red,
),
Container(
margin: EdgeInsets.only(top: 8),
child: baseText(
detail == null ? "暂无消息,找人聊聊去" : detail, 15, Color(0xff9B9B9B)),
Widget emptyItem(double width, double height, {String detail}) {
return Container(
width: width,
height: height,
color: Colors.white,
alignment: Alignment.topCenter,
child: Container(
width: 175,
height: 188,
margin: EdgeInsets.only(top: 62.5),
child: Stack(
alignment: AlignmentDirectional.bottomCenter,
children: <Widget>[
Container(
width: 175,
height: 188,
child: Image.asset("assets/empty.png"),
),
Positioned(
bottom: 17,
child: baseText(detail ?? "此处太寂寥,转转别处吧", 15, Color(0xff666666)),
)
],
),
],
),
);
}
......@@ -15,6 +15,7 @@ class BasePopMenu extends StatefulWidget {
final int maxHeight;
final Widget child;
final BaseMenuListener listener;
final Function(double progress) proListener;
BasePopMenu(
{this.leftPos,
......@@ -23,11 +24,13 @@ class BasePopMenu extends StatefulWidget {
this.width,
this.height,
this.child,
this.listener});
this.listener,
this.proListener});
@override
State<StatefulWidget> createState() {
return BasePopMenuState();;
return BasePopMenuState();
;
}
}
......@@ -37,6 +40,7 @@ class BasePopMenuState extends State<BasePopMenu>
AnimationController animationController;
LiveData<double> _liveData = LiveData();
bool isOpen = false;
bool isDestory = false;
@override
void initState() {
......@@ -45,12 +49,15 @@ class BasePopMenuState extends State<BasePopMenu>
duration: const Duration(milliseconds: 300), vsync: this)
..addListener(() {
_liveData.notifyView(animation.value * widget.maxHeight);
if (widget.proListener != null && !isDestory) {
widget.proListener(animation.value);
}
});
animation = new Tween(begin: 0.0, end: 1.0).animate(animationController);
widget.listener.addListener(() {
if(widget.listener.isShow){
if (widget.listener.isShow) {
animationController.forward();
}else{
} else {
animationController.reverse();
}
});
......@@ -77,6 +84,7 @@ class BasePopMenuState extends State<BasePopMenu>
@override
void dispose() {
isDestory = true;
_liveData.dispost();
animationController.dispose();
super.dispose();
......
......@@ -4,13 +4,16 @@ import 'package:flutter/material.dart';
import 'package:flutter_boost/flutter_boost.dart';
import 'package:flutter_common/Annotations/anno/RouterCenter.dart';
import 'package:flutter_common/commonModel/util/WindowUtil.dart';
import 'package:gm_flutter/commonModel/base/BaseComponent.dart';
import 'package:gm_flutter/main.mark.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:gm_flutter/ClueModel/page/PlanCompareDetail/PlanCompareDetailPage.dart';
import 'DemoPage.dart';
import 'DemoPage1.dart';
import 'commonModel/base/BaseComponent.dart';
import 'commonModel/base/BaseUtil.dart';
import 'commonModel/cache/CacheManager.dart';
import 'commonModel/nav/NavigationService.dart';
import 'main.mark.dart';
NavigationService navigationService;
......@@ -31,6 +34,9 @@ void main() {
runApp(
MyAppWidget(),
);
SharedPreferences.getInstance().then((value) {
sharedPreferences = value;
});
RouterCenterImpl().findMainRouter().init();
}, (Object error, StackTrace stack) {
//TODO
......@@ -77,11 +83,11 @@ class MyApp extends State<MyAppWidget> {
home: isDebug
? RouterCenterImpl().findMainRouter().getTestPage()
: Container(
color: Colors.white,
child: Center(
child: loadingItem(),
),
));
color: Colors.white,
child: Center(
child: loadingItem(),
),
));
}
void _onRoutePushed(
......
......@@ -15,6 +15,13 @@ packages:
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.39.10"
app_settings:
dependency: "direct main"
description:
name: app_settings
url: "https://pub.flutter-io.cn"
source: hosted
version: "4.0.1+1"
archive:
dependency: transitive
description:
......@@ -106,6 +113,13 @@ packages:
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.2.0+1"
characters:
dependency: transitive
description:
name: characters
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.0.0"
charcode:
dependency: transitive
description:
......@@ -203,7 +217,7 @@ packages:
name: file
url: "https://pub.flutter-io.cn"
source: hosted
version: "5.2.0"
version: "5.2.1"
fixnum:
dependency: transitive
description:
......@@ -356,6 +370,13 @@ packages:
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.11.4"
lottie:
dependency: "direct main"
description:
name: lottie
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.4.0+1"
matcher:
dependency: transitive
description:
......@@ -460,7 +481,7 @@ packages:
name: permission_handler
url: "https://pub.flutter-io.cn"
source: hosted
version: "5.0.1"
version: "5.0.1+1"
permission_handler_platform_interface:
dependency: transitive
description:
......@@ -530,7 +551,7 @@ packages:
name: pull_to_refresh
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.5.8"
version: "1.6.0"
quiver:
dependency: transitive
description:
......
......@@ -31,6 +31,8 @@ dependencies:
permission_handler: ^5.0.0
#轻量级存储
shared_preferences: ^0.5.7+1
lottie: ^0.4.0+1
app_settings: ^4.0.1+1
dev_dependencies:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment