import 'dart:io'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:image_picker/image_picker.dart'; import 'package:sk_base_mobile/apis/api.dart'; import 'package:sk_base_mobile/app_theme.dart'; import 'package:sk_base_mobile/constants/bg_color.dart'; import 'package:sk_base_mobile/constants/enum.dart'; import 'package:sk_base_mobile/models/role.model.dart'; import 'package:sk_base_mobile/models/user_info.model.dart'; import 'package:sk_base_mobile/router/router.util.dart'; import 'package:sk_base_mobile/screens/hr_manage/components/dept_picker.dart'; import 'package:sk_base_mobile/util/loading_util.dart'; import 'package:sk_base_mobile/util/logger_util.dart'; import 'package:sk_base_mobile/util/media_util.dart'; import 'package:sk_base_mobile/util/screen_adaper_util.dart'; import 'package:sk_base_mobile/util/snack_bar.util.dart'; import 'package:sk_base_mobile/util/util.dart'; import 'package:sk_base_mobile/widgets/common/multi-picker/models/value_item.dart'; import 'package:sk_base_mobile/widgets/core/sk_cascade_picker.dart'; import 'package:sk_base_mobile/widgets/core/sk_dialog_header.dart'; import 'package:sk_base_mobile/widgets/form_item/sk_multi_picker.dart'; import 'package:sk_base_mobile/widgets/form_item/sk_text_input.dart'; import 'package:sk_base_mobile/widgets/gradient_button.dart'; import 'package:sk_base_mobile/widgets/loading_indicator.dart'; /// 编辑用户信息 class EditUserInfo extends StatelessWidget { final int userId; final EditUserInfoController controller; EditUserInfo({super.key, required this.userId}) : controller = Get.put(EditUserInfoController(userId)); @override Widget build(BuildContext context) { return Scaffold( // appBar: PreferredSize( // preferredSize: Size.fromHeight(40), // child: AppBar(elevation: 0, title: const Text('首页')), // ), backgroundColor: AppTheme.nearlyWhite, body: buildBody(), ); // return buildBody() } Widget buildBody() { return Column( children: [ const SkDialogHeader( title: '编辑员工信息', ), Expanded( child: GestureDetector( onTap: () { FocusScope.of(Get.context!).requestFocus(FocusNode()); }, child: Obx(() => controller.loading.value ? const LoadingIndicator( common: true, ) : SingleChildScrollView( child: Container( padding: EdgeInsets.symmetric( horizontal: ScreenAdaper.height(15), vertical: ScreenAdaper.height(15)), child: Column(children: [ buildAvatar(), SizedBox( height: ScreenAdaper.height(defaultPadding), ), /// 姓名 SkTextInput( isDense: true, isRequired: true, textController: controller.nicknameEditController, customLabel: true, labelText: '姓名', ), SizedBox( height: ScreenAdaper.height(defaultPadding), ), /// 部门 SkTextInput( isDense: true, customLabel: true, isRequired: true, keyboardType: TextInputType.none, textController: controller.deptEditController, labelText: '所属部门', onTap: (_) async { Get.bottomSheet( DeptPicker(onSelected: (CascadeItem item) { controller.deptEditController.text = item.label; controller.deptId = item.value; })); }, ), SizedBox( height: ScreenAdaper.height(defaultPadding), ), /// 角色 SkMultiPickerDropdown( isDense: true, customLabel: true, labelText: '角色', isRequired: true, hint: '选择角色', options: controller.roles, onOptionSelected: (List> selectedData) => { controller.roleSelection.assignAll(selectedData) }, selectedOptions: controller.roleSelection, ), SizedBox( height: ScreenAdaper.height(defaultPadding), ), SkTextInput( isDense: true, isRequired: true, textController: controller.usernameEditController, customLabel: true, labelText: '登录用户名', ), SizedBox( height: ScreenAdaper.height(defaultPadding), ), SkTextInput( isDense: true, customLabel: true, textController: controller.phoneEditController, labelText: '手机号', ), SizedBox( height: ScreenAdaper.height(defaultPadding), ), SkTextInput( isDense: true, customLabel: true, textController: controller.emailEditController, labelText: '邮箱', ), ]), ), )))), SizedBox( height: ScreenAdaper.height(10), ), GradientButton( borderRadius: BorderRadius.zero, onPressed: controller.submit, buttonText: '保存', ) ], ); } Widget buildAvatar() { return Column( children: [ SizedBox( height: ScreenAdaper.height(10), ), Obx(() => controller.filePath.isEmpty && controller.userInfo.value.avatar == null ? buildImageUploader() : builderImagePreview()), ], ); } Widget builderImagePreview() { return Stack( children: [ Container( margin: EdgeInsets.symmetric(horizontal: ScreenAdaper.width(5)), width: ScreenAdaper.width(180), height: ScreenAdaper.width(180), decoration: BoxDecoration( borderRadius: BorderRadius.circular(20), border: Border.all(width: 1.0, color: AppTheme.dividerColor), // color: AppTheme.primaryColor, ), child: Center( child: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(10), image: DecorationImage( fit: BoxFit.cover, image: controller.filePath.value.isNotEmpty ? FileImage(File(controller.filePath.value)) : NetworkImage(MediaUtil.getMediaUrl( controller.userInfo.value.avatar)) as ImageProvider), )), ), ), Positioned( top: ScreenAdaper.height(5), right: ScreenAdaper.width(5), child: GestureDetector( onTap: () { controller.filePath.value = ''; controller.userInfo.value.avatar = null; }, child: Icon( Icons.close, shadows: const [ Shadow( color: Colors.black, offset: Offset(1, 1), blurRadius: 3, ), Shadow( color: Colors.black, offset: Offset(-1, -1), blurRadius: 3, ), ], size: ScreenAdaper.height(40), color: AppTheme.nearlyWhite, ), )) ], ); } // 上传照片控制器 Widget buildImageUploader() { return GestureDetector( onTap: () { controller.photoPicker(); }, child: Container( margin: EdgeInsets.symmetric(horizontal: ScreenAdaper.width(5)), width: ScreenAdaper.width(180), height: ScreenAdaper.width(180), decoration: BoxDecoration( borderRadius: BorderRadius.circular(100), border: Border.all(width: 1.0, color: AppTheme.dividerColor), // color: AppTheme.primaryColor, ), child: Center( child: Icon( Icons.add_a_photo_rounded, size: ScreenAdaper.height(60), color: AppTheme.primaryColor, )))); } } class EditUserInfoController extends GetxController { final int userId; EditUserInfoController(this.userId); final deptEditController = TextEditingController(); final nicknameEditController = TextEditingController(); final usernameEditController = TextEditingController(); final phoneEditController = TextEditingController(); final emailEditController = TextEditingController(); final userInfo = Rx(UserInfoModel()); final RxList> roles = RxList([]); final RxBool loading = false.obs; final List> roleSelection = []; int? deptId; final filePath = ''.obs; @override onReady() { init(); super.onReady(); } init() async { loading.value = true; await Future.wait([getUserInfo(), getRoles()]); loading.value = false; } Future submit() async { Map data = { 'nickname': nicknameEditController.text, 'deptId': deptId, 'username': usernameEditController.text, 'phone': phoneEditController.text, 'roleIds': roleSelection.map((e) => e.value).toList() }; if (nicknameEditController.text.isEmpty) { SnackBarUtil().error( '姓名不能为空', ); return; } if (deptId == null) { SnackBarUtil().error( '部门不能为空', ); return; } if (usernameEditController.text.isEmpty) { SnackBarUtil().error( '登录名不能为空', ); return; } if (roleSelection.map((e) => e.value).toList().isEmpty) { SnackBarUtil().error( '角色至少选择一个基础员工角色', ); return; } await LoadingUtil.to.show(status: '保存中请稍后...'); try { if (filePath.value.isNotEmpty) { // 批量同时上传 final res = await MediaUtil().uploadImg(File(filePath.value)); if (res != null) { data['avatar'] = res.path; } } await Api.updateUserInfo(userInfo.value.id!, data); await LoadingUtil.to.dismiss(); final resUser = await Api.getUserInfo(userInfo.value.id!); if (resUser.data != null) { userInfo.value = UserInfoModel.fromJson(resUser.data); } await RouterUtil.back(result: userInfo.value); SnackBarUtil().success( '保存成功', ); } catch (e) { LoggerUtil().error(e); } finally { LoadingUtil.to.dismiss(); } } Future getRoles() async { try { await Future.delayed(const Duration(milliseconds: 500)); final res = await Api.getRoles({'page': 1, 'pageSize': 30, 'useForSelect': 1}); if (res.data != null) { List> result = res.data!.items.map>((e) { RoleModel data = RoleModel.fromJson(e); return ValueItem( label: data.name, value: data.id!, subLabel: data.remark); }).toList(); final rootRole = userInfo.value.roles .firstWhereOrNull((element) => element.id == ROOT_ROLE_ID); if (rootRole != null) { result.add(ValueItem( label: rootRole.name, value: rootRole.id, subLabel: rootRole.remark)); } roles.assignAll(result); } } catch (e) { LoggerUtil().error(e); } } Future getUserInfo() async { try { final response = await Api.getUserInfo(userId); if (response.data != null) { userInfo.value = UserInfoModel.fromJson(response.data); nicknameEditController.text = userInfo.value.nickname ?? ''; usernameEditController.text = userInfo.value.username ?? ''; deptEditController.text = userInfo.value.dept?.name ?? ''; phoneEditController.text = userInfo.value.phone ?? ''; emailEditController.text = userInfo.value.email ?? ''; deptId = userInfo.value.dept?.id; roleSelection.assignAll(userInfo.value!.roles .map>((data) => ValueItem( label: data.name, value: data.id!, )) .toList()); } } catch (e) { SnackBarUtil().error('$e'); } finally {} } Future photoPicker() async { await MediaUtil().showPicker(callback: (path) async { if (path != null) { filePath.value = path; // 拿到照片大小多少MB final file = File(path); final size = await file.length(); final sizeInMb = size / (1024 * 1024); print(sizeInMb); // if (sizeInMb > 2) { // SnackBarUtil().error('图片大小不能超过2MB'); // filePath.value = ''; // } } }); } }