video_upload.dart 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680
  1. import 'package:flutter/material.dart';
  2. import 'package:liftmanager/res/gaps.dart';
  3. import 'package:liftmanager/net/api_service.dart';
  4. import 'package:liftmanager/utils/toast.dart';
  5. import 'package:liftmanager/widgets/app_bar.dart';
  6. import 'package:liftmanager/internal/search/search_router.dart';
  7. import 'package:liftmanager/widgets/app_search_bar.dart';
  8. import 'package:liftmanager/res/resources.dart';
  9. import 'package:liftmanager/routers/fluro_navigator.dart';
  10. import 'package:liftmanager/widgets/load_image.dart';
  11. import 'package:liftmanager/widgets/selected_image_change.dart';
  12. import 'package:image_picker/image_picker.dart';
  13. import 'dart:io';
  14. import 'package:liftmanager/widgets/bbs_content.dart';
  15. import 'package:flutter_screenutil/flutter_screenutil.dart';
  16. import 'package:flutter_spinkit/flutter_spinkit.dart';
  17. import 'package:video_player/video_player.dart';
  18. import 'package:liftmanager/utils/image_utils.dart';
  19. import 'package:liftmanager/internal/bbs/bbs_router.dart';
  20. import 'package:liftmanager/internal/wode/wode_router.dart';
  21. import 'package:liftmanager/internal/bbs/model/video_detail.dart';
  22. import 'package:liftmanager/utils/log_util.dart';
  23. import 'dart:convert';
  24. import 'package:flustars/flustars.dart' as FlutterStars;
  25. import 'package:liftmanager/common/common.dart';
  26. import 'dart:math';
  27. import 'package:liftmanager/utils/fast_notification.dart';
  28. import 'package:liftmanager/utils/theme_utils.dart';
  29. class VideoUpload extends StatefulWidget {
  30. VideoUpload(this.id);
  31. final String id;
  32. @override
  33. State<StatefulWidget> createState() {
  34. return VideoUploadState();
  35. }
  36. }
  37. class VideoUploadState extends State<VideoUpload> {
  38. // NewsDetailItem item = NewsDetailItem();
  39. ScrollController _scrollController = new ScrollController();
  40. String brandChiose='请选择';
  41. String brandName = "品牌";
  42. int brandIdss;
  43. bool sortBool = true;
  44. List<String> imagesUrl = [];
  45. List<String> videoUrl = [];
  46. VideoDetailModel detailObj;
  47. // 焦点控制
  48. FocusNode _focusNode1 = new FocusNode();
  49. GlobalKey _formKey= new GlobalKey<FormState>();
  50. TextEditingController _titleController = new TextEditingController();
  51. TextEditingController _descController = new TextEditingController();
  52. @override
  53. void initState() {
  54. super.initState();
  55. print(widget.id);
  56. if(widget.id!=null&&widget.id!=""){
  57. NewApiService().getVideoDetail(int.parse(widget.id), 1,
  58. onSuccess: (res) {
  59. if (res != null) {
  60. detailObj = res;
  61. LogUtil.d(jsonEncode(res));
  62. print(88885);
  63. setState(() {
  64. videoUrl = [];
  65. imagesUrl = [];
  66. videoUrl.add(res.url);
  67. imagesUrl.add(res.cover);
  68. _titleController.text = res.title;
  69. _descController.text = res.descr;
  70. brandIdss = res.brandId;
  71. brandChiose = res.brandName;
  72. });
  73. }
  74. }, onError: (code, msg) {
  75. toasts(msg);
  76. });
  77. }
  78. }
  79. upLoadFileOnce(path) {
  80. showLoading(context, "正在上传...");
  81. NewApiService().upload(path, onSuccess: (res) {
  82. // imagesUrl.add(res.path);
  83. dismissLoading(context);
  84. setState(() {
  85. videoUrl = [];
  86. imagesUrl = [];
  87. videoUrl.add(res.pathUrl);
  88. imagesUrl.add(res.coverUrl);
  89. });
  90. }, onError: (code, msg) {
  91. dismissLoading(context);
  92. toasts(msg);
  93. });
  94. }
  95. randomInt(int min, int max) {
  96. return new Random().nextInt(max) % (max - min + 1) + min;
  97. }
  98. List<dynamic> brandList;
  99. Future getBrandList() async {
  100. await NewApiService().getBrandListNoPage(
  101. onSuccess: (res) {
  102. if (res != null) {
  103. brandList = res;
  104. setState(() {});
  105. }
  106. }, onError: (code, msg) {
  107. toasts(msg);
  108. });
  109. }
  110. ///选择视频
  111. void selectPicker() {
  112. showDialog(
  113. context: context,
  114. builder: (BuildContext context) {
  115. return SimpleDialog(
  116. title: Text("选择方式"),
  117. children: ["拍照", '从手机相册选择'].map((String value) {
  118. print("$value");
  119. return SimpleDialogOption(
  120. child: Text(
  121. "${value}",
  122. style: TextStyle(fontSize: 16, fontWeight: FontWeight.w500),
  123. ),
  124. onPressed: () {
  125. _getImage(value == '拍照' ? 1 : 0);
  126. Navigator.of(context).pop();
  127. },
  128. );
  129. }).toList());
  130. });
  131. }
  132. void _getImage(int key) async {
  133. print(key);
  134. print(333);
  135. try {
  136. var _imageFile = await ImagePicker.pickVideo(
  137. source: key == 1 ? ImageSource.camera : ImageSource.gallery,
  138. );
  139. if (_imageFile != null) {
  140. // print(123);
  141. // print(_imageFile);
  142. // print(jsonEncode(_imageFile));
  143. LogUtil.d(_imageFile);
  144. LogUtil.d(_imageFile.hashCode);
  145. LogUtil.d(_imageFile.path);
  146. print(123);
  147. upLoadFileOnce(_imageFile.path);
  148. setState(() {});
  149. }
  150. } catch (e) {
  151. toasts("没有权限,无法打开相册!");
  152. }
  153. }
  154. FocusNode focusNode1 = new FocusNode();
  155. @override
  156. Widget build(BuildContext context) {
  157. double width = MediaQuery.of(context).size.width;
  158. double height = MediaQuery.of(context).size.height;
  159. // 监听FocusNode
  160. _focusNode1.addListener((){
  161. // _focusNode1.hasFocus 是否聚焦
  162. print(_focusNode1.hasFocus);
  163. });
  164. return Scaffold(
  165. resizeToAvoidBottomPadding: false,//不让键盘弹上去
  166. appBar: MyAppBar(
  167. centerTitle: "上传视频",
  168. ),
  169. body:GestureDetector(
  170. onTap: () {
  171. // 点击空白页面关闭键盘
  172. FocusScope.of(context).requestFocus(focusNode1);
  173. },
  174. child: Stack(
  175. children: <Widget>[
  176. Container(
  177. child: ListView(
  178. children: <Widget>[
  179. Form(
  180. key: _formKey, //设置globalKey,用于后面获取FormState
  181. // autovalidate: true, //开启自动校验
  182. child: Column(
  183. children: <Widget>[
  184. ChioseThisRight(label: "电梯品牌",value:brandChiose,fun:(){
  185. setState(() {
  186. // brandChiose = brandListChiose[index];
  187. sortBool = false;
  188. print(5656333);
  189. });
  190. getBrandList();
  191. // Navigator.maybePop(context);
  192. }),
  193. Row(
  194. crossAxisAlignment: CrossAxisAlignment.start,
  195. mainAxisAlignment: MainAxisAlignment.start,
  196. children: <Widget>[
  197. Container(
  198. padding:EdgeInsets.only(left:ScreenUtil().setWidth(15),top:ScreenUtil().setWidth(10),bottom:ScreenUtil().setWidth(5)),
  199. child: Text(
  200. "视频标题",
  201. style: TextStyle(
  202. color:Color(0xff222222),
  203. // fontSize:ScreenUtil().setSp(14),
  204. ),
  205. textAlign:TextAlign.left,
  206. ),
  207. ),
  208. ],
  209. ),
  210. Container(
  211. height:80,
  212. padding: EdgeInsets.only(left:ScreenUtil().setWidth(15),right:ScreenUtil().setWidth(15),bottom:ScreenUtil().setWidth(20)),
  213. child: TextFormField(
  214. // autofocus: true,
  215. maxLength: 50,
  216. cursorColor: Color(0xffcccccc),
  217. controller: _titleController,
  218. maxLines:5,
  219. decoration: InputDecoration(
  220. contentPadding: EdgeInsets.all(0),
  221. hintText: '请输入你上传视频的标题',
  222. hintStyle:TextStyle(
  223. color: Color(0xffcccccc)
  224. ),
  225. focusedBorder: InputBorder.none,
  226. border: InputBorder.none,
  227. // filled: true, // 背景色
  228. // fillColor: Colors.cyan.withAlpha(35),
  229. // icon: Icon(Icons.person)
  230. ),
  231. // 校验
  232. validator: (val) {
  233. return val.trim().length > 0 ? null : "不能为空";
  234. }
  235. ),
  236. ),
  237. SizedBox(
  238. height:6,
  239. child: Container(
  240. color:ThemeUtils.getDialogTextFieldColor(context)
  241. ),
  242. ),
  243. Row(
  244. crossAxisAlignment: CrossAxisAlignment.start,
  245. mainAxisAlignment: MainAxisAlignment.start,
  246. children: <Widget>[
  247. Container(
  248. padding:EdgeInsets.only(left:ScreenUtil().setWidth(15),top:ScreenUtil().setWidth(10),bottom:ScreenUtil().setWidth(5)),
  249. child: Text(
  250. "视频简介",
  251. style: TextStyle(
  252. color:Color(0xff222222),
  253. // fontSize:ScreenUtil().setSp(14),
  254. ),
  255. textAlign:TextAlign.left,
  256. ),
  257. ),
  258. ],
  259. ),
  260. Container(
  261. height:120,
  262. padding: EdgeInsets.only(left:ScreenUtil().setWidth(15),right:ScreenUtil().setWidth(15),bottom:ScreenUtil().setWidth(20)),
  263. child: TextFormField(
  264. // autofocus: true,
  265. maxLength: 500,
  266. cursorColor: Color(0xffcccccc),
  267. controller: _descController,
  268. maxLines:5,
  269. decoration: InputDecoration(
  270. contentPadding: EdgeInsets.all(0),
  271. hintText: '请输入您上传视频的简介',
  272. hintStyle:TextStyle(
  273. color: Color(0xffcccccc)
  274. ),
  275. focusedBorder: InputBorder.none,
  276. border: InputBorder.none,
  277. // filled: true, // 背景色
  278. // fillColor: Colors.cyan.withAlpha(35),
  279. // icon: Icon(Icons.person)
  280. ),
  281. // 校验
  282. validator: (val) {
  283. return val.trim().length > 0 ? null : "不能为空";
  284. }
  285. ),
  286. ),
  287. SizedBox(
  288. height:6,
  289. child: Container(
  290. color:ThemeUtils.getDialogTextFieldColor(context)
  291. ),
  292. ),
  293. Container(
  294. width: width,
  295. padding: EdgeInsets.only(left:15,top:15),
  296. child: Text(
  297. "(建议时长3分钟,建议大小50M)",
  298. style: TextStyle(
  299. color: Colors.red,
  300. fontSize:
  301. ScreenUtil()
  302. .setSp(14),
  303. ),
  304. textAlign: TextAlign.left,
  305. ),
  306. ),
  307. Container(
  308. color: ThemeUtils.getTabsBg(context),
  309. child: GridView.builder(
  310. shrinkWrap: true,
  311. padding: const EdgeInsets.fromLTRB(8.0, 12, 8.0, 12.0),
  312. physics: NeverScrollableScrollPhysics(),
  313. gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
  314. crossAxisCount: 3, childAspectRatio: 1.18),
  315. itemCount: videoUrl.length >= 1 ? 1 : videoUrl.length + 1,
  316. itemBuilder: (_, index) {
  317. return Stack(
  318. children: <Widget>[
  319. Center(
  320. child: SelectedImage(
  321. image: index < videoUrl.length ? imagesUrl[index] : null,
  322. // image: index < videoUrl.length ? videoUrl[index] : null,
  323. index:index,
  324. onTap: () {
  325. if(index >= videoUrl.length){
  326. selectPicker();
  327. }
  328. FocusScope.of(context).requestFocus(FocusNode());
  329. print(index);
  330. print(videoUrl);
  331. }),
  332. ),
  333. index < videoUrl.length?Positioned(
  334. top:0,
  335. right:0,
  336. child:GestureDetector(
  337. onTap: (){
  338. print(index);
  339. videoUrl.remove(videoUrl[index]);
  340. imagesUrl.remove(imagesUrl[index]);
  341. setState(() {
  342. });
  343. },
  344. child:Icon(
  345. IconData(
  346. 0xe62a,
  347. fontFamily:"myfont"
  348. ),
  349. size: 24.0,
  350. color:Color(0xff999999),
  351. ),
  352. )
  353. ):Container(child: null,)
  354. ],
  355. );
  356. },
  357. )
  358. ),
  359. SizedBox(
  360. height:ScreenUtil().setWidth(80),
  361. ),
  362. ],
  363. ),
  364. )
  365. ]
  366. )
  367. ),
  368. Positioned(
  369. bottom:0,
  370. left:0,
  371. child:Container(
  372. width: width,
  373. padding: EdgeInsets.only(top:ScreenUtil().setWidth(15),bottom:ScreenUtil().setWidth(15),left:ScreenUtil().setWidth(25),right:ScreenUtil().setWidth(25)),
  374. color:ThemeUtils.getDialogTextFieldColor(context),
  375. child: Container(
  376. height:ScreenUtil().setWidth(44),
  377. decoration: BoxDecoration(
  378. borderRadius: BorderRadius.circular(ScreenUtil().setWidth(22)),
  379. gradient: const LinearGradient(
  380. colors: [Color(0xFF00D9FF), Color(0xFF0287FF)]),
  381. ),
  382. child: FlatButton(
  383. // padding: EdgeInsets.all(15.0),
  384. child: Text("提交"),
  385. textColor: Colors.white,
  386. onPressed: () {
  387. if(brandIdss==null){
  388. toasts("请选择品牌");
  389. return;
  390. }
  391. if(videoUrl.length<1){
  392. toasts("请上传视频");
  393. return;
  394. }
  395. String videos = videoUrl.join(",");
  396. String images = imagesUrl.join(",");
  397. if((_formKey.currentState as FormState).validate()){
  398. showLoading(context, "正在提交...");
  399. if(widget.id!=null&&widget.id!=""){
  400. dynamic objEdit = {
  401. "brandId":brandIdss,
  402. "title":_titleController.text,
  403. "descr":_descController.text,
  404. "url":videos,
  405. "cover": images,
  406. "checkFlag":2,
  407. "statuz":1,
  408. "platformFlag":1,
  409. "userId":FlutterStars.SpUtil.getString(Constant.userId),
  410. "id":detailObj.id
  411. };
  412. NewApiService().editVideo(objEdit, onSuccess: (res) {
  413. dismissLoading(context);
  414. toasts("修改成功");
  415. String initThisMyVideo = randomInt(1111,9999).toString() + DateTime.now().millisecondsSinceEpoch.toString();
  416. FastNotification.push("initMyVideo",initThisMyVideo);
  417. Navigator.pop(context);
  418. }, onError: (code, msg) {
  419. dismissLoading(context);
  420. toasts(msg);
  421. });
  422. }else {
  423. dynamic obj = {
  424. "brandId":brandIdss,
  425. "title":_titleController.text,
  426. "descr":_descController.text,
  427. "url":videos,
  428. "cover": images,
  429. "checkFlag":2,
  430. "statuz":1,
  431. "platformFlag":1,
  432. "userId":FlutterStars.SpUtil.getString(Constant.userId)
  433. };
  434. NewApiService().addVideo(obj, onSuccess: (res) {
  435. dismissLoading(context);
  436. toasts("提交成功");
  437. String initThisMyVideo = randomInt(1111,9999).toString() + DateTime.now().millisecondsSinceEpoch.toString();
  438. FastNotification.push("initMyVideo",initThisMyVideo);
  439. Navigator.pop(context);
  440. }, onError: (code, msg) {
  441. dismissLoading(context);
  442. toasts(msg);
  443. });
  444. }
  445. }
  446. },
  447. ),
  448. ),
  449. )
  450. ),
  451. !sortBool?
  452. Positioned(
  453. top:0,
  454. left:0,
  455. child: Container(
  456. width:width,
  457. height:height,
  458. color: Color.fromRGBO(0, 0, 0, 0.5)
  459. )
  460. )
  461. :Container(
  462. child:null
  463. ),
  464. !sortBool?
  465. Positioned(
  466. top:0,
  467. right:0,
  468. child:Container(
  469. width: width/4*3,
  470. height:height,
  471. color: ThemeUtils.getTabsBg(context),
  472. padding: EdgeInsets.all(10),
  473. child:ListView(
  474. children:<Widget>[
  475. Container(
  476. padding: EdgeInsets.only(left:5,top:5,bottom:10),
  477. child:Text(
  478. "品牌",
  479. style: TextStyle(
  480. color:Color(0xff666666),
  481. fontSize:ScreenUtil().setSp(16)
  482. ),
  483. textAlign:TextAlign.start,
  484. ),
  485. ),
  486. brandList!=null&&brandList!=[]?Container(
  487. child: Wrap(
  488. alignment: WrapAlignment.start,
  489. crossAxisAlignment: WrapCrossAlignment.center,
  490. children: brandList.asMap().keys.map((index){
  491. return InkWell(
  492. onTap: (){
  493. print("666");
  494. setState(() {
  495. sortBool = true;
  496. brandChiose = brandList[index].name??"";
  497. brandIdss = brandList[index].id;
  498. });
  499. },
  500. child: Container(
  501. width: width/4-17,
  502. padding: EdgeInsets.only(bottom:ScreenUtil().setWidth(10),top:ScreenUtil().setWidth(10)),
  503. margin: EdgeInsets.only(left:5,right:5,bottom:5,top:5),
  504. decoration: BoxDecoration(
  505. // border: Border(
  506. // bottom: BorderSide(width: 0.5, color: Colours.line),
  507. // ),
  508. color: Color(0xfff5f5f5)
  509. ),
  510. child:Text(
  511. brandList[index].name??"",
  512. style: TextStyle(
  513. color:Color(0xff666666),
  514. fontSize:ScreenUtil().setSp(15)
  515. ),
  516. textAlign:TextAlign.center,
  517. maxLines: 1,
  518. overflow: TextOverflow.ellipsis,
  519. ),
  520. ),
  521. );
  522. }).toList(),
  523. )
  524. ):loadCircle()
  525. ],
  526. )
  527. )
  528. ):
  529. Container(
  530. child:null
  531. ),
  532. ],
  533. ),
  534. ),
  535. );
  536. }
  537. Widget loadCircle() {
  538. return Container(
  539. padding: EdgeInsets.only(top: 10, bottom: 10),
  540. color: ThemeUtils.getTabsBg(context),
  541. child: Center(
  542. child: SpinKitFadingCircle(
  543. color: Colors.blueAccent,
  544. size: 30.0,
  545. ),
  546. ),
  547. );
  548. }
  549. }
  550. class ChioseThisRight extends StatelessWidget {
  551. ChioseThisRight({Key key,this.value,this.label,this.fun,this.labelText='请选择'}) : super(key: key);
  552. String value;
  553. String label;
  554. Function fun;
  555. String labelText;
  556. @override
  557. Widget build(BuildContext context) {
  558. double width = MediaQuery.of(context).size.width;
  559. return InkWell(
  560. onTap: (){
  561. fun();
  562. },
  563. child: Container(
  564. padding: EdgeInsets.only(top:ScreenUtil().setWidth(15),bottom:ScreenUtil().setWidth(15)),
  565. margin: EdgeInsets.only(left:ScreenUtil().setWidth(15)),
  566. decoration: BoxDecoration(
  567. border: Border(
  568. bottom: BorderSide(width: 0.5, color: Colours.line),
  569. ),
  570. ),
  571. child: Row(
  572. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  573. children:<Widget>[
  574. Text(
  575. label,
  576. style: TextStyle(
  577. color:Color(0xff222222),
  578. // fontSize: ScreenUtil().setSp(14)
  579. ),
  580. textAlign:TextAlign.start,
  581. ),
  582. value.isEmpty? Container(
  583. child: Row(
  584. children:<Widget>[
  585. Text(
  586. labelText,
  587. style: TextStyle(
  588. color:Color(0xffcccccc),
  589. // fontSize: ScreenUtil().setSp(14)
  590. ),
  591. textAlign:TextAlign.start,
  592. ),
  593. Container(
  594. padding: EdgeInsets.only(top:3),
  595. child: Icon(
  596. Icons.keyboard_arrow_right,
  597. size: 20.0,
  598. color:Color(0xffcccccc),
  599. ),
  600. ),
  601. SizedBox(
  602. width:10
  603. )
  604. ]
  605. ),
  606. ):
  607. Container(
  608. padding: EdgeInsets.only(right:ScreenUtil().setWidth(15)),
  609. child: Row(
  610. children:<Widget>[
  611. Text(
  612. value,
  613. style: TextStyle(
  614. color:Color(0xff222222),
  615. fontSize: ScreenUtil().setSp(14)
  616. ),
  617. textAlign:TextAlign.start,
  618. ),
  619. ]
  620. ),
  621. ),
  622. ]
  623. ),
  624. ),
  625. );
  626. }
  627. }