YSTools.dart 80 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111
  1. import 'dart:convert';
  2. import 'dart:math';
  3. import 'dart:ui';
  4. import 'package:flutter/cupertino.dart';
  5. import 'package:flutter/foundation.dart';
  6. import 'package:flutter/material.dart';
  7. import 'package:flutter/services.dart';
  8. import 'package:package_info/package_info.dart';
  9. import 'package:url_launcher/url_launcher.dart';
  10. import 'package:webview_flutter/webview_flutter.dart';
  11. import 'package:ysairplane2/code/YSLogin.dart';
  12. import 'package:flutter_screenutil/screenutil.dart';
  13. import 'package:shared_preferences/shared_preferences.dart';
  14. import 'dart:math' as math;
  15. import 'package:ysairplane2/tools/YSNetWorking.dart';
  16. class YSDatePicker extends StatefulWidget {
  17. final ValueSetter<String> choose;
  18. final bool isBefore;
  19. final bool isDate;
  20. const YSDatePicker({Key key, this.choose, this.isBefore, this.isDate = false}) : super(key: key);
  21. @override
  22. _YSDatePickerState createState() => _YSDatePickerState();
  23. }
  24. class _YSDatePickerState extends State<YSDatePicker> {
  25. String birthday = DateTime.now().year.toString()+'-'+DateTime.now().month.toString().padLeft(2,'0')+'-'+DateTime.now().day.toString().padLeft(2,'0')+' '+
  26. DateTime.now().hour.toString().padLeft(2,'0')+':'+DateTime.now().minute.toString().padLeft(2,'0');
  27. @override
  28. void initState() {
  29. if(widget.isDate==true){
  30. birthday = DateTime.now().year.toString()+'-'+DateTime.now().month.toString().padLeft(2,'0')+'-'+DateTime.now().day.toString().padLeft(2,'0');
  31. }
  32. super.initState();
  33. }
  34. @override
  35. Widget build(BuildContext context) {
  36. return Container(
  37. color: Colors.transparent,
  38. height: 280,
  39. child: Column(
  40. crossAxisAlignment: CrossAxisAlignment.end,
  41. children: [
  42. Container(
  43. height: 40,
  44. padding: EdgeInsets.only(left: wsp(40),right: wsp(40)),
  45. decoration: BoxDecoration(
  46. color: Colors.white,
  47. border: Border(bottom: BorderSide(width: 0.5,color: Color(0xFFEEEEEE)))
  48. ),
  49. child: Row(
  50. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  51. children: [
  52. GestureDetector(
  53. child: Text('取消',style: TextStyle(fontSize: zsp(30),color: Color(0xFF999999)),),
  54. onTap: (){
  55. Navigator.pop(context);
  56. },
  57. ),
  58. GestureDetector(
  59. child: Text('确定',style: TextStyle(fontSize: zsp(30),color: Color(0xFF108DE9)),),
  60. onTap: (){
  61. widget.choose(birthday);
  62. Navigator.pop(context);
  63. },
  64. )
  65. ],
  66. ),
  67. ),
  68. Container(
  69. height: 240,
  70. padding: EdgeInsets.all(10),
  71. decoration: BoxDecoration(
  72. color: Colors.white,
  73. borderRadius: BorderRadius.only(topLeft: Radius.circular(20),topRight: Radius.circular(20))
  74. ),
  75. child: CupertinoDatePicker(
  76. initialDateTime: DateTime.now(),
  77. use24hFormat: true,
  78. minimumDate: widget.isBefore==true?null:DateTime.parse(DateTime.now().year.toString()+'-'+DateTime.now().month.toString().padLeft(2,'0')+'-'+
  79. DateTime.now().day.toString().padLeft(2,'0')+' '+
  80. DateTime.now().hour.toString().padLeft(2,'0')+':'+DateTime.now().minute.toString().padLeft(2,'0')),
  81. onDateTimeChanged: (date) {
  82. if(widget.isDate==true){
  83. birthday = date.year.toString()+'-'+date.month.toString().padLeft(2,'0')+'-'+date.day.toString().padLeft(2,'0');
  84. }else{
  85. birthday = date.year.toString()+'-'+date.month.toString().padLeft(2,'0')+'-'+date.day.toString().padLeft(2,'0')+' '+
  86. date.hour.toString().padLeft(2,'0')+':'+date.minute.toString().padLeft(2,'0');
  87. }
  88. },
  89. mode: widget.isDate==true?CupertinoDatePickerMode.date:CupertinoDatePickerMode.dateAndTime,
  90. ),
  91. ),
  92. ],
  93. ),
  94. );
  95. }
  96. }
  97. class BottomInputDialog extends StatefulWidget {
  98. final Widget inputView;
  99. final double height;
  100. final Color color;
  101. const BottomInputDialog({Key key, this.inputView,this.height,this.color}) : super(key: key);
  102. @override
  103. _State createState() => _State();
  104. }
  105. class _State extends State<BottomInputDialog> with WidgetsBindingObserver{
  106. @override
  107. void initState() {
  108. WidgetsBinding.instance.addObserver(this);
  109. super.initState();
  110. }
  111. @override
  112. void didChangeMetrics() {
  113. WidgetsBinding.instance.addPostFrameCallback((_) {
  114. if(MediaQuery.of(context).viewInsets.bottom <= 0){
  115. Navigator.pop(context);
  116. if (!mounted) {
  117. return;
  118. }
  119. WidgetsBinding.instance.removeObserver(this);
  120. }
  121. });
  122. super.didChangeMetrics();
  123. }
  124. @override
  125. void dispose() {
  126. super.dispose();
  127. if (!mounted) {
  128. return;
  129. }
  130. WidgetsBinding.instance.removeObserver(this);
  131. }
  132. @override
  133. Widget build(BuildContext context) {
  134. return CupertinoPageScaffold(
  135. backgroundColor: Colors.transparent,
  136. child: Stack(
  137. children: <Widget>[
  138. GestureDetector(
  139. child: BackdropFilter(
  140. filter: ImageFilter.blur(sigmaX: 3, sigmaY: 3),
  141. child: Container(
  142. height: MediaQuery.of(context).size.height,
  143. color: widget.color!=null?widget.color:Colors.black12.withOpacity(0.8),
  144. ),
  145. ),
  146. onTap: () {
  147. Navigator.pop(context);
  148. if (!mounted) {
  149. return;
  150. }
  151. WidgetsBinding.instance.removeObserver(this);
  152. },
  153. ),
  154. Container(
  155. margin: EdgeInsets.only(top: MediaQuery.of(context).size.height-widget.height-MediaQuery.of(context).viewInsets.bottom),
  156. height: widget.height,
  157. decoration: BoxDecoration(
  158. color: Colors.white,
  159. borderRadius: BorderRadius.only(topLeft: Radius.circular(10),topRight: Radius.circular(10)),
  160. boxShadow: [
  161. BoxShadow(
  162. color: Colors.black12,
  163. offset: Offset(-1, -3),
  164. blurRadius: 5
  165. )
  166. ]
  167. ),
  168. padding: EdgeInsets.all(10),
  169. child: widget.inputView,
  170. )
  171. ],
  172. ),
  173. );
  174. }
  175. }
  176. class PopRoute extends PopupRoute{
  177. final Duration _duration = Duration(milliseconds: 300);
  178. Widget child;
  179. PopRoute({@required this.child});
  180. @override
  181. Color get barrierColor => null;
  182. @override
  183. bool get barrierDismissible => true;
  184. @override
  185. String get barrierLabel => null;
  186. @override
  187. Widget buildPage(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
  188. return child;
  189. }
  190. @override
  191. Duration get transitionDuration => _duration;
  192. }
  193. wsp(int number){
  194. return ScreenUtil().setWidth(number);
  195. }
  196. hsp(int number){
  197. return ScreenUtil().setHeight(number);
  198. }
  199. zsp(int number){
  200. return ScreenUtil().setSp(number,allowFontScalingSelf: false);
  201. }
  202. isLogin(BuildContext context,{VoidCallback login}) async{
  203. SharedPreferences prefs = await SharedPreferences.getInstance();
  204. String token = prefs.getString('token');
  205. if(token==null){
  206. Navigator.of(context,rootNavigator: true).push(
  207. CupertinoPageRoute(
  208. fullscreenDialog: true,
  209. builder: (context){
  210. return YSLogin();
  211. }
  212. )
  213. ).then((value){
  214. if(value!=null){
  215. login();
  216. }
  217. });
  218. }else{
  219. login();
  220. }
  221. }
  222. ///手机号验证
  223. bool isChinaPhoneLegal(String str) {
  224. return RegExp(r"^1([38][0-9]|4[579]|5[0-3,5-9]|6[6]|7[0135678]|9[89])\d{8}$").hasMatch(str);
  225. }
  226. ///邮箱验证
  227. bool isEmail(String str) {
  228. return RegExp(r"^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$").hasMatch(str);
  229. }
  230. ///验证URL
  231. bool isUrl(String value) {
  232. return RegExp(r"^((https|http|ftp|rtsp|mms)?:\/\/)[^\s]+").hasMatch(value);
  233. }
  234. ///验证身份证
  235. bool isIdCard(String value) {
  236. return RegExp(r"\d{17}[\d|x]|\d{15}").hasMatch(value);
  237. }
  238. ///验证中文
  239. bool isChinese(String value) {
  240. return RegExp(r"[\u4e00-\u9fa5]").hasMatch(value);
  241. }
  242. class LogUtil {
  243. static var _separator = "=";
  244. static var _split =
  245. "$_separator$_separator$_separator$_separator$_separator$_separator$_separator$_separator$_separator";
  246. static var _title = "Yl-Log";
  247. static var _isDebug = true;
  248. static int _limitLength = 800;
  249. static String _startLine = "$_split$_title$_split";
  250. static String _endLine = "$_split$_separator$_separator$_separator$_split";
  251. static void init({String title, @required bool isDebug,int limitLength}) {
  252. _title = title;
  253. _isDebug = isDebug;
  254. _limitLength = limitLength??=_limitLength;
  255. _startLine = "$_split$_title$_split";
  256. var endLineStr = StringBuffer();
  257. var cnCharReg = RegExp("[\u4e00-\u9fa5]");
  258. for (int i = 0; i < _startLine.length; i++) {
  259. if (cnCharReg.stringMatch(_startLine[i]) != null) {
  260. endLineStr.write(_separator);
  261. }
  262. endLineStr.write(_separator);
  263. }
  264. _endLine = endLineStr.toString();
  265. }
  266. //仅Debug模式可见
  267. static void d(dynamic obj) {
  268. if (_isDebug) {
  269. _log(obj.toString());
  270. }
  271. }
  272. static void v(dynamic obj) {
  273. _log(obj.toString());
  274. }
  275. static void _log(String msg) {
  276. print("$_startLine");
  277. _logEmpyLine();
  278. if(msg.length<_limitLength){
  279. print(msg);
  280. }else{
  281. segmentationLog(msg);
  282. }
  283. _logEmpyLine();
  284. print("$_endLine");
  285. }
  286. static void segmentationLog(String msg) {
  287. var outStr = StringBuffer();
  288. for (var index = 0; index < msg.length; index++) {
  289. outStr.write(msg[index]);
  290. if (index % _limitLength == 0 && index!=0) {
  291. print(outStr);
  292. outStr.clear();
  293. var lastIndex = index+1;
  294. if(msg.length-lastIndex<_limitLength){
  295. var remainderStr = msg.substring(lastIndex,msg.length);
  296. print(remainderStr);
  297. break;
  298. }
  299. }
  300. }
  301. }
  302. static void _logEmpyLine(){
  303. print("");
  304. }
  305. }
  306. //indicate
  307. Widget indicateString(String longStr,String str,String otherStr){
  308. List strings = longStr.split(str);
  309. print(strings);
  310. return Container(
  311. child: RichText(
  312. text: longStr!=str?TextSpan(
  313. children:
  314. [
  315. for(int i = 0;i<strings.length;i++)TextSpan(
  316. children: [
  317. TextSpan(
  318. text: strings[i]==''?str:strings[i],
  319. style: TextStyle(fontSize: zsp(32),color: strings[i]==''?Color(0xFF007AFF):Color(0xFF444444)),
  320. ),
  321. ]
  322. ),
  323. TextSpan(
  324. text: ' $otherStr',
  325. style: TextStyle(fontSize: zsp(26),color: Color(0xFF999999)),
  326. )
  327. ]
  328. ):TextSpan(
  329. children:[
  330. TextSpan(
  331. text: longStr,
  332. style: TextStyle(fontSize: zsp(32),color: Color(0xFF007AFF)),
  333. ),
  334. TextSpan(
  335. text: ' $otherStr',
  336. style: TextStyle(fontSize: zsp(26),color: Color(0xFF999999)),
  337. )
  338. ]
  339. ),
  340. ),
  341. );
  342. }
  343. class ExpandableText extends StatefulWidget {
  344. final String text;
  345. final int maxLines;
  346. final TextStyle style;
  347. final bool expand;
  348. const ExpandableText({Key key, this.text, this.maxLines, this.style, this.expand}) : super(key: key);
  349. @override
  350. State<StatefulWidget> createState() {
  351. return _ExpandableTextState(text, maxLines, style, expand);
  352. }
  353. }
  354. class _ExpandableTextState extends State<ExpandableText> {
  355. final String text;
  356. final int maxLines;
  357. final TextStyle style;
  358. bool expand;
  359. _ExpandableTextState(this.text, this.maxLines, this.style, this.expand) {
  360. if (expand == null) {
  361. expand = false;
  362. }
  363. }
  364. @override
  365. Widget build(BuildContext context) {
  366. return LayoutBuilder(builder: (context, size) {
  367. final span = TextSpan(text: text ?? '', style: style);
  368. final tp = TextPainter(
  369. text: span, maxLines: maxLines, textDirection: TextDirection.ltr);
  370. tp.layout(maxWidth: size.maxWidth);
  371. if (tp.didExceedMaxLines) {
  372. return Column(
  373. crossAxisAlignment: CrossAxisAlignment.start,
  374. children: <Widget>[
  375. expand ?
  376. Text(text ?? '', style: style) :
  377. Text(text ?? '', maxLines: maxLines,overflow: TextOverflow.ellipsis,style: style),
  378. GestureDetector(
  379. behavior: HitTestBehavior.translucent,
  380. onTap: () {
  381. setState(() {
  382. expand = !expand;
  383. });
  384. },
  385. child: Container(
  386. padding: EdgeInsets.only(top: 2),
  387. child: Text(expand ? '收起' : '全文', style: TextStyle(
  388. fontSize: style != null ? style.fontSize : null,
  389. color: Colors.blue)),
  390. ),
  391. ),
  392. ],
  393. );
  394. } else {
  395. return Text(text ?? '', style: style);
  396. }
  397. });
  398. }
  399. }
  400. Widget ysTextExpend({String text,int maxLines,TextStyle style,bool expand = false}) {
  401. return StatefulBuilder(
  402. builder: (context,ysState){
  403. return LayoutBuilder(builder: (context, size) {
  404. final span = TextSpan(text: text ?? '', style: style);
  405. final tp = TextPainter(
  406. text: span, maxLines: maxLines, textDirection: TextDirection.ltr);
  407. tp.layout(maxWidth: size.maxWidth);
  408. if (tp.didExceedMaxLines) {
  409. return Column(
  410. crossAxisAlignment: CrossAxisAlignment.start,
  411. children: <Widget>[
  412. expand ?
  413. Text(text ?? '', style: style) :
  414. Text(text ?? '', maxLines: maxLines,
  415. overflow: TextOverflow.ellipsis,
  416. style: style),
  417. GestureDetector(
  418. behavior: HitTestBehavior.translucent,
  419. onTap: () {
  420. ysState(() {
  421. expand = !expand;
  422. });
  423. },
  424. child: Container(
  425. padding: EdgeInsets.only(top: 2),
  426. child: Text(expand ? '收起' : '全文', style: TextStyle(
  427. fontSize: style != null ? style.fontSize : null,
  428. color: Colors.blue)),
  429. ),
  430. ),
  431. ],
  432. );
  433. } else {
  434. return Text(text ?? '', style: style);
  435. }
  436. });
  437. },
  438. );
  439. }
  440. class YSPicker extends StatefulWidget {
  441. final ValueSetter choose;
  442. final List dataArray;
  443. final String title;
  444. const YSPicker({Key key, this.choose, this.dataArray, this.title}) : super(key: key);
  445. @override
  446. _YSPickerState createState() => _YSPickerState();
  447. }
  448. class _YSPickerState extends State<YSPicker> {
  449. var _value;
  450. @override
  451. Widget build(BuildContext context) {
  452. _value = widget.dataArray[0];
  453. return Container(
  454. color: Colors.transparent,
  455. height: hsp(600),
  456. child: Column(
  457. crossAxisAlignment: CrossAxisAlignment.end,
  458. children: [
  459. Container(
  460. height: hsp(100),
  461. padding: EdgeInsets.only(left: wsp(40),right: wsp(40)),
  462. decoration: BoxDecoration(
  463. color: Colors.white,
  464. border: Border(bottom: BorderSide(width: 0.5,color: Color(0xFFEEEEEE)))
  465. ),
  466. child: Row(
  467. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  468. children: [
  469. GestureDetector(
  470. child: Text('取消',style: TextStyle(fontSize: zsp(30),color: Color(0xFF999999)),),
  471. onTap: (){
  472. Navigator.pop(context);
  473. },
  474. ),
  475. GestureDetector(
  476. child: Text('确定',style: TextStyle(fontSize: zsp(30),color: Color(0xFF108DE9)),),
  477. onTap: (){
  478. widget.choose(_value);
  479. Navigator.pop(context);
  480. },
  481. )
  482. ],
  483. ),
  484. ),
  485. Container(
  486. height: hsp(500),
  487. padding: EdgeInsets.all(10),
  488. decoration: BoxDecoration(
  489. color: Colors.white,
  490. borderRadius: BorderRadius.only(topLeft: Radius.circular(20),topRight: Radius.circular(20))
  491. ),
  492. child: CupertinoPicker(
  493. children: [
  494. for(int i=0;i<widget.dataArray.length;i++)Container(
  495. alignment: Alignment.center,
  496. child: Text('${widget.dataArray[i][widget.title]}'),
  497. )
  498. ],
  499. itemExtent: hsp(100),
  500. onSelectedItemChanged: (value){
  501. _value = widget.dataArray[value];
  502. },
  503. ),
  504. ),
  505. ],
  506. ),
  507. );
  508. }
  509. }
  510. timeTag(String time) {
  511. DateTime date = DateTime(DateTime.parse('$time').year,DateTime.parse('$time').month,DateTime.parse('$time').day);
  512. DateTime now = DateTime(DateTime.now().year,DateTime.now().month,DateTime.now().day);
  513. String tagStr = '';
  514. if(now.difference(date).inHours<=0 && now.difference(date).inHours>-24){
  515. tagStr = '今天';
  516. }else if(now.difference(date).inHours<=-24 && now.difference(date).inHours>-48){
  517. tagStr = '明天';
  518. }else if(now.difference(date).inHours<=-48 && now.difference(date).inHours>-72){
  519. tagStr = '后天';
  520. }else{
  521. switch(date.weekday){
  522. case 1: tagStr = '周一';break;
  523. case 2: tagStr = '周二';break;
  524. case 3: tagStr = '周三';break;
  525. case 4: tagStr = '周四';break;
  526. case 5: tagStr = '周五';break;
  527. case 6: tagStr = '周六';break;
  528. case 7: tagStr = '周日';break;
  529. }
  530. }
  531. return tagStr;
  532. }
  533. class DashedRect extends StatelessWidget {
  534. final Color color;
  535. final double strokeWidth;
  536. final double gap;
  537. DashedRect(
  538. {this.color = Colors.black, this.strokeWidth = 1.0, this.gap = 5.0});
  539. @override
  540. Widget build(BuildContext context) {
  541. return Container(
  542. child: Padding(
  543. padding: EdgeInsets.all(strokeWidth / 2),
  544. child: CustomPaint(
  545. painter:
  546. DashRectPainter(color: color, strokeWidth: strokeWidth, gap: gap),
  547. ),
  548. ),
  549. );
  550. }
  551. }
  552. class DashRectPainter extends CustomPainter {
  553. double strokeWidth;
  554. Color color;
  555. double gap;
  556. DashRectPainter(
  557. {this.strokeWidth = 5.0, this.color = Colors.red, this.gap = 5.0});
  558. @override
  559. void paint(Canvas canvas, Size size) {
  560. Paint dashedPaint = Paint()
  561. ..color = color
  562. ..strokeWidth = strokeWidth
  563. ..style = PaintingStyle.stroke;
  564. double x = size.width;
  565. double y = size.height;
  566. Path _topPath = getDashedPath(
  567. a: math.Point(0, 0),
  568. b: math.Point(x, 0),
  569. gap: gap,
  570. );
  571. Path _rightPath = getDashedPath(
  572. a: math.Point(x, 0),
  573. b: math.Point(x, y),
  574. gap: gap,
  575. );
  576. Path _bottomPath = getDashedPath(
  577. a: math.Point(0, y),
  578. b: math.Point(x, y),
  579. gap: gap,
  580. );
  581. Path _leftPath = getDashedPath(
  582. a: math.Point(0, 0),
  583. b: math.Point(0.001, y),
  584. gap: gap,
  585. );
  586. canvas.drawPath(_topPath, dashedPaint);
  587. canvas.drawPath(_rightPath, dashedPaint);
  588. canvas.drawPath(_bottomPath, dashedPaint);
  589. canvas.drawPath(_leftPath, dashedPaint);
  590. }
  591. Path getDashedPath({
  592. @required math.Point<double> a,
  593. @required math.Point<double> b,
  594. @required gap,
  595. }) {
  596. Size size = Size(b.x - a.x, b.y - a.y);
  597. Path path = Path();
  598. path.moveTo(a.x, a.y);
  599. bool shouldDraw = true;
  600. math.Point currentPoint = math.Point(a.x, a.y);
  601. num radians = math.atan(size.height / size.width);
  602. num dx = math.cos(radians) * gap < 0
  603. ? math.cos(radians) * gap * -1
  604. : math.cos(radians) * gap;
  605. num dy = math.sin(radians) * gap < 0
  606. ? math.sin(radians) * gap * -1
  607. : math.sin(radians) * gap;
  608. while (currentPoint.x <= b.x && currentPoint.y <= b.y) {
  609. shouldDraw
  610. ? path.lineTo(currentPoint.x, currentPoint.y)
  611. : path.moveTo(currentPoint.x, currentPoint.y);
  612. shouldDraw = !shouldDraw;
  613. currentPoint = math.Point(
  614. currentPoint.x + dx,
  615. currentPoint.y + dy,
  616. );
  617. }
  618. return path;
  619. }
  620. @override
  621. bool shouldRepaint(CustomPainter oldDelegate) {
  622. return true;
  623. }
  624. }
  625. getSecretStr(String str) {
  626. String secret = str.length==11?'****':'***********';
  627. return str.substring(0,3)+secret+str.substring(str.length-4,str.length);
  628. }
  629. class CirclePageRoute extends PageRoute {
  630. CirclePageRoute({
  631. @required this.builder,
  632. this.transitionDuration = const Duration(milliseconds: 500),
  633. this.opaque = true,
  634. this.barrierDismissible = false,
  635. this.barrierColor,
  636. this.barrierLabel,
  637. this.maintainState = true,
  638. });
  639. final WidgetBuilder builder;
  640. @override
  641. final Duration transitionDuration;
  642. @override
  643. final bool opaque;
  644. @override
  645. final bool barrierDismissible;
  646. @override
  647. final Color barrierColor;
  648. @override
  649. final String barrierLabel;
  650. @override
  651. final bool maintainState;
  652. @override
  653. Widget buildPage(BuildContext context, Animation<double> animation,
  654. Animation<double> secondaryAnimation) {
  655. return AnimatedBuilder(
  656. animation: animation,
  657. builder: (context, child) {
  658. return ClipPath(
  659. clipper: CirclePath(animation.value),
  660. child: child,
  661. );
  662. },
  663. child: builder(context),
  664. );
  665. }
  666. }
  667. class CirclePath extends CustomClipper<Path> {
  668. CirclePath(this.value);
  669. final double value;
  670. @override
  671. Path getClip(Size size) {
  672. var path = Path();
  673. double radius =
  674. value * sqrt(size.height * size.height + size.width * size.width);
  675. path.addOval(Rect.fromLTRB(
  676. size.width - radius, -radius, size.width + radius, radius));
  677. return path;
  678. }
  679. @override
  680. bool shouldReclip(CustomClipper<Path> oldClipper) {
  681. return true;
  682. }
  683. }
  684. loadingView() {
  685. return Center(
  686. //child: CircularProgressIndicator(),
  687. );
  688. }
  689. Widget platformView({ValueSetter platforms,Map message}){
  690. if(message==null)message = {'type':2};
  691. if(defaultTargetPlatform == TargetPlatform.android){
  692. return AndroidView(
  693. viewType: 'plugins.flutter.io/custom_platform_view',
  694. onPlatformViewCreated: (viewId) {
  695. platforms(MethodChannel('com.flutter.guide.MyFlutterView_$viewId'));
  696. },
  697. creationParams: message,
  698. creationParamsCodec: StandardMessageCodec(),
  699. );
  700. }else{
  701. return UiKitView(
  702. viewType: 'plugins.flutter.io/custom_platform_view',
  703. onPlatformViewCreated: (viewId) {
  704. platforms(MethodChannel('com.flutter.guide.MyFlutterView_$viewId'));
  705. },
  706. creationParams: message,
  707. creationParamsCodec: StandardMessageCodec(),
  708. );
  709. }
  710. }
  711. Future<bool> checkVersion() async{
  712. PackageInfo packageInfo = await PackageInfo.fromPlatform();
  713. SharedPreferences prefer = await SharedPreferences.getInstance();
  714. String locVer = prefer.getString('version')??'';
  715. String version = packageInfo.version;
  716. prefer.setString('version', version);
  717. return locVer==version;
  718. }
  719. Widget ysHtml1(String content) {
  720. double htmlHeight = 1;
  721. WebViewController _controller;
  722. return StatefulBuilder(
  723. builder: (context,heightSet){
  724. return Container(
  725. height: htmlHeight,
  726. width: MediaQuery.of(context).size.width,
  727. color: Colors.white,
  728. child: WebView(
  729. javascriptMode: JavascriptMode.unrestricted,
  730. onWebViewCreated: (WebViewController controller) {
  731. controller.loadUrl(Uri.dataFromString(content, mimeType: 'text/html', encoding: Encoding.getByName('utf-8')).toString());
  732. _controller = controller;
  733. },
  734. onPageFinished: (url){
  735. _controller.evaluateJavascript("document.body.scrollHeight").then((result){
  736. heightSet(() {
  737. htmlHeight = double.parse(result);
  738. });
  739. });
  740. },
  741. )
  742. );
  743. },
  744. );
  745. }
  746. class YSHtmlView extends StatefulWidget {
  747. final content;
  748. const YSHtmlView({Key key, this.content}) : super(key: key);
  749. @override
  750. _YSHtmlViewState createState() => _YSHtmlViewState();
  751. }
  752. class _YSHtmlViewState extends State<YSHtmlView> {
  753. double _htmlHeight = 1;
  754. WebViewController _controller;
  755. @override
  756. void dispose() {
  757. _controller.clearCache();
  758. super.dispose();
  759. }
  760. @override
  761. Widget build(BuildContext context) {
  762. return Container(
  763. height: _htmlHeight,
  764. width: MediaQuery.of(context).size.width,
  765. color: Colors.white,
  766. child: WebView(
  767. javascriptMode: JavascriptMode.unrestricted,
  768. onWebViewCreated: (WebViewController controller) {
  769. controller.loadUrl(Uri.dataFromString(widget.content, mimeType: 'text/html', encoding: Encoding.getByName('utf-8')).toString());
  770. _controller = controller;
  771. },
  772. onPageFinished: (url){
  773. _controller.evaluateJavascript("document.body.scrollHeight").then((result){
  774. setState(() {
  775. _htmlHeight = double.parse(result);
  776. });
  777. });
  778. },
  779. )
  780. ,
  781. );
  782. }
  783. }
  784. showNegotiateAlertDio(BuildContext context,{String content,VoidCallback sure}){
  785. showGeneralDialog(
  786. context: context,
  787. barrierDismissible:true,
  788. barrierColor: Colors.black.withOpacity(0.6),
  789. barrierLabel: '',
  790. transitionDuration: Duration(milliseconds: 200),
  791. pageBuilder: (BuildContext context, Animation<double> animation,
  792. Animation<double> secondaryAnimation) {
  793. return Center(
  794. child: Container(
  795. height: MediaQuery.of(context).size.height-(MediaQuery.of(context).padding.top+hsp(100)*2),
  796. width: MediaQuery.of(context).size.width-wsp(100),
  797. decoration: BoxDecoration(
  798. color: Colors.white,
  799. borderRadius: BorderRadius.all(Radius.circular(5))
  800. ),
  801. child: Column(
  802. children: [
  803. Container(
  804. height: hsp(100),
  805. padding: EdgeInsets.only(left: wsp(30),right: wsp(30)),
  806. child: Row(
  807. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  808. children: [
  809. Container(width: hsp(50),),
  810. Text('预定须知',style: TextStyle(fontSize: zsp(34),color: Color(0xFF242329),decoration: TextDecoration.none),),
  811. GestureDetector(
  812. child: Icon(Icons.close,size: hsp(50),color: Color(0xFF242329)),
  813. onTap: (){Navigator.pop(context);},
  814. )
  815. ],
  816. ),
  817. ),
  818. Container(
  819. height: MediaQuery.of(context).size.height-(MediaQuery.of(context).padding.top+hsp(100)*2)-hsp(200),
  820. width: MediaQuery.of(context).size.width-wsp(100),
  821. padding: EdgeInsets.all(wsp(20)),
  822. color: Colors.white,
  823. child: SingleChildScrollView(
  824. child: YSHtmlView(content:content),
  825. )
  826. ),
  827. GestureDetector(
  828. onTap: (){Navigator.pop(context);sure();},
  829. child: Container(
  830. height: hsp(100),
  831. alignment: Alignment.center,
  832. child: Text('我知道了',style: TextStyle(fontSize: zsp(34),color: Color(0xFF007EFF),decoration: TextDecoration.none),),
  833. ),
  834. ),
  835. ],
  836. ),
  837. ),
  838. );
  839. }
  840. );
  841. }
  842. showAgreeAlert(BuildContext context,{String title = '',String content = '',ValueSetter agree,bool isWelcome = false}) async{
  843. showGeneralDialog(
  844. context: context,
  845. barrierDismissible:true,
  846. barrierColor: Colors.black.withOpacity(0.6),
  847. barrierLabel: '',
  848. transitionDuration: Duration(milliseconds: 200),
  849. pageBuilder: (BuildContext context, Animation<double> animation,
  850. Animation<double> secondaryAnimation) {
  851. return Center(
  852. child: Container(
  853. height: MediaQuery.of(context).size.height-(MediaQuery.of(context).padding.top+hsp(100)*2),
  854. width: MediaQuery.of(context).size.width-wsp(100),
  855. decoration: BoxDecoration(
  856. color: Colors.white,
  857. borderRadius: BorderRadius.all(Radius.circular(5))
  858. ),
  859. child: Column(
  860. children: [
  861. Container(
  862. height: hsp(100),
  863. padding: EdgeInsets.only(left: wsp(30),right: wsp(30)),
  864. child: Row(
  865. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  866. children: [
  867. Container(width: hsp(34),),
  868. Text(title,style: TextStyle(fontSize: zsp(34),color: Color(0xFF242329),decoration: TextDecoration.none),),
  869. GestureDetector(
  870. onTap: (){Navigator.pop(context);},
  871. child: Icon(Icons.close,size: hsp(50),color: Color(0xFF242329)),
  872. )
  873. ],
  874. ),
  875. ),
  876. Container(
  877. height: MediaQuery.of(context).size.height-(MediaQuery.of(context).padding.top+hsp(100)*2)-hsp(200),
  878. width: MediaQuery.of(context).size.width-wsp(100),
  879. padding: EdgeInsets.all(wsp(20)),
  880. color: Color(0xFFF9F9F9),
  881. child: WebView(
  882. javascriptMode: JavascriptMode.unrestricted,
  883. onWebViewCreated: (WebViewController webViewController) {
  884. webViewController.loadUrl(Uri.dataFromString(content, mimeType: 'text/html', encoding: Encoding.getByName('utf-8')).toString());
  885. },
  886. )
  887. ),
  888. Container(
  889. height: hsp(100),
  890. alignment: Alignment.center,
  891. child: Row(
  892. children: [
  893. GestureDetector(
  894. onTap: (){
  895. agree(false);
  896. },
  897. child: Container(
  898. width: (MediaQuery.of(context).size.width-wsp(100))/2-wsp(1),
  899. alignment: Alignment.center,
  900. child: Text(isWelcome?'不同意并退出':'不同意',style: TextStyle(fontSize: zsp(34),color: Color(0xFF999999),decoration: TextDecoration.none),),
  901. ),
  902. ),
  903. Container(
  904. height: hsp(100),
  905. width: wsp(2),
  906. color: Color(0xFFF9F9F9),
  907. ),
  908. GestureDetector(
  909. onTap: (){
  910. agree(true);
  911. },
  912. child: Container(
  913. width: (MediaQuery.of(context).size.width-wsp(100))/2-wsp(1),
  914. alignment: Alignment.center,
  915. child: Text('同意',style: TextStyle(fontSize: zsp(34),color: Color(0xFF0079FF),decoration: TextDecoration.none),),
  916. ),
  917. )
  918. ],
  919. )
  920. ),
  921. ],
  922. ),
  923. ),
  924. );
  925. }
  926. );
  927. }
  928. showKnowAlert(BuildContext context,{String title = '',String content = '',VoidCallback know}) async{
  929. showGeneralDialog(
  930. context: context,
  931. barrierDismissible:true,
  932. barrierColor: Colors.black.withOpacity(0.6),
  933. barrierLabel: '',
  934. transitionDuration: Duration(milliseconds: 200),
  935. pageBuilder: (BuildContext context, Animation<double> animation,
  936. Animation<double> secondaryAnimation) {
  937. return Center(
  938. child: Container(
  939. height: MediaQuery.of(context).size.height-(MediaQuery.of(context).padding.top+hsp(100)*2),
  940. width: MediaQuery.of(context).size.width-wsp(100),
  941. decoration: BoxDecoration(
  942. color: Colors.white,
  943. borderRadius: BorderRadius.all(Radius.circular(5))
  944. ),
  945. child: Column(
  946. children: [
  947. Container(
  948. height: hsp(100),
  949. padding: EdgeInsets.only(left: wsp(30),right: wsp(30)),
  950. child: Row(
  951. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  952. children: [
  953. Container(),
  954. Text(title,style: TextStyle(fontSize: zsp(34),color: Color(0xFF242329),decoration: TextDecoration.none),),
  955. GestureDetector(
  956. onTap: (){Navigator.pop(context);},
  957. child: Icon(Icons.close,size: hsp(50),color: Color(0xFF242329)),
  958. )
  959. ],
  960. ),
  961. ),
  962. Container(
  963. height: MediaQuery.of(context).size.height-(MediaQuery.of(context).padding.top+hsp(100)*2)-hsp(200),
  964. width: MediaQuery.of(context).size.width-wsp(100),
  965. padding: EdgeInsets.all(wsp(20)),
  966. color: Color(0xFFF9F9F9),
  967. child: WebView(
  968. // initialUrl: 'data:text/html;base64,${base64Encode(const Utf8Encoder().convert(content))}',
  969. javascriptMode: JavascriptMode.unrestricted,
  970. onWebViewCreated: (WebViewController webViewController) {
  971. webViewController.loadUrl(Uri.dataFromString(content, mimeType: 'text/html', encoding: Encoding.getByName('utf-8')).toString());
  972. },
  973. )
  974. ),
  975. GestureDetector(
  976. child: Container(
  977. height: hsp(100),
  978. alignment: Alignment.center,
  979. child: Text('我知道了',style: TextStyle(fontSize: zsp(34),color: Color(0xFF0079FF),decoration: TextDecoration.none),),
  980. ),
  981. onTap: (){
  982. Navigator.pop(context);
  983. know();
  984. },
  985. behavior: HitTestBehavior.opaque,
  986. ),
  987. ],
  988. ),
  989. ),
  990. );
  991. }
  992. );
  993. }
  994. showInformAlert(BuildContext context,{String title = '',String content = '',VoidCallback sure}){
  995. double htmlHeight = MediaQuery.of(context).size.height*0.85-0.5-hsp(100);
  996. WebViewController _controller;
  997. showModalBottomSheet(
  998. isScrollControlled: true,
  999. context: context,
  1000. backgroundColor: Colors.transparent,
  1001. builder: (context){
  1002. return Container(
  1003. height: MediaQuery.of(context).size.height*0.85,
  1004. decoration: BoxDecoration(
  1005. color: Colors.white,
  1006. borderRadius: BorderRadius.only(topRight: Radius.circular(10),topLeft: Radius.circular(10))
  1007. ),
  1008. child: Column(
  1009. children: [
  1010. Container(
  1011. height: hsp(100),
  1012. padding: EdgeInsets.only(left: hsp(30),right: hsp(30)),
  1013. child: Row(
  1014. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  1015. children: [
  1016. Container(width: wsp(50),),
  1017. Text(title,style: TextStyle(fontSize: 15,color: Color(0xFF000000),decoration: TextDecoration.none,fontWeight: FontWeight.bold),),
  1018. GestureDetector(
  1019. child: Text('关闭',style: TextStyle(fontSize: 15,color: Color(0xFF007EFF),decoration: TextDecoration.none,fontWeight: FontWeight.bold),),
  1020. onTap: (){
  1021. Navigator.pop(context);
  1022. },
  1023. ),
  1024. ],
  1025. ),
  1026. ),
  1027. Divider(height: 0.5,thickness: 0.5,color: Color(0xFFE5E5E5),),
  1028. Container(
  1029. height: MediaQuery.of(context).size.height*0.85-0.5-hsp(100),
  1030. child: WebView(
  1031. // initialUrl: 'data:text/html;base64,${base64Encode(const Utf8Encoder().convert(content))}',
  1032. javascriptMode: JavascriptMode.unrestricted,
  1033. onWebViewCreated: (WebViewController webViewController) {
  1034. webViewController.loadUrl(Uri.dataFromString(content, mimeType: 'text/html', encoding: Encoding.getByName('utf-8')).toString());
  1035. },
  1036. ),
  1037. ),
  1038. ],
  1039. ),
  1040. );
  1041. }
  1042. );
  1043. }
  1044. alertPhone(BuildContext context, String phoneStr) async{
  1045. showCupertinoDialog(
  1046. context: context,
  1047. builder: (context) {
  1048. return CupertinoAlertDialog(
  1049. title: Text('提示'),
  1050. content: Text('拨打 $phoneStr ?'),
  1051. actions: <Widget>[
  1052. CupertinoDialogAction(child: Text('取消'),onPressed: (){Navigator.pop(context);},),
  1053. CupertinoDialogAction(child: Text('确认'),onPressed: (){Navigator.pop(context);launch('tel:$phoneStr');},),
  1054. ],
  1055. );
  1056. });
  1057. }
  1058. _getMonthDay() async{
  1059. }
  1060. getDateArray({ValueSetter dates,int count = 90,String startStr}) {
  1061. List zhongQius = ['2021-9-21','2022-9-10','2023-9-29','2024-9-17','2025-10-6','2026-9-25','2027-9-15','2028-10-3','2029-9-22','2030-9-12'];
  1062. List chuXis = ['2021-2-11','2022-1-31','2023-1-21','2024-2-9','2025-1-28','2026-2-16','2027-2-5','2028-1-25','2029-2-12','2030-2-2'];
  1063. List chunJies = ['2021-2-12','2022-2-1','2023-1-22','2024-2-10','2025-1-29','2026-2-17','2027-2-6','2028-1-26','2029-2-13','2030-2-3'];
  1064. List duanWus = ['2021-6-14','2022-6-3','2023-6-22','2024-6-10','2025-5-31','2026-6-19','2027-6-9','2028-6-27','2029-6-16','2030-6-5'];
  1065. DateTime _time = startStr!=null?DateTime.parse(startStr):DateTime.now();
  1066. int year = _time.year;
  1067. List dateArray = [];
  1068. int month = _time.month;
  1069. int days = DateTime(year, month + 1, 0).day;
  1070. int days2 = DateTime(year, month + 2, 0).day;
  1071. int months = count>days-_time.day+days2+1?3:2;
  1072. int number = 1;
  1073. for(int i = 0;i<months;i++){
  1074. if(month>12){
  1075. year++;
  1076. month = 1;
  1077. }
  1078. int days3 = DateTime(year, month + 1, 0).day;
  1079. dateArray.add({'year':year,'month':month,'days':[]});
  1080. int firstNum = 0;
  1081. int week = DateTime.parse('$year-${'$month'.padLeft(2,'0')}-01 00:00:00').weekday;
  1082. if(week==7){
  1083. firstNum = 0;
  1084. }else{
  1085. firstNum = week;
  1086. }
  1087. for(int j=1;j<days3+1+firstNum;j++){
  1088. if(j<=firstNum){
  1089. dateArray[i]['days'].add(0);
  1090. }else if(number>count||(year==_time.year&&month==_time.month&&j-firstNum<_time.day)){
  1091. //print('$i=============$days================${count+_time.day}');
  1092. dateArray[i]['days'].add((j-firstNum)*0.01);
  1093. }else{
  1094. number++;
  1095. String yStr = '$year-$month-${j-firstNum}';
  1096. String str = '$month-${j-firstNum}';
  1097. if(zhongQius.contains(yStr)==true){
  1098. dateArray[i]['days'].add({'day':j-firstNum,'fes':'中秋'});
  1099. }else if(chuXis.contains(yStr)==true){
  1100. dateArray[i]['days'].add({'day':j-firstNum,'fes':'除夕'});
  1101. }else if(chunJies.contains(yStr)==true){
  1102. dateArray[i]['days'].add({'day':j-firstNum,'fes':'春节'});
  1103. }else if(chunJies.contains(yStr)==true){
  1104. dateArray[i]['days'].add({'day':j-firstNum,'fes':'端午'});
  1105. }else if(str=='1-1'){
  1106. dateArray[i]['days'].add({'day':j-firstNum,'fes':'元旦'});
  1107. }else if(str=='4-4'){
  1108. dateArray[i]['days'].add({'day':j-firstNum,'fes':'清明'});
  1109. }else if(str=='10-1'){
  1110. dateArray[i]['days'].add({'day':j-firstNum,'fes':'国庆'});
  1111. }else if(str=='5-1'){
  1112. dateArray[i]['days'].add({'day':j-firstNum,'fes':'劳动节'});
  1113. }else if(str=='6-1'){
  1114. dateArray[i]['days'].add({'day':j-firstNum,'fes':'儿童节'});
  1115. }else if(str=='12-25'){
  1116. dateArray[i]['days'].add({'day':j-firstNum,'fes':'圣诞节'});
  1117. }else{
  1118. dateArray[i]['days'].add(j-firstNum);
  1119. }
  1120. }
  1121. }
  1122. month++;
  1123. }
  1124. print(dateArray);
  1125. dates(dateArray);
  1126. }
  1127. dateChooseAlert(BuildContext context,{ValueSetter dateValue,int count = 90,String startStr}) {
  1128. List dates = [];
  1129. getDateArray( dates: (value){dates = value;},count: count,startStr: startStr);
  1130. List weeks = ['日','一','二','三','四','五','六'];
  1131. int today = DateTime.now().day;
  1132. int thisMonth = DateTime.now().month;
  1133. int thisYear = DateTime.now().year;
  1134. int year = DateTime.now().year;
  1135. int month = DateTime.now().month;
  1136. int day = DateTime.now().day;
  1137. showModalBottomSheet(
  1138. context: context,
  1139. backgroundColor: Colors.transparent,
  1140. isScrollControlled: true,
  1141. builder: (context){
  1142. return StatefulBuilder(
  1143. builder: (context,dateSet){
  1144. return Container(
  1145. height: MediaQuery.of(context).size.height*0.7,
  1146. width: MediaQuery.of(context).size.width,
  1147. color: Colors.white,
  1148. child: SingleChildScrollView(
  1149. child: Column(
  1150. children: [
  1151. Container(
  1152. height: hsp(80),
  1153. padding: EdgeInsets.only(left: hsp(30),right: hsp(40),top: hsp(10)),
  1154. child: Row(
  1155. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  1156. children: [
  1157. GestureDetector(
  1158. onTap: (){Navigator.pop(context);},
  1159. child: Icon(Icons.close,size: hsp(40),color: Color(0xFF4B4B4B),),
  1160. ),
  1161. Text('选择日期',style: TextStyle(fontSize: zsp(30),color: Colors.black,fontWeight: FontWeight.bold),),
  1162. Container(width: hsp(40),)
  1163. ],
  1164. ),
  1165. ),
  1166. Container(
  1167. height: hsp(80),
  1168. width: MediaQuery.of(context).size.width,
  1169. child: ListView.builder(
  1170. itemCount: weeks.length,
  1171. scrollDirection: Axis.horizontal,
  1172. padding: EdgeInsets.all(0),
  1173. itemBuilder: (context,index){
  1174. return Container(
  1175. height: hsp(80),
  1176. width: MediaQuery.of(context).size.width/weeks.length,
  1177. alignment: Alignment.center,
  1178. child: Text('${weeks[index]}',style: TextStyle(fontSize: zsp(32),color: index==0||index==6?Color(0xFFE85D54):Color(0xFF666666)),),
  1179. );
  1180. },
  1181. ),
  1182. ),
  1183. Container(
  1184. height: MediaQuery.of(context).size.height*0.7-hsp(300),
  1185. width: MediaQuery.of(context).size.width,
  1186. child: SingleChildScrollView(
  1187. child: ListView.separated(
  1188. padding: EdgeInsets.all(0),
  1189. itemCount: dates.length,
  1190. shrinkWrap: true,
  1191. physics: NeverScrollableScrollPhysics(),
  1192. itemBuilder: (context,index){
  1193. Map dateMonth = dates[index];
  1194. return Column(
  1195. children: [
  1196. Container(
  1197. width: MediaQuery.of(context).size.width,
  1198. padding: EdgeInsets.only(left: hsp(30),right: hsp(30)),
  1199. alignment: Alignment.center,
  1200. child: Text('${dateMonth['year']}年 '+'${dateMonth['month']}'.padLeft(2,'0')+'月'),
  1201. height: hsp(70),
  1202. ),
  1203. Divider(height: 1,thickness: 1,color: Color(0xFFF4F4F7),),
  1204. GridView.builder(
  1205. itemCount: dateMonth['days'].length,
  1206. padding: EdgeInsets.all(0),
  1207. shrinkWrap: true,
  1208. physics: NeverScrollableScrollPhysics(),
  1209. gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
  1210. crossAxisCount: 7,
  1211. ),
  1212. itemBuilder: (context,indexSub){
  1213. var dateDay = dateMonth['days'][indexSub];
  1214. return dateDay==0?Container():GestureDetector(
  1215. onTap: (){
  1216. if((dateDay is Map?dateDay['day']:dateDay)<1)return;
  1217. dateSet(() {
  1218. month = dateMonth['month'];
  1219. day = dateDay is Map?dateDay['day']:dateDay;
  1220. year = dateMonth['year'];
  1221. });
  1222. },
  1223. child: Container(
  1224. alignment: Alignment.center,
  1225. child: dates[index]['days'][indexSub] is Map?Column(
  1226. children: [
  1227. Text(
  1228. dateDay['day']-today==0&&dateMonth['month']==thisMonth&&dateMonth['year']==thisYear?'今天':
  1229. dateDay['day']-today==1&&dateMonth['month']==thisMonth&&dateMonth['year']==thisYear?'明天':
  1230. dateDay['day']-today==2&&dateMonth['month']==thisMonth&&dateMonth['year']==thisYear?'后天':
  1231. '${dateDay['day']~/(dateDay['day']<1?0.01:1)}',style: TextStyle(fontSize: zsp(28),
  1232. color: dateDay['day']==day&&dateMonth['month']==month&&dateMonth['year']==year?Colors.white:
  1233. dateDay['day']<1?Color(0xFFCBCBCB):Color(0xFF333333)),),
  1234. Text('${dateDay['fes']}',style: TextStyle(fontSize: zsp(20),
  1235. color: dateDay['day']==day&&dateMonth['month']==month&&dateMonth['year']==year?Colors.white:
  1236. dateDay['day']<1?Color(0xFFCBCBCB):Color(0xFFE85D54)),)
  1237. ],
  1238. mainAxisSize: MainAxisSize.min,
  1239. ):Text(
  1240. dateDay-today==0&&dateMonth['month']==thisMonth&&dateMonth['year']==thisYear?'今天':
  1241. dateDay-today==1&&dateMonth['month']==thisMonth&&dateMonth['year']==thisYear?'明天':
  1242. dateDay-today==2&&dateMonth['month']==thisMonth&&dateMonth['year']==thisYear?'后天':
  1243. '${dateDay~/(dateDay<1?0.01:1)}',style: TextStyle(fontSize: zsp(28),
  1244. color: dateDay==day&&dateMonth['month']==month&&dateMonth['year']==year?Colors.white:
  1245. dateDay<1?Color(0xFFCBCBCB):Color(0xFF333333)),),
  1246. margin: EdgeInsets.all(hsp(15)),
  1247. decoration: BoxDecoration(
  1248. color: (dateDay is Map?dateDay['day']:dateDay)==day
  1249. &&dateMonth['month']==month&&dateMonth['year']==year?Color(0xFF007AFF):Colors.transparent,
  1250. borderRadius: BorderRadius.all(Radius.circular(5))
  1251. ),
  1252. ),
  1253. );
  1254. },
  1255. )
  1256. ],
  1257. );
  1258. },
  1259. separatorBuilder: (context,index){
  1260. return Divider(height: hsp(20),thickness: hsp(20),color: Color(0xFFF4F4F7),);
  1261. },
  1262. ),
  1263. ),
  1264. ),
  1265. GestureDetector(
  1266. onTap: (){
  1267. Navigator.pop(context);
  1268. String date = '$year-${'$month'.padLeft(2,'0')}-${'$day'.padLeft(2,'0')}';
  1269. dateValue(date);
  1270. },
  1271. child: Container(
  1272. margin: EdgeInsets.only(top: hsp(26)),
  1273. height: hsp(88),
  1274. width: MediaQuery.of(context).size.width-hsp(80),
  1275. decoration: BoxDecoration(
  1276. color: Color(0xFF007EFF),
  1277. borderRadius: BorderRadius.all(Radius.circular(5))
  1278. ),
  1279. alignment: Alignment.center,
  1280. child: Text('完成',style: TextStyle(fontSize: zsp(36),color: Colors.white),),
  1281. ),
  1282. )
  1283. ],
  1284. ),
  1285. ),
  1286. );
  1287. },
  1288. );
  1289. }
  1290. );
  1291. }
  1292. dateChooseAlert1(BuildContext context,{ValueSetter dateValue}) {
  1293. List dates = [];
  1294. getDateArray( dates: (value){dates = value;});
  1295. List weeks = ['日','一','二','三','四','五','六'];
  1296. int today = DateTime.now().day;
  1297. int thisMonth = DateTime.now().month;
  1298. int thisYear = DateTime.now().year;
  1299. int year = DateTime.now().year;
  1300. int month = DateTime.now().month;
  1301. int day = DateTime.now().day;
  1302. showModalBottomSheet(
  1303. context: context,
  1304. backgroundColor: Colors.transparent,
  1305. isScrollControlled: true,
  1306. builder: (context){
  1307. return StatefulBuilder(
  1308. builder: (context,dateSet){
  1309. return Container(
  1310. height: MediaQuery.of(context).size.height*0.7,
  1311. width: MediaQuery.of(context).size.width,
  1312. color: Colors.white,
  1313. child: SingleChildScrollView(
  1314. child: Column(
  1315. children: [
  1316. Container(
  1317. height: hsp(80),
  1318. padding: EdgeInsets.only(left: hsp(30),right: hsp(40),top: hsp(10)),
  1319. child: Row(
  1320. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  1321. children: [
  1322. GestureDetector(
  1323. onTap: (){Navigator.pop(context);},
  1324. child: Icon(Icons.close,size: hsp(40),color: Color(0xFF4B4B4B),),
  1325. ),
  1326. Text('选择日期',style: TextStyle(fontSize: zsp(30),color: Colors.black,fontWeight: FontWeight.bold),),
  1327. Container(width: hsp(40),)
  1328. ],
  1329. ),
  1330. ),
  1331. Container(
  1332. height: hsp(80),
  1333. width: MediaQuery.of(context).size.width,
  1334. child: ListView.builder(
  1335. itemCount: weeks.length,
  1336. scrollDirection: Axis.horizontal,
  1337. padding: EdgeInsets.all(0),
  1338. itemBuilder: (context,index){
  1339. return Container(
  1340. height: hsp(80),
  1341. width: MediaQuery.of(context).size.width/weeks.length,
  1342. alignment: Alignment.center,
  1343. child: Text('${weeks[index]}',style: TextStyle(fontSize: zsp(32),color: index==0||index==6?Color(0xFFE85D54):Color(0xFF666666)),),
  1344. );
  1345. },
  1346. ),
  1347. ),
  1348. Container(
  1349. height: MediaQuery.of(context).size.height*0.7-hsp(300),
  1350. width: MediaQuery.of(context).size.width,
  1351. child: SingleChildScrollView(
  1352. child: ListView.separated(
  1353. padding: EdgeInsets.all(0),
  1354. itemCount: dates.length,
  1355. shrinkWrap: true,
  1356. physics: NeverScrollableScrollPhysics(),
  1357. itemBuilder: (context,index){
  1358. return Column(
  1359. children: [
  1360. Container(
  1361. width: MediaQuery.of(context).size.width,
  1362. padding: EdgeInsets.only(left: hsp(30),right: hsp(30)),
  1363. alignment: Alignment.center,
  1364. child: Text('${dates[index]['year']}年 '+'${dates[index]['month']}'.padLeft(2,'0')+'月'),
  1365. height: hsp(70),
  1366. ),
  1367. Divider(height: 1,thickness: 1,color: Color(0xFFF4F4F7),),
  1368. GridView.builder(
  1369. itemCount: dates[index]['days'].length,
  1370. padding: EdgeInsets.all(0),
  1371. shrinkWrap: true,
  1372. physics: NeverScrollableScrollPhysics(),
  1373. gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
  1374. crossAxisCount: 7,
  1375. ),
  1376. itemBuilder: (context,indexSub){
  1377. return dates[index]['days'][indexSub]==0?Container():GestureDetector(
  1378. onTap: (){
  1379. if((dates[index]['days'][indexSub] is Map?dates[index]['days'][indexSub]['day']:dates[index]['days'][indexSub])<
  1380. today&&dates[index]['month']==thisMonth&&dates[index]['year']==thisYear)return;
  1381. dateSet(() {
  1382. month = dates[index]['month'];
  1383. day = dates[index]['days'][indexSub] is Map?dates[index]['days'][indexSub]['day']:dates[index]['days'][indexSub];
  1384. year = dates[index]['year'];
  1385. });
  1386. },
  1387. child: Container(
  1388. alignment: Alignment.center,
  1389. child: dates[index]['days'][indexSub] is Map?Column(
  1390. children: [
  1391. Text(
  1392. dates[index]['days'][indexSub]['day']-today==0&&dates[index]['month']==thisMonth&&dates[index]['year']==thisYear?'今天':
  1393. dates[index]['days'][indexSub]['day']-today==1&&dates[index]['month']==thisMonth&&dates[index]['year']==thisYear?'明天':
  1394. dates[index]['days'][indexSub]['day']-today==2&&dates[index]['month']==thisMonth&&dates[index]['year']==thisYear?'后天':
  1395. '${dates[index]['days'][indexSub]['day']}',style: TextStyle(fontSize: zsp(28),
  1396. color: dates[index]['days'][indexSub]['day']==day&&dates[index]['month']==month&&dates[index]['year']==year?Colors.white:
  1397. dates[index]['days'][indexSub]['day']<today&&dates[index]['month']==thisMonth&&dates[index]['year']==thisYear?
  1398. Color(0xFFCBCBCB):Color(0xFF333333)),),
  1399. Text('${dates[index]['days'][indexSub]['fes']}',style: TextStyle(fontSize: zsp(20),
  1400. color: dates[index]['days'][indexSub]['day']==day&&dates[index]['month']==month&&dates[index]['year']==year?Colors.white:
  1401. dates[index]['days'][indexSub]['day']<today&&dates[index]['month']==thisMonth&&dates[index]['year']==thisYear?
  1402. Color(0xFFCBCBCB):Color(0xFFE85D54)),)
  1403. ],
  1404. mainAxisSize: MainAxisSize.min,
  1405. ):Text(dates[index]['days'][indexSub]-today==0&&dates[index]['month']==thisMonth&&dates[index]['year']==thisYear?'今天':
  1406. dates[index]['days'][indexSub]-today==1&&dates[index]['month']==thisMonth&&dates[index]['year']==thisYear?'明天':
  1407. dates[index]['days'][indexSub]-today==2&&dates[index]['month']==thisMonth&&dates[index]['year']==thisYear?'后天':
  1408. '${dates[index]['days'][indexSub]}',style: TextStyle(fontSize: zsp(28),
  1409. color: dates[index]['days'][indexSub]==day&&dates[index]['month']==month&&dates[index]['year']==year?Colors.white:
  1410. dates[index]['days'][indexSub]<today&&dates[index]['month']==thisMonth&&dates[index]['year']==thisYear?
  1411. Color(0xFFCBCBCB):Color(0xFF333333)),),
  1412. margin: EdgeInsets.all(hsp(15)),
  1413. decoration: BoxDecoration(
  1414. color: (dates[index]['days'][indexSub] is Map?dates[index]['days'][indexSub]['day']:dates[index]['days'][indexSub])==day
  1415. &&dates[index]['month']==month&&dates[index]['year']==year?Color(0xFF007AFF):Colors.transparent,
  1416. borderRadius: BorderRadius.all(Radius.circular(5))
  1417. ),
  1418. ),
  1419. );
  1420. },
  1421. )
  1422. ],
  1423. );
  1424. },
  1425. separatorBuilder: (context,index){
  1426. return Divider(height: hsp(20),thickness: hsp(20),color: Color(0xFFF4F4F7),);
  1427. },
  1428. ),
  1429. ),
  1430. ),
  1431. GestureDetector(
  1432. onTap: (){
  1433. String date = '$year-${'$month'.padLeft(2,'0')}-${'$day'.padLeft(2,'0')}';
  1434. Navigator.pop(context);
  1435. dateValue(date);
  1436. },
  1437. child: Container(
  1438. margin: EdgeInsets.only(top: hsp(26)),
  1439. height: hsp(88),
  1440. width: MediaQuery.of(context).size.width-hsp(80),
  1441. decoration: BoxDecoration(
  1442. color: Color(0xFF007EFF),
  1443. borderRadius: BorderRadius.all(Radius.circular(5))
  1444. ),
  1445. alignment: Alignment.center,
  1446. child: Text('完成',style: TextStyle(fontSize: zsp(36),color: Colors.white),),
  1447. ),
  1448. )
  1449. ],
  1450. ),
  1451. ),
  1452. );
  1453. },
  1454. );
  1455. }
  1456. );
  1457. }
  1458. timeChooseAlert(BuildContext context,{ValueSetter timeValue}) {
  1459. int hour = DateTime.now().hour;
  1460. int min = DateTime.now().minute;
  1461. showModalBottomSheet(
  1462. context: context,
  1463. backgroundColor: Colors.transparent,
  1464. builder: (context){
  1465. return Container(
  1466. color: Colors.transparent,
  1467. height: 280,
  1468. child: Column(
  1469. crossAxisAlignment: CrossAxisAlignment.end,
  1470. children: [
  1471. Container(
  1472. height: 40,
  1473. padding: EdgeInsets.only(left: wsp(40),right: wsp(40)),
  1474. decoration: BoxDecoration(
  1475. color: Colors.white,
  1476. border: Border(bottom: BorderSide(width: 0.5,color: Color(0xFFEEEEEE)))
  1477. ),
  1478. child: Row(
  1479. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  1480. children: [
  1481. GestureDetector(
  1482. child: Text('取消',style: TextStyle(fontSize: zsp(30),color: Color(0xFF999999)),),
  1483. onTap: (){
  1484. Navigator.pop(context);
  1485. },
  1486. ),
  1487. GestureDetector(
  1488. child: Text('确定',style: TextStyle(fontSize: zsp(30),color: Color(0xFF108DE9)),),
  1489. onTap: (){
  1490. Navigator.pop(context);
  1491. timeValue(hour.toString().padLeft(2,'0')+':'+min.toString().padLeft(2,'0'));
  1492. },
  1493. )
  1494. ],
  1495. ),
  1496. ),
  1497. Row(
  1498. children: [
  1499. for(int i=0;i<2;i++)Container(
  1500. height: 240,
  1501. width: MediaQuery.of(context).size.width/2,
  1502. color: Colors.white,
  1503. child: CupertinoPicker(
  1504. itemExtent: hsp(100),
  1505. children: [
  1506. for(int j=0;j<(i==0?24:60);j++)Container(
  1507. child: Text(i==0?'$j时':'$j分',style: TextStyle(fontSize: zsp(32),color: Colors.black),),
  1508. alignment: Alignment.center,
  1509. )
  1510. ],
  1511. onSelectedItemChanged: (value){
  1512. if(i==0){
  1513. hour = value;
  1514. }else{
  1515. min = value;
  1516. }
  1517. },
  1518. scrollController: FixedExtentScrollController(
  1519. initialItem: i==0?hour:min
  1520. ),
  1521. ),
  1522. ),
  1523. ],
  1524. ),
  1525. ],
  1526. ),
  1527. );
  1528. }
  1529. );
  1530. }
  1531. showVersionAlert(BuildContext context){
  1532. showGeneralDialog(
  1533. context: context,
  1534. barrierDismissible:true,
  1535. barrierColor: Colors.black.withOpacity(0.6),
  1536. barrierLabel: '',
  1537. transitionDuration: Duration(milliseconds: 200),
  1538. pageBuilder: (BuildContext context, Animation<double> animation,
  1539. Animation<double> secondaryAnimation) {
  1540. return Center(
  1541. child: Container(
  1542. height: MediaQuery.of(context).size.height*0.5,
  1543. width: MediaQuery.of(context).size.width-hsp(100),
  1544. decoration: BoxDecoration(
  1545. color: Colors.white,
  1546. borderRadius: BorderRadius.all(Radius.circular(5))
  1547. ),
  1548. child: Column(
  1549. children: [
  1550. Container(
  1551. padding: EdgeInsets.all(hsp(30)),
  1552. child: Text('版本更新',style: TextStyle(fontSize: zsp(32),color: Colors.black,decoration: TextDecoration.none,fontWeight: FontWeight.normal),),
  1553. alignment: Alignment.center,
  1554. ),
  1555. Divider(height: 1,thickness: 1,color: Color(0xFFF4F4F7),),
  1556. Container(
  1557. height: MediaQuery.of(context).size.height*0.5-hsp(215),
  1558. width: MediaQuery.of(context).size.width-hsp(100),
  1559. child: ListView.separated(
  1560. itemCount: 5,
  1561. padding: EdgeInsets.only(left: hsp(50),right: hsp(50),top: hsp(30),bottom: hsp(30)),
  1562. itemBuilder: (context,index){
  1563. return Container(
  1564. child: Text('${index+1}、更新更新更新更新更新更新更新更新更新更新更新更新',
  1565. style: TextStyle(fontSize: zsp(30),color: Colors.black,decoration: TextDecoration.none,fontWeight: FontWeight.normal),),
  1566. width: MediaQuery.of(context).size.width-hsp(160),
  1567. );
  1568. },
  1569. separatorBuilder: (context,index){
  1570. return Divider(height: hsp(20),thickness: hsp(20),color: Colors.transparent,);
  1571. },
  1572. ),
  1573. ),
  1574. Divider(height: 1,thickness: 1,color: Color(0xFFF4F4F7),),
  1575. Container(
  1576. height: hsp(100),
  1577. child: Row(
  1578. children: [
  1579. GestureDetector(
  1580. onTap: (){
  1581. Navigator.pop(context);
  1582. },
  1583. child: Container(
  1584. width: (MediaQuery.of(context).size.width-hsp(100))/2-hsp(1),
  1585. height: hsp(100),
  1586. alignment: Alignment.center,
  1587. child: Text('忽略此版',style: TextStyle(fontSize: zsp(32),color: Colors.black,decoration: TextDecoration.none,fontWeight: FontWeight.normal),),
  1588. ),
  1589. ),
  1590. Container(height: hsp(100),color: Color(0xFFF4F4F7),width: hsp(2),),
  1591. GestureDetector(
  1592. onTap: (){
  1593. Navigator.pop(context);
  1594. },
  1595. child: Container(
  1596. width: (MediaQuery.of(context).size.width-hsp(100))/2-hsp(1),
  1597. height: hsp(100),
  1598. alignment: Alignment.center,
  1599. child: Text('立即更新',style: TextStyle(fontSize: zsp(32),color: Color(0xFF007AFF),decoration: TextDecoration.none),),
  1600. ),
  1601. )
  1602. ],
  1603. ),
  1604. )
  1605. ],
  1606. ),
  1607. ),
  1608. );
  1609. }
  1610. );
  1611. }
  1612. class NumberFormat extends TextInputFormatter {
  1613. NumberFormat({this.decimalRange = 3})
  1614. : assert(decimalRange == null || decimalRange > 0);
  1615. final int decimalRange;
  1616. @override
  1617. TextEditingValue formatEditUpdate(TextEditingValue oldValue,
  1618. TextEditingValue newValue) {
  1619. // 拿到录入后的字符
  1620. String nValue = newValue.text;
  1621. //当前所选择的文字区域
  1622. TextSelection nSelection = newValue.selection;
  1623. // 先来一波过滤,过滤出数字及小数点
  1624. // 匹配包含数字和小数点的字符
  1625. Pattern p = RegExp(r'(\d+\.?)|(\.?\d+)|(\.?)');
  1626. nValue = p.allMatches(nValue)
  1627. .map<String>((Match match) => match.group(0))
  1628. .join();
  1629. // 用匹配完的字符判断
  1630. if (nValue.startsWith('.')) { //如果小数点开头,我们给他补个0
  1631. nValue = '0.';
  1632. } else if (nValue.contains('.')) {
  1633. //来验证小数点位置
  1634. if (nValue.substring(nValue.indexOf('.') + 1).length > decimalRange) {
  1635. nValue = oldValue.text;
  1636. } else {
  1637. if (nValue.split('.').length > 2) { //多个小数点,去掉后面的
  1638. List<String> split = nValue.split('.');
  1639. nValue = split[0] + '.' + split[1];
  1640. }
  1641. }
  1642. }
  1643. //使光标定位到最后一个字符后面
  1644. nSelection = newValue.selection.copyWith(
  1645. baseOffset: math.min(nValue.length, nValue.length + 1),
  1646. extentOffset: math.min(nValue.length, nValue.length + 1),
  1647. );
  1648. return TextEditingValue(
  1649. text: nValue,
  1650. selection: nSelection,
  1651. composing: TextRange.empty
  1652. );
  1653. }
  1654. }
  1655. GlobalKey<_YSGoodsServiceViewState> serviceKey = GlobalKey();
  1656. class YSGoodsServiceView extends StatefulWidget {
  1657. final List personArray;
  1658. final type;
  1659. final tourId;
  1660. final ValueSetter<double> totalSetter;
  1661. const YSGoodsServiceView({Key key, this.personArray, this.type, this.tourId, this.totalSetter}) : super(key: key);
  1662. @override
  1663. _YSGoodsServiceViewState createState() => _YSGoodsServiceViewState();
  1664. }
  1665. class _YSGoodsServiceViewState extends State<YSGoodsServiceView> {
  1666. List _chooseArray = [];
  1667. List _serviceArray = [];
  1668. double _totalNumber = 0;
  1669. @override
  1670. void initState() {
  1671. Future.delayed(Duration(seconds: 0)).then((value) {
  1672. _getServiceData();
  1673. });
  1674. super.initState();
  1675. }
  1676. clearChoose() {
  1677. _chooseArray.clear();
  1678. widget.personArray.forEach((element) {
  1679. element.remove('services');
  1680. });
  1681. setState(() {});
  1682. _totalNumber = 0;
  1683. widget.totalSetter(_totalNumber);
  1684. }
  1685. @override
  1686. Widget build(BuildContext context) {
  1687. return Container(
  1688. child: Column(
  1689. children: [
  1690. Container(
  1691. height: hsp(80),
  1692. padding: EdgeInsets.only(left: hsp(30)),
  1693. child: Text('增值服务',style: TextStyle(fontSize: zsp(30),color: Color(0xFF9A9A9A)),),
  1694. alignment: Alignment.centerLeft,
  1695. decoration: BoxDecoration(
  1696. border: Border(bottom: BorderSide(color: Color(0xFFF1F2F4),width: hsp(1)))
  1697. ),
  1698. ),
  1699. ListView.builder(itemBuilder: (context,index){
  1700. Map item = _serviceArray[index];
  1701. bool isChoose = _chooseArray.contains(item);
  1702. return GestureDetector(
  1703. onTap: (){
  1704. if(widget.personArray.length==0){
  1705. ysFlutterToast(context, '请添加出行人后选择');
  1706. return;
  1707. }
  1708. if(isChoose){
  1709. _chooseArray.remove(item);
  1710. setState(() {});
  1711. widget.personArray.forEach((element) {
  1712. String serviceStr = element['services']??'';
  1713. List serviceArray = [];
  1714. if(serviceStr.isNotEmpty){
  1715. serviceArray = serviceStr.split(',');
  1716. }
  1717. if(serviceArray.contains(item['id'])){
  1718. serviceArray.remove(item['id']);
  1719. _totalNumber -= double.parse('${item['price']}');
  1720. }
  1721. if(serviceArray.length==0){
  1722. element.remove('services');
  1723. }else{
  1724. element['services'] = serviceArray.join(',');
  1725. }
  1726. });
  1727. widget.totalSetter(_totalNumber);
  1728. }else{
  1729. showModalBottomSheet(context: context, builder: (context){
  1730. return YSPersonChooseView(
  1731. personArray: widget.personArray,
  1732. isSingle: item['is_single']==1,
  1733. valueSetter: (value){
  1734. _chooseArray.add(item);
  1735. _totalNumber += double.parse('${item['price']}')*value.length;
  1736. setState(() {});
  1737. widget.totalSetter(_totalNumber);
  1738. },
  1739. serviceId: item['id'],
  1740. );
  1741. },backgroundColor: Colors.transparent);
  1742. }
  1743. },
  1744. child: Container(
  1745. padding: EdgeInsets.only(left: hsp(30),right: hsp(30),top: hsp(20)),
  1746. child: LayoutBuilder(
  1747. builder: (context,conSize){
  1748. return Row(
  1749. children: [
  1750. Icon(isChoose?Icons.check_box:Icons.check_box_outline_blank,size: hsp(40),color: isChoose?Colors.blue:Colors.grey,),
  1751. Container(
  1752. width: (conSize.maxWidth-hsp(40))*0.6,
  1753. padding: EdgeInsets.only(left: hsp(10)),
  1754. child: Text(item['name'],style: TextStyle(fontSize: zsp(28),color: Color(isChoose?0xFF333333:0xFF888888)),),
  1755. ),
  1756. Container(
  1757. width: (conSize.maxWidth-hsp(40))*0.4,
  1758. padding: EdgeInsets.only(left: hsp(10)),
  1759. child: Text('¥${item['price']}',style: TextStyle(fontSize: zsp(28),color: Color(isChoose?0xFFEC3323:0xFF888888)),),
  1760. alignment: Alignment.centerRight,
  1761. )
  1762. ],
  1763. );
  1764. },
  1765. ),
  1766. ),
  1767. );
  1768. },itemCount: _serviceArray.length,shrinkWrap: true,physics: NeverScrollableScrollPhysics(),padding: EdgeInsets.all(0),)
  1769. ],
  1770. ),
  1771. );
  1772. }
  1773. _getServiceData() async{
  1774. var dict = await ysRequestHttp(context,type: requestType.get,api: '/app/airplaneservice/dtAirplaneService/queryService',
  1775. parameter: {'type':widget.type,'tourId':widget.tourId},isLoading: true,isToken: false);
  1776. if(dict!=null){
  1777. setState(() {
  1778. _serviceArray = dict['data'];
  1779. });
  1780. }
  1781. }
  1782. }
  1783. class YSPersonChooseView extends StatefulWidget {
  1784. final List personArray;
  1785. final ValueSetter<List> valueSetter;
  1786. final bool isSingle;
  1787. final serviceId;
  1788. const YSPersonChooseView({Key key, this.personArray, this.valueSetter, this.isSingle = false, this.serviceId}) : super(key: key);
  1789. @override
  1790. _YSPersonChooseViewState createState() => _YSPersonChooseViewState();
  1791. }
  1792. class _YSPersonChooseViewState extends State<YSPersonChooseView> {
  1793. List _chooseArray = [];
  1794. @override
  1795. void initState() {
  1796. _chooseArray.add(widget.personArray.first);
  1797. super.initState();
  1798. }
  1799. @override
  1800. Widget build(BuildContext context) {
  1801. return Container(
  1802. height: hsp(500),
  1803. decoration: BoxDecoration(
  1804. color: Colors.white,
  1805. borderRadius: BorderRadius.only(topRight: Radius.circular(10),topLeft: Radius.circular(10))
  1806. ),
  1807. child: Column(
  1808. children: [
  1809. Container(
  1810. height: hsp(100),
  1811. alignment: Alignment.center,
  1812. child: Text('用户选择',style: TextStyle(fontSize: zsp(34),color: Color(0xFF353535)),),
  1813. decoration: BoxDecoration(
  1814. border: Border(bottom: BorderSide(color: Color(0xFFE5E5E5),width: hsp(1)))
  1815. ),
  1816. ),
  1817. Container(
  1818. height: hsp(300),
  1819. child: GridView.builder(gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
  1820. crossAxisCount: 5,
  1821. crossAxisSpacing: hsp(20),
  1822. mainAxisSpacing: hsp(20),
  1823. childAspectRatio: 2
  1824. ), itemBuilder: (context,index){
  1825. Map item = widget.personArray[index];
  1826. bool isChoose = _chooseArray.contains(item);
  1827. return GestureDetector(
  1828. onTap: (){
  1829. if(widget.isSingle){
  1830. _chooseArray.clear();
  1831. }
  1832. if(isChoose){
  1833. _chooseArray.remove(item);
  1834. }else{
  1835. _chooseArray.add(item);
  1836. }
  1837. setState(() {});
  1838. },
  1839. child: Stack(
  1840. children: [
  1841. Container(
  1842. decoration: BoxDecoration(
  1843. borderRadius: BorderRadius.all(Radius.circular(5)),
  1844. border: Border.all(color: Color(isChoose?0xFFE02515:0xFF8A8A8A),width: hsp(1))
  1845. ),
  1846. alignment: Alignment.center,
  1847. child: Text(item['username']??'',style: TextStyle(fontSize: zsp(30),color: Color(isChoose?0xFFE02515:0xFF8A8A8A)),),
  1848. )
  1849. ],
  1850. ),
  1851. );
  1852. },padding: EdgeInsets.all(hsp(30)),itemCount: widget.personArray.length,),
  1853. ),
  1854. Container(
  1855. height: hsp(100),
  1856. decoration: BoxDecoration(
  1857. border: Border(top: BorderSide(color: Color(0xFFE5E5E5),width: hsp(1)))
  1858. ),
  1859. padding: EdgeInsets.only(left: hsp(50),right: hsp(50),top: hsp(15),bottom: hsp(15)),
  1860. child: GestureDetector(
  1861. onTap: (){
  1862. if(_chooseArray.length==0){
  1863. ysFlutterToast(context, '至少需要选择一名用户');
  1864. return;
  1865. }
  1866. widget.personArray.forEach((element) {
  1867. String serviceStr = element['services']??'';
  1868. List serviceArray = [];
  1869. if(serviceStr.isNotEmpty){
  1870. serviceArray = serviceStr.split(',');
  1871. }
  1872. if(serviceArray.contains(widget.serviceId)){
  1873. serviceArray.remove(widget.serviceId);
  1874. }
  1875. if(serviceArray.length==0){
  1876. element.remove('services');
  1877. }else{
  1878. element['services'] = serviceArray.join(',');
  1879. }
  1880. });
  1881. _chooseArray.forEach((element) {
  1882. String serviceStr = element['services']??'';
  1883. List serviceArray = [];
  1884. if(serviceStr.isNotEmpty){
  1885. serviceArray = serviceStr.split(',');
  1886. }
  1887. if(serviceArray.contains(widget.serviceId)){
  1888. serviceArray.remove(widget.serviceId);
  1889. }
  1890. serviceArray.add(widget.serviceId);
  1891. element['services'] = serviceArray.join(',');
  1892. });
  1893. // LogUtil.d(widget.personArray);
  1894. // return;
  1895. widget.valueSetter(_chooseArray);
  1896. Navigator.pop(context);
  1897. },
  1898. child: Container(
  1899. decoration: BoxDecoration(
  1900. color: Color(0xFF007EFF),
  1901. borderRadius: BorderRadius.all(Radius.circular(50))
  1902. ),
  1903. alignment: Alignment.center,
  1904. child: Text('确定',style: TextStyle(fontSize: zsp(30),color: Colors.white),),
  1905. ),
  1906. ),
  1907. )
  1908. ],
  1909. ),
  1910. );
  1911. }
  1912. }
  1913. personCancel(List array) {
  1914. }
  1915. class YSSetMealView extends StatelessWidget {
  1916. final List packageArray;
  1917. final ValueSetter valueSetter;
  1918. const YSSetMealView({Key key, this.packageArray, this.valueSetter}) : super(key: key);
  1919. @override
  1920. Widget build(BuildContext context) {
  1921. return Container(
  1922. margin: EdgeInsets.only(top: hsp(10)),
  1923. color: Colors.white,
  1924. child: Column(
  1925. children: [
  1926. Container(
  1927. height: hsp(80),
  1928. padding: EdgeInsets.only(left: hsp(30)),
  1929. child: Text('选择套餐',style: TextStyle(fontSize: zsp(30),color: Color(0xFF9A9A9A)),),
  1930. alignment: Alignment.centerLeft,
  1931. decoration: BoxDecoration(
  1932. border: Border(bottom: BorderSide(color: Color(0xFFF1F2F4),width: hsp(1)))
  1933. ),
  1934. ),
  1935. ListView.builder(
  1936. itemBuilder: (context,index){
  1937. Map item = packageArray[index];
  1938. return Container(
  1939. padding: EdgeInsets.only(left: hsp(30),bottom: hsp(20),top: hsp(20),right: hsp(30)),
  1940. width: MediaQuery.of(context).size.width,
  1941. color: Colors.white,
  1942. child: Column(
  1943. crossAxisAlignment: CrossAxisAlignment.start,
  1944. children: [
  1945. Text('${item['name']}',style: TextStyle(fontSize: zsp(24),color: Color(0xFF888888)),),
  1946. Container(height: hsp(10),),
  1947. Row(
  1948. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  1949. children: [
  1950. RichText(
  1951. text: TextSpan(
  1952. text: '¥${item['price']}',
  1953. style: TextStyle(fontSize: zsp(32),color: Color(0xFFEB423B)),
  1954. children: [
  1955. TextSpan(
  1956. text: '/人',
  1957. style: TextStyle(fontSize: zsp(24),color: Color(0xFF8B8B8B))
  1958. )
  1959. ]
  1960. ),
  1961. ),
  1962. GestureDetector(
  1963. child: Container(
  1964. height: hsp(50),
  1965. width: hsp(100),
  1966. decoration: BoxDecoration(
  1967. color: Color(0xFFEA4D45),
  1968. borderRadius: BorderRadius.all(Radius.circular(3))
  1969. ),
  1970. alignment: Alignment.center,
  1971. child: Text('预订',style: TextStyle(fontSize: zsp(20),color: Colors.white),),
  1972. ),
  1973. onTap: (){
  1974. valueSetter(index);
  1975. },
  1976. )
  1977. ],
  1978. )
  1979. ],
  1980. ),
  1981. );
  1982. },
  1983. itemCount: packageArray.length,
  1984. padding: EdgeInsets.all(0),
  1985. physics: NeverScrollableScrollPhysics(),
  1986. shrinkWrap: true,
  1987. )
  1988. ],
  1989. ),
  1990. );
  1991. }
  1992. }