mobile_skt/lib/screens/hr_manage/hr_manage.dart

355 lines
12 KiB
Dart

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:pull_to_refresh/pull_to_refresh.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/constants.dart';
import 'package:sk_base_mobile/models/user_info.model.dart';
import 'package:sk_base_mobile/screens/hr_manage/components/edit_userinfo.dart';
import 'package:sk_base_mobile/util/date.util.dart';
import 'package:sk_base_mobile/util/debouncer.dart';
import 'package:sk_base_mobile/util/device.util.dart';
import 'package:sk_base_mobile/util/media_util.dart';
import 'package:sk_base_mobile/util/modal.util.dart';
import 'package:sk_base_mobile/router/router.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/core/sk_avatar.dart';
import 'package:sk_base_mobile/widgets/core/sk_ink.dart';
import 'package:sk_base_mobile/widgets/core/sk_tag.dart';
import 'package:sk_base_mobile/widgets/form_item/sk_text_input.dart';
import 'package:sk_base_mobile/widgets/empty.dart';
import 'package:sk_base_mobile/widgets/fade_in_cache_image.dart';
import 'package:sk_base_mobile/widgets/loading_indicator.dart';
import 'package:sk_base_mobile/widgets/core/sk_appbar.dart';
class HrManagePage extends StatelessWidget {
final controller = Get.put(HrManageController());
HrManagePage({super.key});
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
// 取消焦点
FocusScope.of(context).requestFocus(FocusNode());
},
child: Scaffold(
appBar: const SkAppbar(
backgroundColor: AppTheme.nearlyWhite,
iconAndTextColor: AppTheme.black,
title: '人事管理',
),
body: buildBody(),
));
}
Widget buildBody() {
return Column(
children: [
buildSearchBar(),
Expanded(
child: Container(
margin: EdgeInsets.symmetric(
horizontal: ScreenAdaper.height(defaultPadding),
),
child: Obx(
() => controller.loading.value
? const LoadingIndicator(common: true)
: SmartRefresher(
enablePullDown: true,
enablePullUp: true,
controller: controller.refreshController,
onLoading: controller.onLoading,
onRefresh: controller.onRefresh,
child: controller.list.isEmpty
? const Center(
child: Empty(text: '暂无员工'),
)
: ListView.builder(
padding: EdgeInsets.symmetric(
vertical:
ScreenAdaper.height(defaultPadding)),
itemBuilder: (context, index) {
return buildUserCard(index);
},
itemCount: controller.list.length,
)),
)),
)
],
);
}
Widget buildSearchBar() {
final doSearch = debouncer((String value) {
controller.searchKey.value = value;
controller.onRefresh();
}, delayTime: 500);
return Container(
color: AppTheme.nearlyWhite,
padding: EdgeInsets.all(ScreenAdaper.width(20)),
child: Row(crossAxisAlignment: CrossAxisAlignment.center, children: [
Expanded(
child: SizedBox(
height: ScreenAdaper.height(70),
child: SkTextInput(
fillColor: AppTheme.inputFillColor,
textController: controller.searchBarTextConroller,
onChanged: (value) => doSearch(value),
floatingLabelBehavior: FloatingLabelBehavior.never,
border: OutlineInputBorder(
borderSide: BorderSide.none,
borderRadius: BorderRadius.circular(ScreenAdaper.sp(15))),
prefix: Icon(
Icons.search,
color: AppTheme.nearlyBlack,
size: ScreenAdaper.height(40),
), // 当searchBarController有值时不显示
suffixIcon: Obx(() => controller.searchKey.value.isEmpty
? const SizedBox()
: IconButton(
icon: const Icon(Icons.clear),
onPressed: () {
controller.searchKey.value = '';
controller.searchBarTextConroller.clear();
doSearch('');
},
)),
hint: '查询员工 姓名、手机号、邮箱',
isDense: true,
contentPadding:
EdgeInsets.symmetric(vertical: ScreenAdaper.height(10)),
),
)),
SizedBox(
width: ScreenAdaper.width(10),
),
buildFilterBtn()
]),
);
}
Widget buildFilterBtn() {
return SkInk(
border: Border.all(color: AppTheme.grey.withOpacity(0.8)),
borderRadius: BorderRadius.circular(ScreenAdaper.sp(15)),
onTap: () {},
child: SizedBox(
width: ScreenAdaper.height(65),
height: ScreenAdaper.height(65),
child: Icon(
Icons.filter_list_sharp,
size: ScreenAdaper.height(50),
),
),
);
}
Widget buildUserCard(int index) {
return SkInk(
color: AppTheme.nearlyWhite,
onTap: () {
RouterUtil.toNamed(RouteConfig.employeeDetail,
arguments: controller.list[index]);
},
margin: EdgeInsets.only(bottom: ScreenAdaper.height(defaultPadding)),
borderRadius: BorderRadius.circular(ScreenAdaper.sp(15)),
child: Container(
padding: EdgeInsets.symmetric(
horizontal: ScreenAdaper.height(defaultPadding),
vertical: ScreenAdaper.height(defaultPadding)),
child: Column(
children: [
Row(
children: [
// 头像
SkAvatar(url: controller.list[index].avatar),
SizedBox(
width: ScreenAdaper.height(defaultPadding),
),
// 中间信息
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('${controller.list[index].nickname}',
style: TextStyle(
fontSize: ScreenAdaper.height(30),
fontWeight: FontWeight.w600)),
SizedBox(
height: ScreenAdaper.height(5),
), // role
Text('${controller.list[index].dept?.name}',
style: TextStyle(color: AppTheme.grey)),
SizedBox(
height: ScreenAdaper.height(5),
),
Container(
child: Wrap(
spacing: ScreenAdaper.height(5),
runSpacing: ScreenAdaper.height(5),
children: [
...controller.list[index].roles.map((e) => SkTag(
text: '${e.name}',
color: AppTheme.primaryColorLight))
],
)),
],
)),
/// 右侧action
/// 电话
buildActionButton(
onTap: () {
if (controller.list[index].phone == null) {
SnackBarUtil().info('该员工没有录入手机号');
return;
}
DeviceUtil.callPhone(controller.list[index].phone!);
},
icon: Icons.phone,
),
SizedBox(
width: ScreenAdaper.height(defaultPadding),
),
/// 邮件
buildActionButton(
onTap: () {
if (controller.list[index].email == null) {
SnackBarUtil().info('该员工没有录入邮箱');
return;
}
DeviceUtil.sendEmail(controller.list[index].email!);
},
icon: Icons.email_outlined,
),
SizedBox(
width: ScreenAdaper.height(defaultPadding),
),
/// 编辑
buildActionButton(
onTap: () {
ModalUtil.showGeneralDialog<UserInfoModel>(
content: EditUserInfo(
userId: controller.list[index].id!,
)).then((value) {
Get.delete<EditUserInfoController>();
if (value != null) {
controller.list[index] = value;
}
});
// Get.toNamed(RouteConfig.employeeDetail,
// arguments: controller.list[index]);
},
icon: Icons.edit,
)
],
),
const Divider(),
Row(
children: [
Text(
'工龄: ${SkDateUtil.howLongAgo(controller.list[index].createdAt!)}'),
const Spacer(),
const SkTag(
text: '在职',
color: Colors.green,
)
],
)
],
),
),
);
}
Widget buildActionButton({
required Function() onTap,
required IconData icon,
}) {
return SkInk(
onTap: onTap,
border: Border.all(color: AppTheme.grey.withOpacity(0.8)),
borderRadius: BorderRadius.circular(ScreenAdaper.sp(40)),
child: Container(
padding: EdgeInsets.all(ScreenAdaper.height(5)),
child: Icon(
icon,
size: ScreenAdaper.height(40),
),
),
);
}
}
class HrManageController extends GetxController {
RxList<UserInfoModel> list = RxList([]);
RxString searchKey = ''.obs;
final searchBarTextConroller = TextEditingController();
RefreshController refreshController =
RefreshController(initialRefresh: false);
int page = 1;
int limit = 15;
int total = 0;
RxBool loading = false.obs;
@override
onReady() {
super.onReady();
initData();
}
initData() async {
loading.value = true;
try {
await getData(isRefresh: true);
} finally {
loading.value = false;
}
}
Future<List<UserInfoModel>> getData({bool isRefresh = false}) async {
if (isRefresh == true) {
page = 1;
} else {
page++;
}
final res = await Api.getUsers({
'page': page,
'pageSize': 15,
'keyword': searchKey.value,
});
List<UserInfoModel> newList =
res.data!.items.map((e) => UserInfoModel.fromJson(e)).toList();
isRefresh == true ? list.assignAll(newList) : list.addAll(newList);
return newList;
}
Future<void> onRefresh() async {
await getData(isRefresh: true).then((_) {
refreshController.refreshCompleted(resetFooterState: true);
}).catchError((_) {
refreshController.refreshFailed();
});
}
Future<void> onLoading() async {
await getData().then((_) {
if (_.isEmpty) {
refreshController.loadNoData();
} else {
refreshController.loadComplete();
}
}).catchError((_) {
refreshController.loadFailed();
});
}
}