Hibok
No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.
 
 
 
 
 
 

1428 líneas
45 KiB

  1. import 'dart:io';
  2. import 'package:cached_network_image/cached_network_image.dart';
  3. import 'package:chat/chat/emoji_text.dart';
  4. import 'package:chat/chat/input_bar.dart';
  5. import 'package:chat/chat/my_special_text_span_builder.dart';
  6. import 'package:chat/data/UserData.dart';
  7. import 'package:chat/data/constants.dart';
  8. import 'package:chat/generated/i18n.dart';
  9. import 'package:chat/home/MyDialogContent.dart';
  10. import 'package:chat/home/SelectPage.dart';
  11. import 'package:chat/home/VerificationCenter.dart';
  12. import 'package:chat/home/VipPage.dart';
  13. import 'package:chat/models/money_change.dart';
  14. import 'package:chat/utils/ChargeMoney.dart';
  15. import 'package:chat/utils/CustomUI.dart';
  16. import 'package:chat/utils/HttpUtil.dart';
  17. import 'package:chat/utils/MessageMgr.dart';
  18. import 'package:chat/utils/PicSwiper.dart';
  19. import 'package:chat/utils/file_cache_mgr.dart';
  20. import 'package:chat/utils/keyboard/bottom_area_avoider.dart';
  21. import 'package:chat/utils/keyboard_utils.dart';
  22. import 'package:chat/utils/screen.dart';
  23. import 'package:dio/dio.dart';
  24. import 'package:extended_text_field/extended_text_field.dart';
  25. import 'package:flutter/material.dart';
  26. import 'package:flutter/services.dart';
  27. import 'package:flutter_screenutil/flutter_screenutil.dart';
  28. import 'package:multi_image_picker/multi_image_picker.dart';
  29. import 'package:oktoast/oktoast.dart';
  30. import 'package:provider/provider.dart';
  31. import 'package:shared_preferences/shared_preferences.dart';
  32. import '../utils/ShadowButton.dart';
  33. import '../data/UserData.dart';
  34. import '../utils/TokenMgr.dart';
  35. import '../data/WebData.dart';
  36. class AddProgram extends StatefulWidget {
  37. @required
  38. final bool isProgram;
  39. AddProgram({Key key, this.isProgram = true}) : super(key: key);
  40. _AddProgramState createState() => _AddProgramState();
  41. }
  42. const double LEFT_WIDTH = 80;
  43. const int Max_Img_Num = 4;
  44. class _AddProgramState extends State<AddProgram> {
  45. //期待对象
  46. String lovePeople = "";
  47. Set<String> lovePeopleId = new Set();
  48. //约会范围
  49. String dateRange = "";
  50. Set<String> dateRangeId = new Set();
  51. //开始时间
  52. String beginTime = '';
  53. String beginTimeId = '';
  54. //结束时间
  55. String endTime = '';
  56. var endTimeId = -1;
  57. //List<File> imgFileList = [];
  58. //上传图片地址
  59. List<String> imgUrlList = [];
  60. //禁止评论
  61. bool isCanContent = false;
  62. bool isHidden = false;
  63. int programId = -1;
  64. String programCat = '';
  65. // String content = '';
  66. @override
  67. void initState() {
  68. super.initState();
  69. print('AddProgram initState');
  70. _bloc.start();
  71. getKeyboardHeight();
  72. focusNode.addListener(_focusNodeListener);
  73. msgMgr.on('Keyboard Hide', dealWithKeyboardHide);
  74. }
  75. @override
  76. void dispose() {
  77. focusNode.removeListener(_focusNodeListener);
  78. _bloc.dispose();
  79. msgMgr.off('Keyboard Hide', dealWithKeyboardHide);
  80. super.dispose();
  81. }
  82. ///keyboard相关-----------------------------------------------------------------------------------------------
  83. KeyboardBloc _bloc = KeyboardBloc();
  84. MessageMgr msgMgr = MessageMgr();
  85. double keyboardHeight;
  86. final _keyParent = GlobalKey();
  87. double _offset = 0;
  88. Duration _timeToDismiss = Duration(milliseconds: 120);
  89. OverlayEntry _overlayEntry;
  90. FocusNode focusNode = new FocusNode();
  91. bool get _isShowing {
  92. return _overlayEntry != null;
  93. }
  94. bool isShowEmoji = false;
  95. bool _dismissAnimationNeeded = true;
  96. double _kBarSize = 45.0;
  97. bool isActionFromButton = false;
  98. dealWithKeyboardHide(args) {
  99. if (!isActionFromButton) {
  100. closeEmojiAction();
  101. }
  102. }
  103. TextEditingController _textCtrl = TextEditingController();
  104. final ValueNotifier<bool> _counter = ValueNotifier<bool>(false);
  105. void _insertOverlay() {
  106. print('插入界面');
  107. OverlayState os = Overlay.of(context);
  108. _overlayEntry = OverlayEntry(builder: (context) {
  109. // Update and build footer, if any
  110. final queryData = MediaQuery.of(context);
  111. return Positioned(
  112. bottom: queryData.viewInsets.bottom,
  113. left: 0,
  114. right: 0,
  115. child: SafeArea(
  116. child: Container(
  117. height: _kBarSize,
  118. child: Column(
  119. mainAxisSize: MainAxisSize.min,
  120. children: [
  121. Material(
  122. color: Colors.grey[200],
  123. child: Column(
  124. mainAxisSize: MainAxisSize.min,
  125. children: <Widget>[
  126. Divider(
  127. height: 1,
  128. color: Color(0xffb0b0b0),
  129. ),
  130. InkWell(
  131. child: Container(
  132. padding: EdgeInsets.only(left: 15),
  133. height: 43,
  134. color: Colors.white,
  135. alignment: Alignment.centerLeft,
  136. child: Icon(
  137. IconData(isShowEmoji ? 0xe655 : 0xe651,
  138. fontFamily: Constants.IconFontFamily),
  139. size: 27,
  140. color: Color(0xffb0b0b0)),
  141. ),
  142. onTap: () {
  143. setState(() {
  144. isActionFromButton = true;
  145. isShowEmoji = !isShowEmoji;
  146. _kBarSize = isShowEmoji ? keyboardHeight : 45;
  147. if (isShowEmoji) {
  148. SystemChannels.textInput
  149. .invokeMethod('TextInput.hide');
  150. } else {
  151. SystemChannels.textInput
  152. .invokeMethod('TextInput.show');
  153. }
  154. if (isShowEmoji) {
  155. Future.delayed(Duration(milliseconds: 200), () {
  156. ///150延迟防止界面越界
  157. _counter.value = isShowEmoji;
  158. });
  159. Future.delayed(Duration(milliseconds: 1000), () {
  160. ///缩下键盘的时候-防止表情被关闭
  161. isActionFromButton = false;
  162. });
  163. } else {
  164. _counter.value = isShowEmoji;
  165. Future.delayed(Duration(milliseconds: 360), () {
  166. ///150延迟防止界面越界
  167. isActionFromButton = false;
  168. });
  169. }
  170. });
  171. },
  172. ),
  173. ValueListenableBuilder(
  174. builder:
  175. (BuildContext context, bool value, Widget child) {
  176. return value
  177. ? Container(
  178. width: MediaQuery.of(context).size.width,
  179. child: buildEmojiGird(),
  180. )
  181. : SizedBox(
  182. height: 1,
  183. );
  184. },
  185. valueListenable: _counter,
  186. ),
  187. ],
  188. ),
  189. ),
  190. ],
  191. ),
  192. ),
  193. ),
  194. );
  195. });
  196. os.insert(_overlayEntry);
  197. }
  198. getKeyboardHeight() async {
  199. var sp = await SharedPreferences.getInstance();
  200. keyboardHeight = sp.getDouble(Constants.KeyboardHeight);
  201. print('keyboardHeight : $keyboardHeight');
  202. }
  203. Future<Null> _focusNodeListener() async {
  204. print('监听');
  205. if (isShowEmoji) {
  206. return;
  207. }
  208. _focusChanged(focusNode.hasFocus);
  209. }
  210. _focusChanged(bool showBar) {
  211. print('showBar $showBar _isShowing:$_isShowing');
  212. if (showBar && !_isShowing) {
  213. _insertOverlay();
  214. } else if (!showBar && _isShowing) {
  215. _removeOverlay();
  216. } else if (showBar && _isShowing) {
  217. _overlayEntry.markNeedsBuild();
  218. }
  219. }
  220. /// Remove the overlay bar. Call when losing focus or being dismissed.
  221. void _removeOverlay({bool fromDispose = false}) async {
  222. if (_dismissAnimationNeeded) {
  223. if (mounted && !fromDispose) {
  224. _overlayEntry?.markNeedsBuild();
  225. await Future.delayed(_timeToDismiss);
  226. }
  227. }
  228. _overlayEntry?.remove();
  229. _overlayEntry = null;
  230. if (!fromDispose && _dismissAnimationNeeded) _updateOffset();
  231. _dismissAnimationNeeded = true;
  232. }
  233. void _updateOffset() {
  234. if (!mounted) {
  235. return;
  236. }
  237. if (!_isShowing) {
  238. setState(() {
  239. _offset = 0.0;
  240. });
  241. return;
  242. }
  243. double newOffset = _kBarSize; // offset for the actions bar
  244. newOffset += MediaQuery.of(context)
  245. .viewInsets
  246. .bottom; // + offset for the system keyboard
  247. if (newOffset < 0) newOffset = 0;
  248. // Update state if changed
  249. if (_offset != newOffset) {
  250. setState(() {
  251. _offset = newOffset;
  252. });
  253. }
  254. }
  255. Widget buildEmojiGird() {
  256. return Container(
  257. height: keyboardHeight - 44,
  258. child: Stack(
  259. children: <Widget>[
  260. Padding(
  261. padding: EdgeInsets.fromLTRB(5, 8, 50, 0),
  262. child: GridView.builder(
  263. controller: new ScrollController(keepScrollOffset: false),
  264. gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
  265. crossAxisCount: 7, crossAxisSpacing: 0, mainAxisSpacing: 0),
  266. itemBuilder: (context, index) {
  267. return GestureDetector(
  268. child: Container(
  269. padding: EdgeInsets.all(7),
  270. child: Image.asset(EmojiUitl
  271. .instance.emojiMap[EmojiText.flag + "${index + 1}]"]),
  272. ),
  273. behavior: HitTestBehavior.translucent,
  274. onTap: () {
  275. if (_textCtrl.value.text.length < 94) {
  276. InputBarState.insertText(
  277. EmojiText.flag + "${index + 1}]", _textCtrl);
  278. }
  279. // setState(() {
  280. // _isComposingMessage = _textCtrl.text.length > 0;
  281. // });
  282. },
  283. );
  284. },
  285. itemCount: EmojiUitl.instance.emojiMap.length,
  286. padding: EdgeInsets.all(5.0),
  287. ),
  288. ),
  289. Positioned.fill(
  290. child: Container(
  291. padding: EdgeInsets.fromLTRB(0, 0, 0, 14),
  292. alignment: Alignment(1, 1),
  293. child: InkWell(
  294. onTap: () {
  295. InputBarState.deleteText(_textCtrl);
  296. },
  297. child: Container(
  298. decoration: BoxDecoration(
  299. color: Color(0x4d0E0E10),
  300. borderRadius: BorderRadius.only(
  301. topLeft: Radius.circular(4.0),
  302. bottomLeft: Radius.circular(4))),
  303. width: 37,
  304. height: 28,
  305. child: Icon(
  306. IconData(
  307. 0xe679,
  308. fontFamily: 'iconfont',
  309. ),
  310. size: 16,
  311. color: Colors.white,
  312. ),
  313. ),
  314. ),
  315. )),
  316. ],
  317. ),
  318. );
  319. }
  320. ///keyboard相关------------------------------------------------------------------------------------------------------------
  321. void closeEmojiAction() {
  322. print('### closeEmojiAction');
  323. FocusScope.of(context).requestFocus(FocusNode());
  324. isShowEmoji = false;
  325. _counter.value = isShowEmoji;
  326. _removeOverlay();
  327. _offset = 0;
  328. _kBarSize = isShowEmoji ? keyboardHeight : 45;
  329. }
  330. ScrollController _scrollController = new ScrollController();
  331. @override
  332. Widget build(BuildContext context) {
  333. Widget appBar = new AppBar(
  334. backgroundColor: AppColors.NewAppbarBgColor,
  335. title: Text(
  336. widget.isProgram
  337. ? I18n.of(context).release_program
  338. : I18n.of(context).release_dynamics,
  339. style: TextStyle(color: AppColors.NewAppbarTextColor),
  340. ),
  341. elevation: 0,
  342. leading: CustomUI.buildCustomLeading(context, onTap: () {
  343. closeEmojiAction();
  344. Navigator.of(context).pop();
  345. }),
  346. centerTitle: true,
  347. );
  348. return WillPopScope(
  349. child: Scaffold(
  350. appBar: appBar,
  351. body: SafeArea(
  352. child: Center(
  353. child: Container(
  354. height: MediaQuery.of(context).size.height,
  355. width: MediaQuery.of(context).size.width,
  356. child: GestureDetector(
  357. onTap: () {
  358. closeEmojiAction();
  359. },
  360. child: Material(
  361. color: Colors.transparent,
  362. child: SizedBox(
  363. width: double.maxFinite,
  364. key: _keyParent,
  365. child: BottomAreaAvoider(
  366. scrollTo: _scrollController,
  367. areaToAvoid: _offset,
  368. duration: Duration(
  369. milliseconds:
  370. (_timeToDismiss.inMilliseconds * 1.8).toInt()),
  371. autoScroll: true,
  372. child: Container(
  373. child: Column(
  374. children: <Widget>[_buildBody()],
  375. ),
  376. ),
  377. ),
  378. ),
  379. ),
  380. ),
  381. ),
  382. )),
  383. ),
  384. onWillPop: () {
  385. closeEmojiAction();
  386. return Future.value(true);
  387. });
  388. }
  389. // Future<bool> _willPop() {
  390. // print('###### willpop');
  391. //// tempDispose=true;
  392. //// closeEmojiAction();
  393. //// print('isshowemoji:$isShowEmoji');
  394. //// _counter.value = false;
  395. //// print('关闭emoji');
  396. //// FocusScope.of(context).requestFocus(FocusNode());
  397. // Navigator.pop(context);
  398. // return new Future.value(false);
  399. // }
  400. BoxDecoration _getCardDecoration() {
  401. return new BoxDecoration(
  402. color: Colors.white,
  403. boxShadow: [
  404. BoxShadow(
  405. color: Color.fromRGBO(230, 230, 230, 1),
  406. offset: Offset(0, 10),
  407. blurRadius: 8,
  408. )
  409. ],
  410. );
  411. }
  412. //节目主题
  413. Widget _buildProgramCat() {
  414. return new Container(
  415. margin: EdgeInsets.only(top: 15),
  416. decoration: _getCardDecoration(),
  417. child: _bottomBorderBox(
  418. I18n.of(context).program_theme,
  419. programCat == '' ? I18n.of(context).choose : programCat,
  420. false,
  421. null, () {
  422. CustomUI.buildTip(
  423. context, I18n.of(context).please_choose, _buildCategoryButton());
  424. }, rightTextGrey: programCat == ''),
  425. );
  426. }
  427. //选择期待对象
  428. void selectLovePeople() {
  429. var tempSet = lovePeopleId.toSet();
  430. List<Widget> actions = [
  431. FlatButton(
  432. child: fixedText(I18n.of(context).close),
  433. onPressed: () {
  434. tempSet.clear();
  435. Navigator.of(context).pop();
  436. },
  437. ),
  438. FlatButton(
  439. child: fixedText(I18n.of(context).determine),
  440. onPressed: () {
  441. Navigator.of(context).pop();
  442. setState(() {
  443. lovePeopleId = tempSet.toSet();
  444. lovePeople = '';
  445. lovePeopleId.forEach((k) {
  446. lovePeople += (lovePeople == '')
  447. ? WebData().loverPeopleMap[k]
  448. : ('/' + WebData().loverPeopleMap[k]);
  449. });
  450. });
  451. },
  452. ),
  453. ];
  454. //约会节目
  455. showDialog(
  456. context: context,
  457. builder: (BuildContext context) {
  458. return AlertDialog(
  459. title: new Align(
  460. alignment: Alignment.center,
  461. child: Text(I18n.of(context).expect_lover, textScaleFactor: 1.0),
  462. ),
  463. content: new MyDialogContent(
  464. mostNum: 4,
  465. dataMap: WebData().loverPeopleMap,
  466. keyList: tempSet,
  467. ),
  468. contentPadding: EdgeInsets.only(top: 10),
  469. actions: actions,
  470. );
  471. });
  472. }
  473. //选择约会地区
  474. void selectDateRange() async {
  475. Navigator.of(context).push(
  476. new MaterialPageRoute(
  477. builder: (context) {
  478. return SelectPage(
  479. mostNum: 4,
  480. dataId: dateRangeId,
  481. title: I18n.of(context).select_city,
  482. provinces: {'VietNam': WebData().provinces['VietNam']},
  483. cities: WebData().cities,
  484. isSingle: true,
  485. callback: (tempRankId) {
  486. dateRangeId = tempRankId.toSet();
  487. dateRange = '';
  488. dateRangeId.forEach((item) {
  489. var city = item.split('-');
  490. dateRange += dateRange == ''
  491. ? WebData().cities[city[0]][city[1]]
  492. : '/${WebData().cities[city[0]][city[1]]}';
  493. });
  494. Navigator.of(context).pop();
  495. },
  496. );
  497. },
  498. ),
  499. );
  500. }
  501. //选择开始时间
  502. void selectBegin() async {
  503. DateTime _date = DateTime.now();
  504. final DateTime picked = await showDatePicker(
  505. context: context,
  506. initialDate: _date,
  507. firstDate: DateTime(_date.year, _date.month, _date.day),
  508. locale: WebData().locale,
  509. lastDate: DateTime(_date.year, _date.month, _date.day + 7));
  510. setState(() {
  511. if (picked != null) {
  512. beginTime = '${picked.year}-${picked.month}-${picked.day}';
  513. beginTimeId = '${picked.year}-${picked.month}-${picked.day}';
  514. }
  515. });
  516. if (picked == null) _date = DateTime.now();
  517. }
  518. //分类按钮
  519. Widget _buildCategoryButton() {
  520. return Container(
  521. padding: EdgeInsets.only(top: 10),
  522. child: Column(
  523. children: <Widget>[
  524. Container(
  525. child: Row(
  526. mainAxisAlignment: MainAxisAlignment.spaceEvenly,
  527. children: <Widget>[
  528. _buildIconButton(1, WebData().getProgramName(context, 0),
  529. Constants.Category1Color, 0),
  530. _buildIconButton(2, WebData().getProgramName(context, 1),
  531. Constants.Category2Color, 1),
  532. _buildIconButton(3, WebData().getProgramName(context, 2),
  533. Constants.Category3Color, 2),
  534. _buildIconButton(4, WebData().getProgramName(context, 3),
  535. Constants.Category4Color, 3),
  536. ],
  537. ),
  538. ),
  539. Container(
  540. child: Row(
  541. mainAxisAlignment: MainAxisAlignment.spaceEvenly,
  542. children: <Widget>[
  543. _buildIconButton(5, WebData().getProgramName(context, 4),
  544. Constants.Category5Color, 4),
  545. _buildIconButton(6, WebData().getProgramName(context, 5),
  546. Constants.Category6Color, 5),
  547. _buildIconButton(7, WebData().getProgramName(context, 6),
  548. Constants.Category7Color, 6),
  549. _buildIconButton(8, WebData().getProgramName(context, 7),
  550. Constants.Category8Color, 7),
  551. ],
  552. ),
  553. ),
  554. ],
  555. ));
  556. }
  557. Widget _buildIconButton(iconNum, str, strColor, value) {
  558. Widget icon = Container(
  559. padding: EdgeInsets.only(bottom: 10),
  560. child: Image.asset(
  561. 'assets/images/park/qz_icon$iconNum.png',
  562. height: 60,
  563. ));
  564. Widget text = Positioned(
  565. bottom: 0,
  566. child: Container(
  567. child: new Text(str,
  568. textScaleFactor: 1.0,
  569. style: TextStyle(
  570. color: strColor, fontWeight: FontWeight.w700, fontSize: 13)),
  571. ));
  572. return InkWell(
  573. onTap: () {
  574. setState(() {
  575. programId = value;
  576. programCat = WebData().getProgramName(context, value);
  577. Navigator.of(context).pop();
  578. });
  579. },
  580. highlightColor: Colors.transparent,
  581. radius: 0,
  582. child: Container(
  583. width: (MediaQuery.of(context).size.width * 0.9) / 4,
  584. margin: EdgeInsets.only(top: 10),
  585. child: Stack(
  586. alignment: Alignment.center,
  587. children: <Widget>[
  588. icon,
  589. text,
  590. ],
  591. ),
  592. ));
  593. }
  594. Widget _buildTimeSelect(str, value) {
  595. return InkWell(
  596. child: Container(
  597. margin: EdgeInsets.only(top: 5, bottom: 5),
  598. height: 20,
  599. alignment: Alignment.center,
  600. child: Text(
  601. str,
  602. textScaleFactor: 1.0,
  603. style: TextStyle(fontSize: 15, color: Constants.BlackTextColor),
  604. ),
  605. ),
  606. onTap: () async {
  607. if (WebData().testTimeOver(value, beginTimeId)) {
  608. showToast(I18n.of(context).outTime);
  609. return;
  610. }
  611. setState(() {
  612. endTimeId = value;
  613. endTime = str;
  614. Navigator.of(context).pop();
  615. });
  616. },
  617. );
  618. }
  619. //选择结束时间
  620. void selectEnd() async {
  621. Widget title = Container(
  622. margin: EdgeInsets.only(top: 15, bottom: 10),
  623. alignment: Alignment.center,
  624. child: Text(
  625. I18n.of(context).select_time,
  626. textScaleFactor: 1.0,
  627. style: TextStyle(fontSize: 19, color: Constants.BlackTextColor),
  628. ),
  629. );
  630. List<Widget> list = [title];
  631. WebData().getDateTime(context).forEach((k, v) {
  632. list.add(Divider());
  633. list.add(_buildTimeSelect(v, k));
  634. });
  635. if (beginTimeId == '') {
  636. showToast(I18n.of(context).please_choose4);
  637. return;
  638. }
  639. showModalBottomSheet(
  640. context: context,
  641. builder: (BuildContext context) {
  642. return SafeArea(
  643. child: Container(
  644. height: 345,
  645. child: Column(children: list),
  646. ));
  647. },
  648. ).then((val) {});
  649. }
  650. void _sendPicture() async {
  651. closeEmojiAction();
  652. List<Asset> resultList = List<Asset>();
  653. resultList = await MultiImagePicker.pickImages(
  654. maxImages: Max_Img_Num - imgUrlList.length,
  655. enableCamera: false,
  656. selectedAssets: [],
  657. cupertinoOptions: CupertinoOptions(takePhotoIcon: "chat"),
  658. materialOptions: MaterialOptions(
  659. actionBarColor: "#50A7F9",
  660. actionBarTitle: "Hibok",
  661. allViewTitle: "",
  662. useDetailsView: false,
  663. selectCircleStrokeColor: "#000000",
  664. ),
  665. );
  666. if (resultList != null && resultList.length > 0) {
  667. List<File> fileList = [];
  668. for (var i = 0; i < resultList.length; i++) {
  669. Asset photoEntity = resultList[i];
  670. print('名字:${photoEntity.name}');
  671. ByteData byteData = await photoEntity.getByteData();
  672. File file = await FileCacheMgr().writeFile(
  673. 'temp-photo-${DateTime.now().millisecondsSinceEpoch}.png',
  674. byteData.buffer.asInt8List(0));
  675. fileList.add(file);
  676. }
  677. print('文件列表${fileList.length}');
  678. Map data = {"type": 7, "userId": UserData().basicInfo.userId};
  679. data['sign'] = TokenMgr().getSign(data);
  680. Response res = await HttpUtil().uploadFiles(
  681. fileList, data, 'upload/post/postfiles', 'image',
  682. isShowLoading: true);
  683. var resData = res.data;
  684. if (resData['code'] == 0 && resData['msg'] != null) {
  685. var returnList = resData['msg'].split('|');
  686. imgUrlList.addAll(returnList);
  687. if (returnList.length != fileList.length) {
  688. showToast(I18n.of(context).hava_error_photo);
  689. }
  690. setState(() {});
  691. }
  692. }
  693. // var photos = await PhotoPicker.pickAsset(
  694. // context: context,
  695. // themeColor: Color(0xFFF0F0F0),
  696. // maxSelected: Max_Img_Num - imgUrlList.length,
  697. // textColor: Color(0xFF3F3F3F),
  698. // pickType: PickType.onlyImage);
  699. //
  700. // if (photos != null && photos.length > 0) {
  701. // List<File> fileList = [];
  702. // for (var i = 0; i < photos.length; i++) {
  703. // AssetEntity photoEntity = photos[i];
  704. // fileList.add(await photoEntity.file);
  705. // }
  706. // Map data = {"type": 3, "userId": UserData().basicInfo.userId};
  707. // data['sign'] = TokenMgr().getSign(data);
  708. // Response res = await HttpUtil().uploadFiles(
  709. // fileList, data, 'upload/post/postfiles', 'image',
  710. // isShowLoading: true);
  711. // var resData = res.data;
  712. // if (resData['code'] == 0 && resData['msg'] != null) {
  713. // imgUrlList.addAll(resData['msg'].split("|"));
  714. // setState(() {});
  715. // }
  716. // }
  717. }
  718. Widget _buildDynicContent() {
  719. Widget moreInfo = Container(
  720. alignment: Alignment.topCenter,
  721. padding: EdgeInsets.only(left: 15, right: 15),
  722. child: ExtendedTextField(
  723. keyboardAppearance: Brightness.light,
  724. onTap: () {
  725. // if(!isActionFromButton){
  726. isShowEmoji = false;
  727. _counter.value = isShowEmoji;
  728. _kBarSize = isShowEmoji ? keyboardHeight : 45;
  729. // }
  730. },
  731. focusNode: focusNode,
  732. specialTextSpanBuilder:
  733. MySpecialTextSpanBuilder(showAtBackground: true, emojiSize: 17.0),
  734. decoration: new InputDecoration(
  735. hintText: I18n.of(context).please_civilization,
  736. hintStyle: TextStyle(fontSize: 13, height: 1.25),
  737. border: InputBorder.none,
  738. ),
  739. maxLines: 6,
  740. controller: _textCtrl,
  741. style: TextStyle(
  742. fontSize: ScreenUtil().setSp(14),
  743. textBaseline: TextBaseline.alphabetic),
  744. inputFormatters: [LengthLimitingTextInputFormatter(100)],
  745. onChanged: (str) {
  746. if (str.length > 100) {
  747. print('超过100了');
  748. _textCtrl.text = _textCtrl.value.text.substring(0, 100);
  749. int length = _textCtrl.text.length;
  750. Future.delayed(Duration(milliseconds: 100), () {
  751. _textCtrl.selection =
  752. TextSelection(baseOffset: length, extentOffset: length);
  753. });
  754. }
  755. },
  756. ));
  757. List<Widget> imgList = imgUrlList.map((f) {
  758. return _buildImg(f);
  759. }).toList();
  760. if (imgList.length < Max_Img_Num) {
  761. imgList.add(_buildUpButton());
  762. }
  763. Widget picture = Container(
  764. alignment: Alignment.centerLeft,
  765. padding: EdgeInsets.only(left: 15, bottom: 15),
  766. child: Wrap(alignment: WrapAlignment.start, children: imgList));
  767. List<Widget> list = [moreInfo, picture];
  768. return new Container(
  769. margin: EdgeInsets.only(top: 15),
  770. decoration: _getCardDecoration(),
  771. child: Column(
  772. children: list,
  773. ),
  774. );
  775. }
  776. Widget _buildUpButton() {
  777. var color = Colors.grey[350];
  778. return Container(
  779. child: InkWell(
  780. onTap: _sendPicture,
  781. child: Container(
  782. margin: EdgeInsets.only(left: 5, right: 5, top: 5, bottom: 5),
  783. decoration: BoxDecoration(
  784. borderRadius: BorderRadius.circular(10.0),
  785. border: Border.all(color: color)),
  786. width: 75,
  787. height: 75,
  788. child: ClipRRect(
  789. borderRadius: BorderRadius.circular(10),
  790. child: Icon(
  791. IconData(
  792. 0xe616,
  793. fontFamily: 'iconfont',
  794. ),
  795. color: color),
  796. ))));
  797. }
  798. //节目内容
  799. Widget _buildProgramContent() {
  800. Widget moreInfo = Container(
  801. child: Column(
  802. crossAxisAlignment: CrossAxisAlignment.start,
  803. mainAxisAlignment: MainAxisAlignment.start,
  804. children: <Widget>[
  805. Container(
  806. width: Screen.width,
  807. padding: EdgeInsets.only(
  808. top: 15,
  809. ),
  810. margin: EdgeInsets.only(left: 15),
  811. child: Text(
  812. I18n.of(context).describe_details,
  813. textScaleFactor: 1.0,
  814. style: TextStyle(fontSize: 14, fontWeight: FontWeight.w600),
  815. )),
  816. Container(
  817. padding: EdgeInsets.only(right: 5),
  818. margin: EdgeInsets.only(left: 15),
  819. child: ExtendedTextField(
  820. keyboardAppearance: Brightness.light,
  821. focusNode: focusNode,
  822. onTap: () {
  823. // if(!isActionFromButton){
  824. isShowEmoji = false;
  825. _counter.value = isShowEmoji;
  826. _kBarSize = isShowEmoji ? keyboardHeight : 45;
  827. // }
  828. if (_scrollController != null) {
  829. ///解决键盘遮挡输入框
  830. _scrollController.position.moveTo(
  831. 200,
  832. duration: Duration(milliseconds: 100),
  833. curve: Curves.easeIn,
  834. );
  835. }
  836. },
  837. controller: _textCtrl,
  838. specialTextSpanBuilder: MySpecialTextSpanBuilder(
  839. showAtBackground: true, emojiSize: 17.0),
  840. decoration: new InputDecoration(
  841. contentPadding:
  842. EdgeInsets.only(top: 6, bottom: 10, right: 10),
  843. hintText: I18n.of(context).please_civilization,
  844. hintStyle: TextStyle(fontSize: 12, height: 1.15),
  845. border: InputBorder.none,
  846. ),
  847. style: TextStyle(
  848. fontSize: 13, textBaseline: TextBaseline.alphabetic),
  849. maxLines: 6,
  850. // inputFormatters: [LengthLimitingTextInputFormatter(100)],
  851. onChanged: (str) {
  852. if (str.length > 100) {
  853. print('超过100了');
  854. _textCtrl.text = _textCtrl.value.text.substring(0, 100);
  855. int length = _textCtrl.text.length;
  856. Future.delayed(Duration(milliseconds: 100), () {
  857. _textCtrl.selection = TextSelection(
  858. baseOffset: length, extentOffset: length);
  859. });
  860. }
  861. },
  862. )),
  863. ],
  864. ),
  865. );
  866. List<Widget> imgList = imgUrlList.map((f) {
  867. return _buildImg(f);
  868. }).toList();
  869. if (imgList.length < Max_Img_Num) {
  870. imgList.add(_buildUpButton());
  871. }
  872. Widget picture = Container(
  873. alignment: Alignment.topCenter,
  874. child: Row(
  875. children: <Widget>[
  876. Container(
  877. alignment: Alignment.centerLeft,
  878. width: LEFT_WIDTH,
  879. margin: EdgeInsets.only(left: 15),
  880. child: fixedText(I18n.of(context).image,
  881. fontSize: 14, fontWeight: FontWeight.w600)),
  882. Expanded(
  883. child: Container(
  884. margin: EdgeInsets.only(top: 10, bottom: 10),
  885. child:
  886. Wrap(alignment: WrapAlignment.start, children: imgList))),
  887. ],
  888. ),
  889. );
  890. List<Widget> list = [
  891. _bottomBorderBox(
  892. I18n.of(context).expect_lover,
  893. lovePeople == '' ? I18n.of(context).choose : lovePeople,
  894. false,
  895. null,
  896. selectLovePeople,
  897. rightTextGrey: lovePeople == ''),
  898. _buildDivider(),
  899. // _bottomBorderBox(
  900. // I18n.of(context).city,
  901. // dateRange == '' ? I18n.of(context).choose : dateRange,
  902. // false,
  903. // null,
  904. // selectDateRange,
  905. // rightTextGrey: dateRange == ''),
  906. // _buildDivider(),
  907. _bottomBorderBox(
  908. I18n.of(context).time,
  909. beginTime == '' ? I18n.of(context).choose : beginTime,
  910. false,
  911. null,
  912. selectBegin,
  913. rightTextGrey: beginTime == ''),
  914. _buildDivider(),
  915. _bottomBorderBox('', endTime == '' ? I18n.of(context).choose : endTime,
  916. false, null, selectEnd,
  917. rightTextGrey: endTime == ''),
  918. _buildDivider(),
  919. moreInfo,
  920. _buildDivider(),
  921. picture
  922. ];
  923. return new Container(
  924. margin: EdgeInsets.only(top: 15),
  925. decoration: _getCardDecoration(),
  926. child: Column(
  927. children: list,
  928. ),
  929. );
  930. }
  931. //下划线
  932. Widget _buildDivider() {
  933. return new Container(
  934. margin: EdgeInsets.zero,
  935. padding: EdgeInsets.zero,
  936. decoration: BoxDecoration(border: Border(top: Constants.GreyBorderSide)),
  937. height: 1,
  938. width: MediaQuery.of(context).size.width * 0.9,
  939. );
  940. }
  941. Widget _buildImg(f) {
  942. return Stack(
  943. children: <Widget>[
  944. InkWell(
  945. onTap: () {
  946. Navigator.of(context).push(
  947. new MaterialPageRoute(
  948. builder: (context) {
  949. return PicSwiper(
  950. id: imgUrlList.indexOf(f),
  951. pics: imgUrlList
  952. .map((f) => PicSwiperItem(
  953. f,
  954. id: imgUrlList.indexOf(f),
  955. ))
  956. .toList(),
  957. );
  958. },
  959. ),
  960. );
  961. },
  962. child: Container(
  963. height: 75,
  964. width: 75,
  965. margin: EdgeInsets.only(left: 5, right: 5, top: 5, bottom: 5),
  966. decoration: BoxDecoration(
  967. borderRadius: BorderRadius.circular(10.0),
  968. border: Border.all(color: Colors.grey[300], width: 1),
  969. ),
  970. child: ClipRRect(
  971. borderRadius: BorderRadius.circular(10),
  972. child: f == null
  973. ? Container()
  974. : CachedNetworkImage(
  975. imageUrl: f,
  976. fit: BoxFit.cover,
  977. placeholder: CustomUI.buildImgLoding,
  978. ),
  979. ))),
  980. Positioned(
  981. right: 0,
  982. child: InkWell(
  983. onTap: () {
  984. imgUrlList.remove(f);
  985. setState(() {});
  986. },
  987. child: Image.asset(
  988. 'assets/images/login/delete.png',
  989. height: 20,
  990. )),
  991. )
  992. ],
  993. );
  994. }
  995. //自定义item
  996. Widget _bottomBorderBox(
  997. String textLeft, String textRight, bool flag, controller, callback,
  998. {bool rightTextGrey = true}) {
  999. Widget left = new Container(
  1000. width: LEFT_WIDTH,
  1001. child: new Text(
  1002. textLeft,
  1003. textScaleFactor: 1.0,
  1004. style: TextStyle(fontSize: 14, fontWeight: FontWeight.w600),
  1005. ));
  1006. Widget right = flag
  1007. ? new Expanded(
  1008. child: new TextField(
  1009. keyboardAppearance: Brightness.light,
  1010. controller: controller,
  1011. decoration: new InputDecoration(
  1012. hintText: textRight,
  1013. hintStyle: TextStyle(fontSize: 14),
  1014. border: InputBorder.none,
  1015. ),
  1016. style: TextStyle(textBaseline: TextBaseline.alphabetic),
  1017. maxLines: 1,
  1018. onChanged: (str) {
  1019. if (flag && callback != null) callback(str);
  1020. },
  1021. ),
  1022. )
  1023. : new Expanded(
  1024. child: GestureDetector(
  1025. onTap: () {
  1026. if (!flag && callback != null) callback();
  1027. },
  1028. child: Container(
  1029. color: Colors.transparent,
  1030. height: 53,
  1031. width: MediaQuery.of(context).size.width,
  1032. alignment: Alignment.centerLeft,
  1033. padding: EdgeInsets.only(left: 5),
  1034. child: Text(
  1035. textRight,
  1036. textScaleFactor: 1.0,
  1037. style: TextStyle(
  1038. fontSize: 14,
  1039. color: rightTextGrey
  1040. ? Constants.GreyTextColor
  1041. : Constants.BlackTextColor),
  1042. ),
  1043. ),
  1044. ),
  1045. );
  1046. return new Container(
  1047. height: 53,
  1048. margin: EdgeInsets.only(left: 15, bottom: 0),
  1049. child: new Row(
  1050. children: <Widget>[left, right],
  1051. ),
  1052. );
  1053. }
  1054. Widget _buildSwitch(str, value, callback) {
  1055. Widget left = new Text(
  1056. str,
  1057. textScaleFactor: 1.0,
  1058. style: TextStyle(
  1059. fontSize: 14,
  1060. fontWeight: widget.isProgram ? FontWeight.w600 : FontWeight.normal),
  1061. );
  1062. Widget right = new Expanded(
  1063. child: new Align(
  1064. alignment: Alignment.centerRight,
  1065. child: new Switch(
  1066. activeTrackColor: Constants.ConfrimButtonColor.withOpacity(0.3),
  1067. value: value,
  1068. onChanged: (bool val) {
  1069. callback();
  1070. },
  1071. )));
  1072. return new Container(
  1073. padding: EdgeInsets.only(left: 15),
  1074. height: 53,
  1075. child: new Row(
  1076. children: <Widget>[left, right],
  1077. ),
  1078. );
  1079. }
  1080. Widget _buildSelct() {
  1081. return new Container(
  1082. decoration: _getCardDecoration(),
  1083. //margin: EdgeInsets.only(top: , bottom: 0),
  1084. child: Column(
  1085. children: <Widget>[
  1086. _buildSwitch(I18n.of(context).prohibit_comments, isCanContent, () {
  1087. setState(() {
  1088. isCanContent = !isCanContent;
  1089. });
  1090. }),
  1091. _buildDivider(),
  1092. _buildSwitch(I18n.of(context).same_sex, isHidden, () {
  1093. setState(() {
  1094. isHidden = !isHidden;
  1095. });
  1096. }),
  1097. ],
  1098. ));
  1099. }
  1100. Widget _buildTip() {
  1101. return Container(
  1102. alignment: Alignment.centerLeft,
  1103. margin: EdgeInsets.only(top: 10, bottom: 10, left: 10),
  1104. child: Text(
  1105. I18n.of(context).dont,
  1106. textScaleFactor: 1.0,
  1107. style: TextStyle(fontSize: 12, color: Constants.GreyTextColor),
  1108. ),
  1109. );
  1110. }
  1111. Widget _buildTips() {
  1112. String str = '';
  1113. if (UserData().isMan()) {
  1114. str = I18n.of(context)
  1115. .member_free
  1116. .replaceFirst('/s1', UserData().addProgramPrice.toString());
  1117. } else {
  1118. str = I18n.of(context)
  1119. .certified_free
  1120. .replaceFirst('/s1', UserData().addProgramPrice.toString());
  1121. }
  1122. return Container(
  1123. padding: EdgeInsets.only(bottom: 100, left: 20, right: 20),
  1124. child: Text(
  1125. str,
  1126. textScaleFactor: 1.0,
  1127. style: TextStyle(fontSize: 12, color: Constants.GreyTextColor),
  1128. ),
  1129. );
  1130. }
  1131. Widget _buildBody() {
  1132. List<Widget> program = [
  1133. _buildProgramCat(),
  1134. _buildProgramContent(),
  1135. _buildTip(),
  1136. _buildSelct(),
  1137. _buildLoginButton(),
  1138. _buildTips()
  1139. ];
  1140. List<Widget> dynamics = [
  1141. _buildDynicContent(),
  1142. _buildTip(),
  1143. _buildSelct(),
  1144. _buildLoginButton(),
  1145. _buildTips()
  1146. ];
  1147. return Column(
  1148. children: widget.isProgram ? program : dynamics,
  1149. );
  1150. }
  1151. //构建登陆按钮
  1152. Widget _buildLoginButton() {
  1153. Text text = new Text(I18n.of(context).release,
  1154. textScaleFactor: 1.0,
  1155. style: TextStyle(fontSize: 15, color: Colors.white));
  1156. LinearGradient gradientColor = new LinearGradient(colors: <Color>[
  1157. Constants.ConfrimButtonColor,
  1158. Constants.ConfrimButtonColor
  1159. ]);
  1160. callback() async {
  1161. closeEmojiAction();
  1162. if (widget.isProgram) {
  1163. if (programId == -1) {
  1164. showToast(I18n.of(context).please_choose);
  1165. return;
  1166. }
  1167. if (lovePeopleId.length == 0) {
  1168. showToast(I18n.of(context).please_choose2);
  1169. return;
  1170. }
  1171. // if (dateRangeId.length == 0) {
  1172. // showToast(I18n.of(context).please_choose3);
  1173. // return;
  1174. // }
  1175. if (beginTimeId == '') {
  1176. showToast(I18n.of(context).please_choose4);
  1177. return;
  1178. }
  1179. if (endTimeId == -1) {
  1180. showToast(I18n.of(context).please_choose5);
  1181. return;
  1182. }
  1183. } else {
  1184. if (_textCtrl.value.text.trim().length == 0 && imgUrlList.length == 0) {
  1185. showToast(I18n.of(context).enter_something);
  1186. return;
  1187. }
  1188. }
  1189. payCallback() {
  1190. if (Provider.of<MoneyChangeProvider>(context).money <
  1191. UserData().addProgramPrice) {
  1192. CustomUI.buildOneConfirm(
  1193. context,
  1194. I18n.of(context).balance_insufficien,
  1195. I18n.of(context).recharge, () {
  1196. Navigator.of(context).pop();
  1197. ChargeMoney.showChargeSheet(context, () {
  1198. setState(() {});
  1199. });
  1200. });
  1201. return;
  1202. }
  1203. Navigator.of(context).pop();
  1204. postAddProgram(UserData().addProgramPrice);
  1205. }
  1206. String title = widget.isProgram
  1207. ? I18n.of(context).release_program
  1208. : I18n.of(context).release_dynamics;
  1209. //非会员男士提示付费
  1210. if (!UserData().isVip && UserData().isMan()) {
  1211. bool isMan = UserData().isMan();
  1212. CustomUI.buildTowConfirm(
  1213. context,
  1214. title,
  1215. isMan
  1216. ? I18n.of(context).become_member2
  1217. : I18n.of(context).now_certification,
  1218. () {
  1219. Navigator.of(context).push(
  1220. new MaterialPageRoute(
  1221. builder: (context) {
  1222. return isMan ? VipPage() : VerificationCenterPage();
  1223. },
  1224. ),
  1225. );
  1226. },
  1227. I18n.of(context)
  1228. .raid_release
  1229. .replaceFirst('/s1', UserData().addProgramPrice.toString()),
  1230. payCallback,
  1231. );
  1232. return;
  1233. }
  1234. //免费次数用完提示付费
  1235. if (UserData().basicInfo.usedPublishNum >=
  1236. UserData().basicInfo.publishNum) {
  1237. CustomUI.buildOneConfirm(
  1238. context,
  1239. title,
  1240. I18n.of(context)
  1241. .pay_unlock
  1242. .replaceFirst('/s1', UserData().addProgramPrice.toString()),
  1243. payCallback);
  1244. return;
  1245. }
  1246. HttpUtil().userFreeTime(context, UserData().basicInfo.userId, 3, () {
  1247. UserData().basicInfo.usedPublishNum++;
  1248. postAddProgram(0);
  1249. });
  1250. }
  1251. return new Container(
  1252. margin: EdgeInsets.only(top: 30, bottom: 10),
  1253. height: 44,
  1254. width: MediaQuery.of(context).size.width * 0.8,
  1255. child: ShadowButton().builder(gradientColor, text, callback),
  1256. );
  1257. }
  1258. postAddProgram(price) async {
  1259. var dateRangeStr = '';
  1260. dateRangeId.forEach((f) => dateRangeStr += dateRangeStr == '' ? f : ',$f');
  1261. var hopeObject = '';
  1262. lovePeopleId.forEach((f) => hopeObject += hopeObject == '' ? f : ',$f');
  1263. String temp = '';
  1264. String postTemp = '';
  1265. imgUrlList.forEach((str) {
  1266. temp += (temp == "" ? str : '|$str');
  1267. postTemp += (postTemp == ""
  1268. ? WebData().deleteDemain(str)
  1269. : '|${WebData().deleteDemain(str)}');
  1270. });
  1271. var type = widget.isProgram ? 0 : 1;
  1272. Map data = {
  1273. "userId": UserData().basicInfo.userId,
  1274. "type": type,
  1275. "price": price,
  1276. };
  1277. data['sign'] = TokenMgr().getSign(data);
  1278. //data['city'] = dateRangeStr;
  1279. data['programType'] = programId;
  1280. data['hopeObject'] = hopeObject;
  1281. data['aboutTime'] = beginTimeId;
  1282. data['content'] = _textCtrl.text;
  1283. data['imgUrl'] = postTemp;
  1284. data['evaluateStatus'] = isCanContent;
  1285. data['sexStatus'] = isHidden;
  1286. data['timeQuantum'] = endTimeId;
  1287. Response res = await HttpUtil()
  1288. .post('station/publish/program', data: data, isShowLoading: true);
  1289. var resData = res.data;
  1290. if (resData['code'] == 0) {
  1291. if (widget.isProgram) {
  1292. UserData().isCanProgram = false;
  1293. }
  1294. MessageMgr().emit('Add_program', {
  1295. 'Id': resData['data'],
  1296. 'UserId': UserData().basicInfo.userId,
  1297. 'NickName': UserData().basicInfo.nickName,
  1298. 'HeadimgUrl': UserData().basicInfo.headimgurl,
  1299. 'Type': type,
  1300. 'Sex': UserData().basicInfo.sex,
  1301. 'IsMember': UserData().basicInfo.isMember,
  1302. 'ProgramType': programId,
  1303. 'HopeObject': hopeObject,
  1304. 'City': dateRangeStr,
  1305. 'AboutTime': beginTimeId,
  1306. 'timeQuantum': endTimeId,
  1307. 'Content': _textCtrl.text,
  1308. 'ImgUrl': temp,
  1309. 'EvaluateStatus': isCanContent ? 1 : 0,
  1310. 'SexStatus': isHidden,
  1311. 'Status': 0,
  1312. 'CreateTime': DateTime.now().toIso8601String(),
  1313. 'FabulousNum': 0,
  1314. 'EvaluateNum': 0,
  1315. 'EnrollNum': 0,
  1316. 'IsAttestation': UserData().basicInfo.isAttestation ? 1 : 0,
  1317. 'IsFabulous': 0,
  1318. 'IsEnroll': 0,
  1319. 'EvaluateList': null,
  1320. "FabulousList": []
  1321. });
  1322. Navigator.of(context).pop();
  1323. focusNode.removeListener(_focusNodeListener);
  1324. } else {
  1325. showToast(resData['msg']);
  1326. }
  1327. }
  1328. }