mobile_skt/lib/screens/hr_manage/components/edit_userinfo.dart

401 lines
14 KiB
Dart

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/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<int>(
isDense: true,
customLabel: true,
labelText: '角色',
isRequired: true,
hint: '选择角色',
options: controller.roles,
onOptionSelected:
(List<ValueItem<int>> 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<Object>),
)),
),
),
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>(UserInfoModel());
final RxList<ValueItem<int>> roles = RxList([]);
final RxBool loading = false.obs;
final List<ValueItem<int>> 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<void> 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<UserInfoModel>(result: userInfo.value);
SnackBarUtil().success(
'保存成功',
);
} catch (e) {
LoggerUtil().error(e);
} finally {
LoadingUtil.to.dismiss();
}
}
Future<void> 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<ValueItem<int>> result = res.data!.items.map<ValueItem<int>>((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<void> 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<ValueItem<int>>((data) => ValueItem(
label: data.name,
value: data.id!,
))
.toList());
}
} catch (e) {
SnackBarUtil().error('$e');
} finally {}
}
Future<void> photoPicker() async {
XFile? pickedFile = await MediaUtil().getImageFromGallery();
if (pickedFile != null) {
filePath.value = pickedFile.path;
}
}
}