YSChildBody.dart 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431
  1. import 'package:fl_chart/fl_chart.dart';
  2. import 'package:flutter/cupertino.dart';
  3. import 'package:flutter/material.dart';
  4. import 'package:flutterappfuyou/code/base/YSNetWorking.dart';
  5. import 'package:flutterappfuyou/code/base/YSTools.dart';
  6. import 'package:shared_preferences/shared_preferences.dart';
  7. import 'YSAddChildBody.dart';
  8. import 'base/YSBase.dart';
  9. class YSChildBody extends StatefulWidget {
  10. @override
  11. _YSChildBodyState createState() => _YSChildBodyState();
  12. }
  13. class _YSChildBodyState extends State<YSChildBody> {
  14. int _selected = 0;
  15. PageController _page = PageController();
  16. List _dataArray = [];
  17. List heightMin = <FlSpot>[];
  18. List heightMax = <FlSpot>[];
  19. List weightMin = <FlSpot>[];
  20. List weightMax = <FlSpot>[];
  21. List hAxis = [];
  22. List wAxis = [];
  23. @override
  24. void initState() {
  25. Future.delayed(Duration(seconds: 0)).then((value){
  26. _getChildBodyData();
  27. _getChildData();
  28. });
  29. super.initState();
  30. }
  31. @override
  32. Widget build(BuildContext context) {
  33. return YSBase(
  34. ystitle: '身高体重',
  35. ysright: CupertinoButton(
  36. padding: EdgeInsets.all(0),
  37. child: Container(
  38. height: 30,
  39. width: 55,
  40. decoration: BoxDecoration(
  41. color: Color(0xFFFFEB3B),
  42. border: Border.all(color: Color(0xFF292929),width: 1),
  43. borderRadius: BorderRadius.all(Radius.circular(20))
  44. ),
  45. alignment: Alignment.center,
  46. child: Text('添加',style: TextStyle(fontSize: 14,color: Color(0xFF292929),decoration: TextDecoration.none),),
  47. ),
  48. onPressed: (){
  49. Navigator.of(context).push(
  50. CupertinoPageRoute(
  51. builder: (context){
  52. return YSAddChildBody();
  53. }
  54. )
  55. ).then((value){
  56. if(value!=null){
  57. _getChildBodyData();
  58. }
  59. });
  60. },
  61. ),
  62. yschild: SingleChildScrollView(
  63. child: Column(
  64. children: [
  65. Container(
  66. height: 50,
  67. decoration: BoxDecoration(
  68. color: Colors.white,
  69. borderRadius: BorderRadius.only(topRight: Radius.circular(20),topLeft: Radius.circular(20)),
  70. ),
  71. padding: EdgeInsets.only(left: 20,right: 20,top: 15),
  72. child: Column(
  73. crossAxisAlignment: CrossAxisAlignment.start,
  74. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  75. children: [
  76. Row(
  77. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  78. children: [
  79. GestureDetector(
  80. // child: Text('身高体重',style: TextStyle(fontSize: 14,color: _selected==0?Color(0xFFDB5279):Color(0xFF808080)),),
  81. onTap: (){
  82. _page.jumpToPage(0);
  83. setState(() {
  84. _selected = 0;
  85. });
  86. },
  87. child: Column(
  88. children: [
  89. Text('身高体重',style: TextStyle(fontSize: 14,color: _selected==0?Color(0xFFDB5279):Color(0xFF808080)),),
  90. Container(
  91. margin: EdgeInsets.only(top: 10),
  92. height: 2,width: 30,color: _selected==0?Color(0xFFDB5279):Colors.transparent
  93. )
  94. ],
  95. ),
  96. ),
  97. GestureDetector(
  98. // child: Text('身高曲线',style: TextStyle(fontSize: 14,color: _selected==1?Color(0xFFDB5279):Color(0xFF808080)),),
  99. onTap: (){
  100. _page.jumpToPage(1);
  101. setState(() {
  102. _selected = 1;
  103. });
  104. },
  105. child: Column(
  106. children: [
  107. Text('身高曲线',style: TextStyle(fontSize: 14,color: _selected==1?Color(0xFFDB5279):Color(0xFF808080)),),
  108. Container(
  109. margin: EdgeInsets.only(top: 10),
  110. height: 2,width: 30,color: _selected==1?Color(0xFFDB5279):Colors.transparent
  111. )
  112. ],
  113. ),
  114. ),
  115. GestureDetector(
  116. // child: Text('体重曲线',style: TextStyle(fontSize: 14,color: _selected==2?Color(0xFFDB5279):Color(0xFF808080)),),
  117. onTap: (){
  118. _page.jumpToPage(2);
  119. setState(() {
  120. _selected = 2;
  121. });
  122. },
  123. child: Column(
  124. children: [
  125. Text('体重曲线',style: TextStyle(fontSize: 14,color: _selected==2?Color(0xFFDB5279):Color(0xFF808080)),),
  126. Container(
  127. margin: EdgeInsets.only(top: 10),
  128. height: 2,width: 30,color: _selected==2?Color(0xFFDB5279):Colors.transparent
  129. )
  130. ],
  131. ),
  132. ),
  133. ],
  134. ),
  135. // Container(height: 2,width: 30,color: Color(0xFFDB5279),
  136. // margin: EdgeInsets.only(left: _selected==0?15:_selected==1?MediaQuery.of(context).size.width/3+25:MediaQuery.of(context).size.width/3*2+40),)
  137. ],
  138. ),
  139. ),
  140. Container(
  141. height: MediaQuery.of(context).size.height-125,
  142. child: PageView(
  143. controller: _page,
  144. onPageChanged: (index){
  145. setState(() {
  146. _selected = index;
  147. });
  148. },
  149. children: [
  150. Container(
  151. height: MediaQuery.of(context).size.height-125,
  152. child: RefreshIndicator(
  153. onRefresh: _getChildBodyData,
  154. child: ListView.separated(
  155. itemBuilder: (context,index){
  156. return GestureDetector(
  157. onTap: (){
  158. Navigator.of(context).push(
  159. CupertinoPageRoute(
  160. builder: (context){
  161. return YSAddChildBody(infoDict: _dataArray[index],);
  162. }
  163. )
  164. ).then((value){
  165. if(value!=null){
  166. _getChildBodyData();
  167. }
  168. });
  169. },
  170. child: Container(
  171. height: 110,
  172. padding: EdgeInsets.all(15),
  173. decoration: BoxDecoration(
  174. color: Colors.white,
  175. borderRadius: BorderRadius.all(Radius.circular(6))
  176. ),
  177. child: Column(
  178. crossAxisAlignment: CrossAxisAlignment.start,
  179. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  180. children: [
  181. Text('${_dataArray[index]['created_at']}',style: TextStyle(fontSize: 14,color: Color(0xFF292929)),overflow: TextOverflow.ellipsis,),
  182. Text('宝宝出生的第${_dataArray[index]['month_age']}月',style: TextStyle(fontSize: 14,color: Color(0xFF808080)),overflow: TextOverflow.ellipsis,),
  183. Container(
  184. width: MediaQuery.of(context).size.width,
  185. height: 1.5,
  186. child: Image.asset('lib/images/line.png'),
  187. ),
  188. Container(
  189. child: Row(
  190. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  191. children: [
  192. RichText(
  193. text: TextSpan(
  194. style: TextStyle(fontSize: 14,color: Color(0xFF292929)),
  195. children: [
  196. TextSpan(text: '身高'),
  197. TextSpan(text: ' ${_dataArray[index]['height']} ',style: TextStyle(color: Color(0xFFDB5279))),
  198. TextSpan(text: 'CM'),
  199. ]
  200. ),
  201. ),
  202. RichText(
  203. text: TextSpan(
  204. style: TextStyle(fontSize: 14,color: Color(0xFF292929)),
  205. children: [
  206. TextSpan(text: '体重'),
  207. TextSpan(text: ' ${_dataArray[index]['weight']} ',style: TextStyle(color: Color(0xFFDB5279))),
  208. TextSpan(text: 'KG'),
  209. ]
  210. ),
  211. )
  212. ],
  213. ),
  214. )
  215. ],
  216. ),
  217. ),
  218. );
  219. },
  220. separatorBuilder: (context,index){
  221. return Divider(height: 5,thickness: 5,color: Color(0xFFF5F3F0),);
  222. },
  223. itemCount: _dataArray.length,
  224. padding: EdgeInsets.all(5),
  225. ),
  226. ),
  227. ),
  228. Container(
  229. height: MediaQuery.of(context).size.height-115,
  230. margin: EdgeInsets.all(5),
  231. padding: EdgeInsets.only(top: 10,bottom: 10,left: 15,right: 15),
  232. color: Colors.white,
  233. child: Column(
  234. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  235. crossAxisAlignment: CrossAxisAlignment.start,
  236. children: [
  237. // Text('宝宝今日正常身高范围: $heightMin~$heightMax cm',style: TextStyle(fontSize: 16,color: Color(0xFF292929)),overflow: TextOverflow.ellipsis,),
  238. Text('彩色区域为正常范围',style: TextStyle(fontSize: 12,color: Color(0xFFDB5279)),overflow: TextOverflow.ellipsis,),
  239. Container(
  240. width: MediaQuery.of(context).size.width,
  241. height: 1.5,
  242. child: Image.asset('lib/images/line.png'),
  243. ),
  244. Text('身高(cm)',style: TextStyle(fontSize: 11,color: Color(0xFF808080)),overflow: TextOverflow.ellipsis,),
  245. Container(
  246. height: MediaQuery.of(context).size.height-230,
  247. child: _dataArray.length==0||hAxis.length==0?Container():LineChartSample7(axis: hAxis,min: heightMin,max: heightMax,data: _dataArray,type: 1,),
  248. )
  249. ],
  250. ),
  251. ),
  252. Container(
  253. height: MediaQuery.of(context).size.height-115,
  254. margin: EdgeInsets.all(5),
  255. padding: EdgeInsets.only(top: 10,bottom: 10,left: 15,right: 15),
  256. color: Colors.white,
  257. child: Column(
  258. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  259. crossAxisAlignment: CrossAxisAlignment.start,
  260. children: [
  261. // Text('宝宝今日正常体重范围: $weightMin~$weightMax kg',style: TextStyle(fontSize: 16,color: Color(0xFF292929)),overflow: TextOverflow.ellipsis,),
  262. Text('彩色区域为正常范围',style: TextStyle(fontSize: 12,color: Color(0xFFDB5279)),overflow: TextOverflow.ellipsis,),
  263. Container(
  264. width: MediaQuery.of(context).size.width,
  265. height: 1.5,
  266. child: Image.asset('lib/images/line.png'),
  267. ),
  268. Text('体重(kg)',style: TextStyle(fontSize: 11,color: Color(0xFF808080)),overflow: TextOverflow.ellipsis,),
  269. Container(
  270. height: MediaQuery.of(context).size.height-230,
  271. child: _dataArray.length==0||wAxis.length==0?Container():LineChartSample7(axis: wAxis,min: weightMin,max: weightMax,data: _dataArray,type: 2,),
  272. )
  273. ],
  274. ),
  275. ),
  276. ],
  277. ),
  278. )
  279. ],
  280. ),
  281. ),
  282. );
  283. }
  284. Future<void> _getChildBodyData() async{
  285. SharedPreferences prefer = await SharedPreferences.getInstance();
  286. Map dict = await ysRequestHttp(context, requestType.get, 'child/body/list', {'child_id':prefer.getInt('childId')});
  287. if(dict!=null){
  288. setState(() {
  289. _dataArray = dict['data'];
  290. });
  291. }
  292. }
  293. _getChildData() async{
  294. SharedPreferences prefer = await SharedPreferences.getInstance();
  295. var dict = await ysRequestHttpNoLoading(context, requestType.get, 'chapter/info', {'category_id':prefer.getInt('chapters')+1,'child_id':prefer.getInt('childId')});
  296. if(dict!=null){
  297. _getHeightStandardData(dict['data']['gender']=='男'?1:2);
  298. }
  299. }
  300. _getHeightStandardData(int type) async{
  301. var dict = await ysRequestHttpNoLoading(context, requestType.get, 'basic/BodyStandard', {'body_type':'child','type':'height','gender':type});
  302. if(dict!=null){
  303. hAxis = dict['name'];
  304. heightMin = dict['min'];
  305. heightMax = dict['max'];
  306. LogUtil.d(hAxis);
  307. _getWeightStandardData(type);
  308. }
  309. }
  310. _getWeightStandardData(int type) async{
  311. var dict = await ysRequestHttpNoLoading(context, requestType.get, 'basic/BodyStandard', {'body_type':'child','type':'weight','gender':type});
  312. if(dict!=null){
  313. wAxis = dict['name'];
  314. weightMin = dict['min'];
  315. weightMax = dict['max'];
  316. }
  317. }
  318. }
  319. class LineChartSample7 extends StatelessWidget {
  320. final List axis,min,max,data;
  321. final int type;
  322. const LineChartSample7({Key key, this.axis, this.min, this.max,this.data,this.type}) : super(key: key);
  323. @override
  324. Widget build(BuildContext context) {
  325. LogUtil.d(data);
  326. return SingleChildScrollView(
  327. padding: EdgeInsets.only(top: 5),
  328. scrollDirection: Axis.horizontal,
  329. child: SizedBox(
  330. width: (MediaQuery.of(context).size.width-40)*4,
  331. child: LineChart(
  332. LineChartData(
  333. lineTouchData: LineTouchData(enabled: false),
  334. lineBarsData: [
  335. LineChartBarData(
  336. spots: [
  337. for(int i = 0;i<axis.length;i++)FlSpot(double.parse('${axis[i]}'),double.parse('${min[i]}'))
  338. ],
  339. isCurved: true,
  340. barWidth: 2,
  341. colors: [
  342. Colors.transparent,
  343. ],
  344. dotData: FlDotData(
  345. show: false,
  346. ),
  347. ),
  348. LineChartBarData(
  349. spots: [
  350. for(int i = 0;i<axis.length;i++)FlSpot(double.parse('${axis[i]}'),double.parse('${max[i]}'))
  351. ],
  352. isCurved: true,
  353. barWidth: 2,
  354. colors: [
  355. Colors.transparent,
  356. ],
  357. dotData: FlDotData(
  358. show: false,
  359. ),
  360. ),
  361. LineChartBarData(
  362. spots: [
  363. for(int i = 0;i<data.length;i++)FlSpot(double.parse('${data[i]['month_age']}'),double.parse('${type==1?data[i]['height']:data[i]['weight']}'))
  364. ],
  365. isCurved: true,
  366. barWidth: 2,
  367. colors: [
  368. Colors.lightGreen,
  369. ],
  370. dotData: FlDotData(
  371. show: true,
  372. ),
  373. ),
  374. ],
  375. betweenBarsData: [
  376. BetweenBarsData(
  377. fromIndex: 0,
  378. toIndex: 1,
  379. colors: [Colors.red.withOpacity(0.3)],
  380. )
  381. ],
  382. minY: 0,
  383. titlesData: FlTitlesData(
  384. bottomTitles: SideTitles(
  385. interval: 3,
  386. showTitles: true,
  387. getTitles: (value) {
  388. return value.toInt().toString()+'月';
  389. },
  390. ),
  391. leftTitles: SideTitles(
  392. showTitles: true,
  393. getTitles: (value) {
  394. return value%3==0?value.toInt().toString():'';
  395. },
  396. ),
  397. rightTitles: SideTitles(
  398. showTitles: true,
  399. getTitles: (value) {
  400. return value%3==0?value.toInt().toString():'';
  401. },
  402. ),
  403. ),
  404. gridData: FlGridData(
  405. show: true,
  406. checkToShowHorizontalLine: (double value) {
  407. return value%3==0;
  408. },
  409. checkToShowVerticalLine: (double value) {
  410. return value%3==0;
  411. },
  412. drawVerticalLine: true,
  413. drawHorizontalLine: true,
  414. verticalInterval: 1,
  415. horizontalInterval: 1,
  416. // drawVerticalLine: true
  417. ),
  418. ),
  419. ),
  420. ),
  421. );
  422. }
  423. }