import 'dart:typed_data'; import 'package:dio/dio.dart'; import 'package:file_picker/file_picker.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; import 'package:get/get.dart'; import 'package:dio/dio.dart' as adio; // import 'package:image_cropper/image_cropper.dart'; import 'package:link/view/edit_avatar.dart'; import '../constants.dart'; import '../utils/api.dart'; import '../utils/http_utils.dart'; import '../utils/size_fit.dart'; import '../utils/util.dart'; import 'component/link_btn.dart'; import 'component/toast.dart'; import 'component/top_container.dart'; import 'component/upload_file.dart'; class EditInfo extends StatefulWidget { const EditInfo({Key? key}) : super(key: key); @override State createState() => _EditInfoState(); } class _EditInfoState extends State { TextEditingController controller = TextEditingController(); TextEditingController introController = TextEditingController(); FocusNode focusNode = FocusNode(); bool isFocus = false; String nickname = ''; String avatar = ''; String location = ''; Uint8List? chooseImage; bool isBoy = true; String intro = ''; Map? userData; @override void initState() { // TODO: implement initState getUserInfo(); Util().setPageTitle('基本信息'); focusNode.addListener(() { setState(() { isFocus = focusNode.hasFocus; }); }); super.initState(); } Future getUserInfo() async { var data = await HttpUtils.get(Api.userInfo); setState(() { userData = data; avatar = data['avatar']; nickname = data['nickname']; intro = data['signature']; isBoy = data['sex'] == 'MALE'; location = data['country'] + ' ' + data['city']; controller.text = nickname; introController.text = intro; }); } @override void dispose() { // TODO: implement dispose focusNode.dispose(); super.dispose(); } Future commit() async { if (chooseImage == null && avatar.isEmpty) { Toast().showInfoText('请上传头像', context: context); return; } if (nickname.isEmpty) { Toast().showInfoText('请输入昵称', context: context); return; } Toast().showHud(context: context); var data2 = await HttpUtils.post(Api.userInfo, data: { 'nickname': nickname, 'sex': isBoy ? 'MALE' : 'FEMALE', 'signature': intro, 'area': '北京', 'city': '北京', 'province': '北京', 'country': '中国' }); if (data2 != null) { print(data2.toString()); } Toast().hideHud(); Get.back(); // Get.toNamed('/edit_base_info'); } Future chooseFile() async { FilePickerResult? result = await FilePicker.platform.pickFiles(type: FileType.image); if (result != null) { // setState(() { // chooseImage = result.files.single.bytes; // }); Uint8List? temp = result.files.single.bytes; showDialog( context: context, barrierDismissible: false, barrierColor: Colors.transparent, useSafeArea: false, builder: (BuildContext context) { return EditAvatar( image: temp!, callback: (Uint8List img) { setState(() { chooseImage = img; }); uploadImage(img); }, ); }); // uploadImage(result.files.single.bytes); // print(result.files.single.path); } } Future uploadImage(Uint8List? imgData) async { // Toast().showHud(context: context); Map data = await HttpUtils.get(Api.ossFormUpload, params: {'type': 'AVATAR', 'file_ext': 'png'}); Dio dio = Dio(); Map map = data['fields']; map['file'] = await adio.MultipartFile.fromBytes(imgData!, filename: 'avatar.png'); adio.FormData formData = adio.FormData.fromMap(map); adio.Response response = await dio.post(data['upload_url'], data: formData); var data2 = await HttpUtils.post(Api.userInfo, data: {'avatar': data['view_url']}); if (data2 != null) { print(data['view_url']); // getUserInfo(); } // Toast().hideHud(); } @override Widget build(BuildContext context) { SizeFit.initialize(context); TextStyle style = TextStyle( color: kThemeColor, fontSize: 16.px, fontWeight: FontWeight.bold); if (userData == null) { return const Material(color: kBgColor); } return Material( color: kBgColor, child: TopContainer( child: Stack(children: [ Positioned( left: 0, top: 0, right: 0, bottom: 0, child: Padding( padding: EdgeInsets.only( bottom: MediaQuery.of(context).viewInsets.bottom), child: SingleChildScrollView( child: Column(children: [ SizedBox( height: 32.px, ), UploadFile( child: ClipRRect( borderRadius: BorderRadius.circular(70.px), child: Container( width: 140.px, height: 140.px, alignment: Alignment.bottomCenter, decoration: BoxDecoration( image: chooseImage != null ? DecorationImage( image: MemoryImage(chooseImage!), fit: BoxFit.cover) : avatar.isNotEmpty ? DecorationImage( image: NetworkImage(avatar), fit: BoxFit.cover) : const DecorationImage( image: AssetImage( 'assets/images/default_avatar.png'))), child: Container( height: 28.px, color: kThemeColor, alignment: Alignment.center, child: SvgPicture.asset( 'assets/icons/edit.svg', width: 24.px, height: 24.px, color: Colors.black, ), ), )), callback: (Uint8List file) { showDialog( context: context, barrierDismissible: false, barrierColor: Colors.transparent, useSafeArea: false, builder: (BuildContext context) { return EditAvatar( image: file, callback: (Uint8List img) { setState(() { chooseImage = img; }); uploadImage(img); }, ); }); // setState(() { // chooseImage = file; // }); // showDialog( // context: context, // barrierDismissible: false, // barrierColor: Colors.transparent, // useSafeArea: false, // builder: (BuildContext context) { // return EditAvatar( // image: chooseImage!, // ); // }); // uploadImage(file); }, ), SizedBox( height: 24.px, ), Container( width: 315.px, height: 68.px, alignment: Alignment.centerLeft, padding: EdgeInsets.only(left: 16.px, right: 16.px), decoration: BoxDecoration( borderRadius: BorderRadius.circular(16.px), color: const Color(0xFF2C2C2E)), child: TextField( // autofocus: true, controller: controller, focusNode: focusNode, maxLength: 50, cursorColor: kBtnColor, onChanged: (value) { setState(() { nickname = value; }); }, textAlign: TextAlign.center, style: TextStyle( color: Colors.white, fontSize: 28.px), decoration: InputDecoration( border: InputBorder.none, hintText: isFocus ? '' : '请输入您的昵称', hintStyle: TextStyle( fontSize: 20.px, color: const Color(0xFF74747A)), counterText: "", ), )), SizedBox( height: 40.px, ), Container( width: 343.px, padding: EdgeInsets.fromLTRB(20.px, 18.px, 20.px, 18.px), decoration: BoxDecoration( color: const Color(0xFF2C2C2E), borderRadius: BorderRadius.circular(24.px)), child: Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Text( '性别', style: style, ), Expanded(child: Container()), GestureDetector( onTap: () { setState(() { isBoy = true; }); }, child: Container( alignment: Alignment.center, width: 40.px, height: 40.px, decoration: BoxDecoration( borderRadius: BorderRadius.circular(20.px), color: isBoy ? const Color(0xFF00FFFF) : const Color(0xFF444447)), child: SvgPicture.asset( 'assets/icons/gender_male.svg', width: 24.px, height: 24.px, ), ), ), SizedBox( width: 16.px, ), GestureDetector( onTap: () { setState(() { isBoy = false; }); }, child: Container( alignment: Alignment.center, width: 40.px, height: 40.px, decoration: BoxDecoration( borderRadius: BorderRadius.circular(20.px), color: !isBoy ? const Color(0xFFFF00AA) : const Color(0xFF444447)), child: SvgPicture.asset( 'assets/icons/gender_female.svg', width: 24.px, height: 24.px, ), ), ) ], ), Container( margin: EdgeInsets.only(top: 18.px, bottom: 18.px), height: 1.px, color: const Color(0xFF404040), ), GestureDetector( child: Row( children: [ Text('地区', style: style), Expanded(child: Container()), Text( '中国 北京', style: TextStyle( color: Colors.white, fontSize: 14.px), ), Image.asset( 'assets/images/arrow_right.png', width: 20.px, height: 20.px, ) // SvgPicture.asset( // 'assets/icons/arrow_right.svg', // color: const Color(0xFF444447), // width: 20.px, // height: 20.px, // ) ], ), ), Container( margin: EdgeInsets.only(top: 18.px, bottom: 18.px), height: 1.px, color: const Color(0xFF404040), ), Text('简介', style: style), TextField( maxLength: 1000, maxLines: 1000, minLines: 1, controller: introController, cursorColor: kBtnColor, style: TextStyle( color: Colors.white, fontSize: 14.px, ), onChanged: (e) { setState(() { intro = e; }); }, decoration: InputDecoration( border: InputBorder.none, hintText: '请填写您的简介(选填)', hintStyle: TextStyle( fontSize: 14.px, color: const Color(0xFF74747A)), counterText: "", )), ])), SizedBox( height: 30.px, ), LinkButton( title: '提交', disable: false, isBlack: false, callback: () { commit(); }) ])))) ]))); } }