feat: develop common widget. Hr management feature
This commit is contained in:
parent
1befdcb786
commit
93a30355cd
|
@ -15,7 +15,7 @@ class AppTheme {
|
||||||
static const Color nearlyWhite = Color(0xFFFEFEFE);
|
static const Color nearlyWhite = Color(0xFFFEFEFE);
|
||||||
static const Color black = Color(0xFF000000);
|
static const Color black = Color(0xFF000000);
|
||||||
static const Color nearlyBlack = Color(0xFF213333);
|
static const Color nearlyBlack = Color(0xFF213333);
|
||||||
static const Color grey = Color.fromARGB(255, 98, 101, 102);
|
static const Color grey = Color.fromARGB(255, 138, 138, 138);
|
||||||
static const Color snackbarErrorBackgroudColor = Colors.red;
|
static const Color snackbarErrorBackgroudColor = Colors.red;
|
||||||
static const Color snackbarSuccessBackgroudColor = Colors.green;
|
static const Color snackbarSuccessBackgroudColor = Colors.green;
|
||||||
static const Color snackbarWarningBackgroudColor = Colors.orange;
|
static const Color snackbarWarningBackgroudColor = Colors.orange;
|
||||||
|
@ -25,6 +25,9 @@ class AppTheme {
|
||||||
static const Color notActiveNavigationBarColor = Colors.grey;
|
static const Color notActiveNavigationBarColor = Colors.grey;
|
||||||
static const Color dangerColor = Colors.red;
|
static const Color dangerColor = Colors.red;
|
||||||
static const Color dividerColor = Color.fromARGB(255, 224, 224, 224);
|
static const Color dividerColor = Color.fromARGB(255, 224, 224, 224);
|
||||||
|
static const Color appbarBgColor = AppTheme.primaryColor;
|
||||||
|
static const Color scaffoldBackgroundColor = Color(0xFFf5f8ff);
|
||||||
|
static const Color inputFillColor = Color(0xFFf5f8ff);
|
||||||
}
|
}
|
||||||
|
|
||||||
final theme = ThemeData(
|
final theme = ThemeData(
|
||||||
|
@ -85,7 +88,7 @@ final theme = ThemeData(
|
||||||
const ProgressIndicatorThemeData(color: AppTheme.primaryColor),
|
const ProgressIndicatorThemeData(color: AppTheme.primaryColor),
|
||||||
dividerColor: AppTheme.dividerColor,
|
dividerColor: AppTheme.dividerColor,
|
||||||
cardColor: AppTheme.white,
|
cardColor: AppTheme.white,
|
||||||
scaffoldBackgroundColor: AppTheme.nearlyWhite,
|
scaffoldBackgroundColor: AppTheme.scaffoldBackgroundColor,
|
||||||
bottomNavigationBarTheme: BottomNavigationBarThemeData(
|
bottomNavigationBarTheme: BottomNavigationBarThemeData(
|
||||||
backgroundColor: AppTheme.nearlyWhite,
|
backgroundColor: AppTheme.nearlyWhite,
|
||||||
unselectedLabelStyle: TextStyle(fontSize: ScreenAdaper.height(20)),
|
unselectedLabelStyle: TextStyle(fontSize: ScreenAdaper.height(20)),
|
||||||
|
@ -103,7 +106,7 @@ final theme = ThemeData(
|
||||||
appBarTheme: AppBarTheme(
|
appBarTheme: AppBarTheme(
|
||||||
centerTitle: true,
|
centerTitle: true,
|
||||||
iconTheme: const IconThemeData(color: Colors.white),
|
iconTheme: const IconThemeData(color: Colors.white),
|
||||||
backgroundColor: AppTheme.primaryColor,
|
backgroundColor: AppTheme.appbarBgColor,
|
||||||
titleTextStyle: TextStyle(
|
titleTextStyle: TextStyle(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
fontSize: ScreenAdaper.height(30),
|
fontSize: ScreenAdaper.height(30),
|
||||||
|
@ -114,6 +117,8 @@ final theme = ThemeData(
|
||||||
color: AppTheme.primaryColor,
|
color: AppTheme.primaryColor,
|
||||||
fontSize: ScreenAdaper.height(30),
|
fontSize: ScreenAdaper.height(30),
|
||||||
),
|
),
|
||||||
|
fillColor: AppTheme.inputFillColor,
|
||||||
|
filled: true,
|
||||||
labelStyle: TextStyle(
|
labelStyle: TextStyle(
|
||||||
fontSize: ScreenAdaper.height(25),
|
fontSize: ScreenAdaper.height(25),
|
||||||
),
|
),
|
||||||
|
|
|
@ -2,11 +2,11 @@
|
||||||
|
|
||||||
// Global config
|
// Global config
|
||||||
class GloablConfig {
|
class GloablConfig {
|
||||||
// static const BASE_URL = "http://10.0.2.2:8001/api/";
|
static const BASE_URL = "http://10.0.2.2:8001/api/";
|
||||||
// static const OSS_URL = "http://10.0.2.2:8001";
|
static const OSS_URL = "http://10.0.2.2:8001";
|
||||||
|
|
||||||
static const BASE_URL = "http://144.123.43.138:3001/api/";
|
// static const BASE_URL = "http://144.123.43.138:3001/api/";
|
||||||
static const OSS_URL = "http://144.123.43.138:3001";
|
// static const OSS_URL = "http://144.123.43.138:3001";
|
||||||
// static const BASE_URL = "http://192.168.60.220:8001/api/";
|
// static const BASE_URL = "http://192.168.60.220:8001/api/";
|
||||||
// static const OSS_URL = "http://192.168.60.220:8001";
|
// static const OSS_URL = "http://192.168.60.220:8001";
|
||||||
static const DOMAIN_NAME = "山矿通";
|
static const DOMAIN_NAME = "山矿通";
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
|
import 'package:sk_base_mobile/screens/hr_manage/hr_manage.dart';
|
||||||
import 'package:sk_base_mobile/screens/inventory/inventory.dart';
|
import 'package:sk_base_mobile/screens/inventory/inventory.dart';
|
||||||
import 'package:sk_base_mobile/screens/login/login.dart';
|
import 'package:sk_base_mobile/screens/login/login.dart';
|
||||||
import 'package:sk_base_mobile/screens/sale_quotation/sale_quotation.dart';
|
import 'package:sk_base_mobile/screens/sale_quotation/sale_quotation.dart';
|
||||||
|
@ -12,12 +13,14 @@ class RouteConfig {
|
||||||
static const String userinfo = '/userinfo';
|
static const String userinfo = '/userinfo';
|
||||||
static const String inventory = '/inventory';
|
static const String inventory = '/inventory';
|
||||||
static const String saleQuotation = '/sale_quotation';
|
static const String saleQuotation = '/sale_quotation';
|
||||||
|
static const String hrManage = '/hr_manage';
|
||||||
|
|
||||||
static final List<GetPage> getPages = [
|
static final List<GetPage> getPages = [
|
||||||
GetPage(name: login, page: () => LoginScreen()),
|
GetPage(name: login, page: () => LoginScreen()),
|
||||||
GetPage(name: home, page: () => LandingPage()),
|
GetPage(name: home, page: () => LandingPage()),
|
||||||
GetPage(name: userinfo, page: () => UserInfoPage()),
|
GetPage(name: userinfo, page: () => UserInfoPage()),
|
||||||
GetPage(name: inventory, page: () => const InventoryPage()),
|
GetPage(name: inventory, page: () => const InventoryPage()),
|
||||||
GetPage(name: saleQuotation, page: () => SaleQuotationPage())
|
GetPage(name: saleQuotation, page: () => SaleQuotationPage()),
|
||||||
|
GetPage(name: hrManage, page: () => HrManagePage())
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ import 'package:sk_base_mobile/constants/cache_key.dart';
|
||||||
import 'package:sk_base_mobile/services/app_info.service.dart';
|
import 'package:sk_base_mobile/services/app_info.service.dart';
|
||||||
import 'package:sk_base_mobile/services/dio.service.dart';
|
import 'package:sk_base_mobile/services/dio.service.dart';
|
||||||
import 'package:sk_base_mobile/services/storage.service.dart';
|
import 'package:sk_base_mobile/services/storage.service.dart';
|
||||||
|
import 'package:timeago/timeago.dart';
|
||||||
import 'store/store.dart';
|
import 'store/store.dart';
|
||||||
import 'package:flutter_native_splash/flutter_native_splash.dart';
|
import 'package:flutter_native_splash/flutter_native_splash.dart';
|
||||||
|
|
||||||
|
@ -27,7 +28,7 @@ class Global {
|
||||||
setSystemUi();
|
setSystemUi();
|
||||||
|
|
||||||
/// 初始化 几天前 的时区国际化
|
/// 初始化 几天前 的时区国际化
|
||||||
timeago.setLocaleMessages('en', timeago.EnMessages());
|
timeago.setLocaleMessages('zh_cn', MyCustomMessages());
|
||||||
|
|
||||||
/// 依赖注入Loading工具
|
/// 依赖注入Loading工具
|
||||||
await Get.putAsync<LoadingUtil>(() => LoadingUtil().init());
|
await Get.putAsync<LoadingUtil>(() => LoadingUtil().init());
|
||||||
|
@ -69,3 +70,39 @@ class Global {
|
||||||
FlutterNativeSplash.remove();
|
FlutterNativeSplash.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// my_custom_messages.dart
|
||||||
|
class MyCustomMessages implements LookupMessages {
|
||||||
|
@override
|
||||||
|
String prefixAgo() => '';
|
||||||
|
@override
|
||||||
|
String prefixFromNow() => '';
|
||||||
|
@override
|
||||||
|
String suffixAgo() => '';
|
||||||
|
@override
|
||||||
|
String suffixFromNow() => '';
|
||||||
|
@override
|
||||||
|
String lessThanOneMinute(int seconds) => '现在';
|
||||||
|
@override
|
||||||
|
String aboutAMinute(int minutes) => '$minutes分钟';
|
||||||
|
@override
|
||||||
|
String minutes(int minutes) => '$minutes分钟';
|
||||||
|
@override
|
||||||
|
String aboutAnHour(int minutes) => '$minutes分钟';
|
||||||
|
@override
|
||||||
|
String hours(int hours) => '$hours小时';
|
||||||
|
@override
|
||||||
|
String aDay(int hours) => '$hours小时';
|
||||||
|
@override
|
||||||
|
String days(int days) => '$days天';
|
||||||
|
@override
|
||||||
|
String aboutAMonth(int days) => '$days天';
|
||||||
|
@override
|
||||||
|
String months(int months) => '$months月';
|
||||||
|
@override
|
||||||
|
String aboutAYear(int year) => '$year年';
|
||||||
|
@override
|
||||||
|
String years(int years) => '$years年';
|
||||||
|
@override
|
||||||
|
String wordSeparator() => ' ';
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,295 @@
|
||||||
|
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/index.dart';
|
||||||
|
import 'package:sk_base_mobile/app_theme.dart';
|
||||||
|
import 'package:sk_base_mobile/constants/bg_color.dart';
|
||||||
|
import 'package:sk_base_mobile/models/user_info.model.dart';
|
||||||
|
import 'package:sk_base_mobile/util/date.util.dart';
|
||||||
|
import 'package:sk_base_mobile/util/debouncer.dart';
|
||||||
|
import 'package:sk_base_mobile/util/screen_adaper_util.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/core/sk_text_input.dart';
|
||||||
|
import 'package:sk_base_mobile/widgets/empty.dart';
|
||||||
|
import 'package:sk_base_mobile/widgets/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(
|
||||||
|
backgroundColor: Color(0xFFe9f0fd),
|
||||||
|
appBar: 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),
|
||||||
|
vertical: ScreenAdaper.height(defaultPadding)),
|
||||||
|
child: Obx(
|
||||||
|
() => 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(
|
||||||
|
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.only(
|
||||||
|
right: ScreenAdaper.width(20),
|
||||||
|
left: ScreenAdaper.width(20),
|
||||||
|
bottom: ScreenAdaper.height(20)),
|
||||||
|
child: Row(children: [
|
||||||
|
Expanded(
|
||||||
|
child: SizedBox(
|
||||||
|
height: ScreenAdaper.height(70),
|
||||||
|
child: SkTextInput(
|
||||||
|
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),
|
||||||
|
),
|
||||||
|
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 Container(
|
||||||
|
padding: EdgeInsets.symmetric(
|
||||||
|
horizontal: ScreenAdaper.height(defaultPadding),
|
||||||
|
vertical: ScreenAdaper.height(defaultPadding)),
|
||||||
|
margin: EdgeInsets.only(bottom: ScreenAdaper.height(defaultPadding)),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: AppTheme.white,
|
||||||
|
borderRadius: BorderRadius.circular(ScreenAdaper.sp(15))),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
// 头像
|
||||||
|
ClipRRect(
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(30)),
|
||||||
|
child: Image(
|
||||||
|
height: ScreenAdaper.height(80),
|
||||||
|
image: NetworkImage(
|
||||||
|
'https://thirdqq.qlogo.cn/g?b=qq&s=100&nk=1743369777')),
|
||||||
|
),
|
||||||
|
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: () {},
|
||||||
|
icon: Icons.phone,
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
width: ScreenAdaper.height(defaultPadding),
|
||||||
|
),
|
||||||
|
|
||||||
|
/// 邮件
|
||||||
|
buildActionButton(
|
||||||
|
onTap: () {},
|
||||||
|
icon: Icons.email_outlined,
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
width: ScreenAdaper.height(defaultPadding),
|
||||||
|
),
|
||||||
|
|
||||||
|
/// 编辑
|
||||||
|
buildActionButton(
|
||||||
|
onTap: () {},
|
||||||
|
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: () {},
|
||||||
|
border: Border.all(color: AppTheme.grey.withOpacity(0.8)),
|
||||||
|
borderRadius: BorderRadius.circular(ScreenAdaper.sp(30)),
|
||||||
|
child: Container(
|
||||||
|
padding: EdgeInsets.all(ScreenAdaper.height(5)),
|
||||||
|
child: Icon(
|
||||||
|
icon,
|
||||||
|
size: ScreenAdaper.height(35),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class HrManageController extends GetxController {
|
||||||
|
RxList<UserInfoModel> list = RxList([]);
|
||||||
|
RxString searchKey = ''.obs;
|
||||||
|
final searchBarTextConroller = TextEditingController();
|
||||||
|
RefreshController refreshController = RefreshController(initialRefresh: true);
|
||||||
|
int page = 1;
|
||||||
|
int limit = 15;
|
||||||
|
int total = 0;
|
||||||
|
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();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,7 +14,7 @@ class Dates extends StatelessWidget {
|
||||||
children: [
|
children: [
|
||||||
Obx(
|
Obx(
|
||||||
() => Text(
|
() => Text(
|
||||||
DateUtil.getMonth(
|
SkDateUtil.getMonth(
|
||||||
controller.endTime.value.add(Duration(days: -index))),
|
controller.endTime.value.add(Duration(days: -index))),
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: controller.currentIndex.value == index
|
color: controller.currentIndex.value == index
|
||||||
|
@ -27,7 +27,7 @@ class Dates extends StatelessWidget {
|
||||||
),
|
),
|
||||||
Obx(
|
Obx(
|
||||||
() => Text(
|
() => Text(
|
||||||
DateUtil.getDate(
|
SkDateUtil.getDate(
|
||||||
controller.endTime.value.add(Duration(days: -index))),
|
controller.endTime.value.add(Duration(days: -index))),
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: controller.currentIndex.value == index
|
color: controller.currentIndex.value == index
|
||||||
|
@ -40,7 +40,7 @@ class Dates extends StatelessWidget {
|
||||||
),
|
),
|
||||||
Obx(
|
Obx(
|
||||||
() => Text(
|
() => Text(
|
||||||
DateUtil.getDay(
|
SkDateUtil.getDay(
|
||||||
controller.endTime.value.add(Duration(days: -index))),
|
controller.endTime.value.add(Duration(days: -index))),
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: controller.currentIndex.value == index
|
color: controller.currentIndex.value == index
|
||||||
|
|
|
@ -109,7 +109,7 @@ class InventoryInoutCard extends StatelessWidget {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
'${DateUtil.format(controller.list[ind][index].time!, formats: [
|
'${SkDateUtil.format(controller.list[ind][index].time!, formats: [
|
||||||
'HH',
|
'HH',
|
||||||
':',
|
':',
|
||||||
"nn"
|
"nn"
|
||||||
|
|
|
@ -62,7 +62,7 @@ class InventoryInoutInfo extends StatelessWidget {
|
||||||
],
|
],
|
||||||
buildListItem(
|
buildListItem(
|
||||||
leading: '出入库时间',
|
leading: '出入库时间',
|
||||||
trailing: DateUtil.format(
|
trailing: SkDateUtil.format(
|
||||||
controller.inventoryInoutInfo.value!.time!,
|
controller.inventoryInoutInfo.value!.time!,
|
||||||
formats: [
|
formats: [
|
||||||
'yyyy',
|
'yyyy',
|
||||||
|
|
|
@ -247,8 +247,8 @@ class InventoryInoutController extends GetxController {
|
||||||
Future<List<InventoryInOutModel>> getInoutHistory() async {
|
Future<List<InventoryInOutModel>> getInoutHistory() async {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
await Future.delayed(const Duration(milliseconds: 500));
|
await Future.delayed(const Duration(milliseconds: 500));
|
||||||
final selectedDate =
|
final selectedDate = SkDateUtil.format(
|
||||||
DateUtil.format(endTime.value.add(Duration(days: -currentIndex.value)));
|
endTime.value.add(Duration(days: -currentIndex.value)));
|
||||||
try {
|
try {
|
||||||
final res = await Api.getInventoryInout({
|
final res = await Api.getInventoryInout({
|
||||||
'time': [selectedDate, selectedDate]
|
'time': [selectedDate, selectedDate]
|
||||||
|
@ -290,7 +290,7 @@ class InventoryInoutController extends GetxController {
|
||||||
}
|
}
|
||||||
|
|
||||||
getDateAccordingTabs(int value) {
|
getDateAccordingTabs(int value) {
|
||||||
return DateUtil.format(
|
return SkDateUtil.format(
|
||||||
endTime.value.add(Duration(days: -(daysNum - value))));
|
endTime.value.add(Duration(days: -(daysNum - value))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -300,7 +300,7 @@ class InventoryInoutController extends GetxController {
|
||||||
RxList<InventoryInOutModel> tempList1 = <InventoryInOutModel>[].obs;
|
RxList<InventoryInOutModel> tempList1 = <InventoryInOutModel>[].obs;
|
||||||
tempList1.clear();
|
tempList1.clear();
|
||||||
for (int j = 0; j < model.length; j++) {
|
for (int j = 0; j < model.length; j++) {
|
||||||
final sourceDateStr = DateUtil.format(model[j].time);
|
final sourceDateStr = SkDateUtil.format(model[j].time);
|
||||||
final currentDateStr = getDateAccordingTabs(i);
|
final currentDateStr = getDateAccordingTabs(i);
|
||||||
if (sourceDateStr == currentDateStr) {
|
if (sourceDateStr == currentDateStr) {
|
||||||
tempList1.add(model[j]);
|
tempList1.add(model[j]);
|
||||||
|
|
|
@ -56,7 +56,7 @@ class MineSettingsPage extends StatelessWidget {
|
||||||
EdgeInsets.symmetric(vertical: ScreenAdaper.width(10)),
|
EdgeInsets.symmetric(vertical: ScreenAdaper.width(10)),
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
await AppInfoService.to.checkVersion();
|
await AppInfoService.to.checkVersion(forceCheck: true);
|
||||||
},
|
},
|
||||||
child: Container(
|
child: Container(
|
||||||
padding: EdgeInsets.symmetric(
|
padding: EdgeInsets.symmetric(
|
||||||
|
|
|
@ -83,18 +83,16 @@ class AgentSearch extends StatelessWidget {
|
||||||
controller: controller.refreshController,
|
controller: controller.refreshController,
|
||||||
onLoading: controller.onLoading,
|
onLoading: controller.onLoading,
|
||||||
onRefresh: controller.onRefresh,
|
onRefresh: controller.onRefresh,
|
||||||
child: controller.refreshController.isLoading
|
child: controller.list.isEmpty
|
||||||
? const SizedBox()
|
? const Center(
|
||||||
: controller.list.isEmpty
|
child: Empty(text: '暂无数据'),
|
||||||
? const Center(
|
)
|
||||||
child: Empty(text: '暂无数据'),
|
: ListView.separated(
|
||||||
)
|
separatorBuilder: (context, index) => const Divider(
|
||||||
: ListView.separated(
|
color: AppTheme.dividerColor,
|
||||||
separatorBuilder: (context, index) => const Divider(
|
),
|
||||||
color: AppTheme.dividerColor,
|
itemCount: controller.list.length,
|
||||||
),
|
itemBuilder: (_, index) => buildItem(index))));
|
||||||
itemCount: controller.list.length,
|
|
||||||
itemBuilder: (_, index) => buildItem(index))));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget buildItem(int index) {
|
Widget buildItem(int index) {
|
||||||
|
|
|
@ -283,7 +283,7 @@ class NewInventoryInout extends StatelessWidget {
|
||||||
},
|
},
|
||||||
onDateSelected: (date) {
|
onDateSelected: (date) {
|
||||||
if (date != null) {
|
if (date != null) {
|
||||||
controller.dateTextController.text = DateUtil.format(date);
|
controller.dateTextController.text = SkDateUtil.format(date);
|
||||||
controller.payload['time'] = controller.dateTextController.text;
|
controller.payload['time'] = controller.dateTextController.text;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -74,8 +74,8 @@ class NewInventoryInoutController extends GetxController {
|
||||||
@override
|
@override
|
||||||
onReady() {
|
onReady() {
|
||||||
super.onReady();
|
super.onReady();
|
||||||
dateTextController.text = DateUtil.format(DateTime.now());
|
dateTextController.text = SkDateUtil.format(DateTime.now());
|
||||||
payload['time'] = DateUtil.format(DateTime.now());
|
payload['time'] = SkDateUtil.format(DateTime.now());
|
||||||
payload['inOrOut'] = inOrOut;
|
payload['inOrOut'] = inOrOut;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,7 +136,7 @@ class NewInventoryInoutController extends GetxController {
|
||||||
// return;
|
// return;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
payload['time'] = DateUtil.format(DateTime.now(), formats: [
|
payload['time'] = SkDateUtil.format(DateTime.now(), formats: [
|
||||||
'yyyy',
|
'yyyy',
|
||||||
'-',
|
'-',
|
||||||
'mm',
|
'mm',
|
||||||
|
@ -274,7 +274,7 @@ class NewInventoryInoutController extends GetxController {
|
||||||
await showTimePicker(context: context, initialTime: TimeOfDay.now());
|
await showTimePicker(context: context, initialTime: TimeOfDay.now());
|
||||||
if (picker != null) {
|
if (picker != null) {
|
||||||
startTime.value =
|
startTime.value =
|
||||||
'${DateUtil.addPrefix(picker.hourOfPeriod.toString())}:${DateUtil.addPrefix(picker.minute.toString())}:${picker.period.name.toUpperCase()}';
|
'${SkDateUtil.addPrefix(picker.hourOfPeriod.toString())}:${SkDateUtil.addPrefix(picker.minute.toString())}:${picker.period.name.toUpperCase()}';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -283,7 +283,7 @@ class NewInventoryInoutController extends GetxController {
|
||||||
await showTimePicker(context: context, initialTime: TimeOfDay.now());
|
await showTimePicker(context: context, initialTime: TimeOfDay.now());
|
||||||
if (picker != null) {
|
if (picker != null) {
|
||||||
endTime.value =
|
endTime.value =
|
||||||
'${DateUtil.addPrefix(picker.hourOfPeriod.toString())}:${DateUtil.addPrefix(picker.minute.toString())}:${picker.period.name.toUpperCase()}';
|
'${SkDateUtil.addPrefix(picker.hourOfPeriod.toString())}:${SkDateUtil.addPrefix(picker.minute.toString())}:${picker.period.name.toUpperCase()}';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -296,7 +296,7 @@ class NewInventoryInoutController extends GetxController {
|
||||||
if (picker != null) {
|
if (picker != null) {
|
||||||
pickedDate = picker;
|
pickedDate = picker;
|
||||||
selectedDate.value =
|
selectedDate.value =
|
||||||
'${DateUtil.addPrefix(picker.day.toString())}/${DateUtil.addPrefix(picker.month.toString())}/${picker.year}';
|
'${SkDateUtil.addPrefix(picker.day.toString())}/${SkDateUtil.addPrefix(picker.month.toString())}/${picker.year}';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -82,18 +82,16 @@ class SaleQuotationGroupSearch extends StatelessWidget {
|
||||||
controller: controller.refreshController,
|
controller: controller.refreshController,
|
||||||
onLoading: controller.onLoading,
|
onLoading: controller.onLoading,
|
||||||
onRefresh: controller.onRefresh,
|
onRefresh: controller.onRefresh,
|
||||||
child: controller.refreshController.isLoading
|
child: controller.list.isEmpty
|
||||||
? const SizedBox()
|
? const Center(
|
||||||
: controller.list.isEmpty
|
child: Empty(text: '暂无数据'),
|
||||||
? const Center(
|
)
|
||||||
child: Empty(text: '暂无数据'),
|
: ListView.separated(
|
||||||
)
|
separatorBuilder: (context, index) => const Divider(
|
||||||
: ListView.separated(
|
color: AppTheme.dividerColor,
|
||||||
separatorBuilder: (context, index) => const Divider(
|
),
|
||||||
color: AppTheme.dividerColor,
|
itemCount: controller.list.length,
|
||||||
),
|
itemBuilder: (_, index) => buildItem(index))));
|
||||||
itemCount: controller.list.length,
|
|
||||||
itemBuilder: (_, index) => buildItem(index))));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget buildItem(int index) {
|
Widget buildItem(int index) {
|
||||||
|
|
|
@ -7,7 +7,7 @@ class WorkBenchController extends GetxController {
|
||||||
WorkBenchModel(title: '库存', route: '/inventory', icon: 'inventory.svg'),
|
WorkBenchModel(title: '库存', route: '/inventory', icon: 'inventory.svg'),
|
||||||
WorkBenchModel(title: '产品', route: '/product', icon: 'product.svg'),
|
WorkBenchModel(title: '产品', route: '/product', icon: 'product.svg'),
|
||||||
WorkBenchModel(title: '合同', route: '/contract', icon: 'contract.svg'),
|
WorkBenchModel(title: '合同', route: '/contract', icon: 'contract.svg'),
|
||||||
WorkBenchModel(title: '人事', route: '/hr', icon: 'hr.svg'),
|
WorkBenchModel(title: '人事', route: '/hr_manage', icon: 'hr.svg'),
|
||||||
WorkBenchModel(title: '公车', route: '/vehicle', icon: 'vehicle.svg'),
|
WorkBenchModel(title: '公车', route: '/vehicle', icon: 'vehicle.svg'),
|
||||||
WorkBenchModel(title: '任务', route: '/task_manage', icon: 'task_manage.svg'),
|
WorkBenchModel(title: '任务', route: '/task_manage', icon: 'task_manage.svg'),
|
||||||
WorkBenchModel(title: '报表', route: '/report', icon: 'report.svg'),
|
WorkBenchModel(title: '报表', route: '/report', icon: 'report.svg'),
|
||||||
|
|
|
@ -112,7 +112,7 @@ class AppInfoService extends GetxService {
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
Future<void> checkVersion() async {
|
Future<void> checkVersion({forceCheck = false}) async {
|
||||||
final res = await Future.wait([
|
final res = await Future.wait([
|
||||||
Api.getSystemParamConfigByCode(SystemParamConfig.appVersion),
|
Api.getSystemParamConfigByCode(SystemParamConfig.appVersion),
|
||||||
Api.getSystemParamConfigByCode(SystemParamConfig.isForceUpgrade)
|
Api.getSystemParamConfigByCode(SystemParamConfig.isForceUpgrade)
|
||||||
|
@ -132,6 +132,8 @@ class AppInfoService extends GetxService {
|
||||||
),
|
),
|
||||||
// contentText: isForceUpgrade == '1' ? '此版本非常重要,强制更新' : '请更新',
|
// contentText: isForceUpgrade == '1' ? '此版本非常重要,强制更新' : '请更新',
|
||||||
);
|
);
|
||||||
|
} else if (forceCheck) {
|
||||||
|
SnackBarUtil().info('已经是最新版本');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
import 'package:date_format/date_format.dart';
|
import 'package:date_format/date_format.dart';
|
||||||
|
import 'package:timeago/timeago.dart' as timeago;
|
||||||
|
|
||||||
class DateUtil {
|
class SkDateUtil {
|
||||||
/// 格式化日期 默认 YYYY-MM-DD
|
/// 格式化日期 默认 YYYY-MM-DD
|
||||||
static String format(DateTime date, {List<String>? formats}) {
|
static String format(DateTime date, {List<String>? formats}) {
|
||||||
return formatDate(date, formats ?? ['yyyy', '-', 'MM', '-', 'dd']);
|
return formatDate(date, formats ?? ['yyyy', '-', 'mm', '-', 'dd']);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 获取几月
|
/// 获取几月
|
||||||
|
@ -33,4 +34,9 @@ class DateUtil {
|
||||||
}
|
}
|
||||||
return string;
|
return string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 使用timeago距现在多久
|
||||||
|
static String howLongAgo(DateTime date) {
|
||||||
|
return timeago.format(date, locale: 'zh_cn'); //
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,7 +74,7 @@ class SnackBarUtil {
|
||||||
borderRadius: 15,
|
borderRadius: 15,
|
||||||
margin: EdgeInsets.symmetric(
|
margin: EdgeInsets.symmetric(
|
||||||
horizontal: ScreenAdaper.height(15), vertical: 0),
|
horizontal: ScreenAdaper.height(15), vertical: 0),
|
||||||
duration: const Duration(seconds: 2),
|
duration: const Duration(seconds: 1),
|
||||||
dismissDirection: DismissDirection.horizontal,
|
dismissDirection: DismissDirection.horizontal,
|
||||||
forwardAnimationCurve: Curves.fastLinearToSlowEaseIn,
|
forwardAnimationCurve: Curves.fastLinearToSlowEaseIn,
|
||||||
reverseAnimationCurve: Curves.linearToEaseOut);
|
reverseAnimationCurve: Curves.linearToEaseOut);
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:sk_base_mobile/app_theme.dart';
|
||||||
|
|
||||||
|
class SkInk extends StatelessWidget {
|
||||||
|
final Widget? child;
|
||||||
|
final void Function()? onTap;
|
||||||
|
final BorderRadius? borderRadius;
|
||||||
|
final BoxBorder? border;
|
||||||
|
const SkInk(
|
||||||
|
{super.key, this.child, this.onTap, this.borderRadius, this.border});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Material(
|
||||||
|
child: Ink(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
border: border ?? Border.all(color: AppTheme.grey.withOpacity(0.8)),
|
||||||
|
borderRadius: borderRadius,
|
||||||
|
),
|
||||||
|
child:
|
||||||
|
InkWell(borderRadius: borderRadius, onTap: onTap, child: child)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -141,19 +141,17 @@ class SkMutilSearchMore<T extends BaseSearchMoreModel> extends StatelessWidget {
|
||||||
controller: controller.refreshController,
|
controller: controller.refreshController,
|
||||||
onLoading: controller.onLoading,
|
onLoading: controller.onLoading,
|
||||||
onRefresh: controller.onRefresh,
|
onRefresh: controller.onRefresh,
|
||||||
child: controller.refreshController.isLoading
|
child: controller.list.isEmpty
|
||||||
? const SizedBox()
|
? const Center(
|
||||||
: controller.list.isEmpty
|
child: Empty(text: '暂无数据'),
|
||||||
? const Center(
|
)
|
||||||
child: Empty(text: '暂无数据'),
|
: ListView.separated(
|
||||||
)
|
separatorBuilder: (context, index) => const Divider(
|
||||||
: ListView.separated(
|
color: AppTheme.dividerColor,
|
||||||
separatorBuilder: (context, index) => const Divider(
|
height: 1,
|
||||||
color: AppTheme.dividerColor,
|
),
|
||||||
height: 1,
|
itemCount: controller.list.length,
|
||||||
),
|
itemBuilder: (_, index) => buildItem(index))));
|
||||||
itemCount: controller.list.length,
|
|
||||||
itemBuilder: (_, index) => buildItem(index))));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget buildItem(int index) {
|
Widget buildItem(int index) {
|
||||||
|
|
|
@ -125,20 +125,18 @@ class SkSingleSearchMore<T> extends StatelessWidget {
|
||||||
controller: controller.refreshController,
|
controller: controller.refreshController,
|
||||||
onLoading: controller.onLoading,
|
onLoading: controller.onLoading,
|
||||||
onRefresh: controller.onRefresh,
|
onRefresh: controller.onRefresh,
|
||||||
child: controller.refreshController.isLoading
|
child: controller.list.isEmpty
|
||||||
? const SizedBox()
|
? const Center(
|
||||||
: controller.list.isEmpty
|
child: Empty(text: '暂无数据'),
|
||||||
? const Center(
|
)
|
||||||
child: Empty(text: '暂无数据'),
|
: ListView.separated(
|
||||||
)
|
separatorBuilder: (context, index) => const Divider(
|
||||||
: ListView.separated(
|
color: AppTheme.dividerColor,
|
||||||
separatorBuilder: (context, index) => const Divider(
|
),
|
||||||
color: AppTheme.dividerColor,
|
itemCount: controller.list.length,
|
||||||
),
|
itemBuilder: (_, index) => itemBuilder != null
|
||||||
itemCount: controller.list.length,
|
? itemBuilder!(_, index)
|
||||||
itemBuilder: (_, index) => itemBuilder != null
|
: buildItem(index))));
|
||||||
? itemBuilder!(_, index)
|
|
||||||
: buildItem(index))));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget buildItem(int index) {
|
Widget buildItem(int index) {
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:sk_base_mobile/app_theme.dart';
|
||||||
|
import 'package:sk_base_mobile/util/screen_adaper_util.dart';
|
||||||
|
|
||||||
|
class SkTag extends StatelessWidget {
|
||||||
|
final String text;
|
||||||
|
final Color? color;
|
||||||
|
const SkTag({super.key, required this.text, required this.color});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
padding: EdgeInsets.symmetric(
|
||||||
|
horizontal: ScreenAdaper.height(10),
|
||||||
|
vertical: ScreenAdaper.height(4)),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
border: Border.all(
|
||||||
|
color: (color ?? AppTheme.primaryColorLight).withOpacity(0.1)),
|
||||||
|
color: (color ?? AppTheme.primaryColorLight).withOpacity(0.2),
|
||||||
|
borderRadius: BorderRadius.circular(ScreenAdaper.sp(15)),
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
text,
|
||||||
|
style: TextStyle(
|
||||||
|
color: color ?? AppTheme.primaryColorLight,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
fontSize: ScreenAdaper.sp(30)),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,7 +6,7 @@ class SkTextInput extends StatefulWidget {
|
||||||
final TextEditingController textController;
|
final TextEditingController textController;
|
||||||
final Function(FocusNode)? onTap;
|
final Function(FocusNode)? onTap;
|
||||||
final bool isRequired;
|
final bool isRequired;
|
||||||
final String labelText;
|
final String? labelText;
|
||||||
final String? hint;
|
final String? hint;
|
||||||
final bool isTextArea;
|
final bool isTextArea;
|
||||||
final bool isDense;
|
final bool isDense;
|
||||||
|
@ -16,6 +16,10 @@ class SkTextInput extends StatefulWidget {
|
||||||
final EdgeInsetsGeometry? contentPadding;
|
final EdgeInsetsGeometry? contentPadding;
|
||||||
final bool autoFocus;
|
final bool autoFocus;
|
||||||
final ValueChanged<String>? onFieldSubmitted;
|
final ValueChanged<String>? onFieldSubmitted;
|
||||||
|
final Icon? prefix;
|
||||||
|
final Widget? suffixIcon;
|
||||||
|
final InputBorder? border;
|
||||||
|
final FloatingLabelBehavior? floatingLabelBehavior;
|
||||||
const SkTextInput(
|
const SkTextInput(
|
||||||
{super.key,
|
{super.key,
|
||||||
required this.textController,
|
required this.textController,
|
||||||
|
@ -24,8 +28,12 @@ class SkTextInput extends StatefulWidget {
|
||||||
this.onFieldSubmitted,
|
this.onFieldSubmitted,
|
||||||
this.isRequired = false,
|
this.isRequired = false,
|
||||||
this.onTapOutside,
|
this.onTapOutside,
|
||||||
this.labelText = '',
|
this.labelText,
|
||||||
|
this.prefix,
|
||||||
|
this.suffixIcon,
|
||||||
this.onChanged,
|
this.onChanged,
|
||||||
|
this.border,
|
||||||
|
this.floatingLabelBehavior = FloatingLabelBehavior.always,
|
||||||
this.isTextArea = false,
|
this.isTextArea = false,
|
||||||
this.autoFocus = false,
|
this.autoFocus = false,
|
||||||
this.contentPadding,
|
this.contentPadding,
|
||||||
|
@ -74,26 +82,33 @@ class _SkTextInputState extends State<SkTextInput> {
|
||||||
onFieldSubmitted: widget.onFieldSubmitted,
|
onFieldSubmitted: widget.onFieldSubmitted,
|
||||||
autovalidateMode: AutovalidateMode.onUserInteraction,
|
autovalidateMode: AutovalidateMode.onUserInteraction,
|
||||||
validator: widget.validator,
|
validator: widget.validator,
|
||||||
|
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
|
prefixIcon: widget.prefix,
|
||||||
|
suffixIcon: widget.suffixIcon,
|
||||||
errorStyle: const TextStyle(fontSize: 0, height: 0.01),
|
errorStyle: const TextStyle(fontSize: 0, height: 0.01),
|
||||||
contentPadding: widget.contentPadding,
|
contentPadding: widget.contentPadding,
|
||||||
isDense: widget.isDense,
|
isDense: widget.isDense,
|
||||||
floatingLabelBehavior: FloatingLabelBehavior.always,
|
border: widget.border,
|
||||||
label: Row(
|
floatingLabelBehavior: widget.floatingLabelBehavior,
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
label: widget.labelText != null
|
||||||
mainAxisSize: MainAxisSize.min,
|
? Row(
|
||||||
children: [
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
if (widget.isRequired)
|
mainAxisSize: MainAxisSize.min,
|
||||||
Text(
|
children: [
|
||||||
"*",
|
if (widget.isRequired)
|
||||||
style: TextStyle(
|
Text(
|
||||||
color: Colors.red, fontSize: ScreenAdaper.height(30)),
|
"*",
|
||||||
),
|
style: TextStyle(
|
||||||
Text(
|
color: Colors.red,
|
||||||
widget.labelText,
|
fontSize: ScreenAdaper.height(30)),
|
||||||
style: TextStyle(fontSize: ScreenAdaper.height(30)),
|
),
|
||||||
),
|
Text(
|
||||||
]),
|
widget.labelText!,
|
||||||
|
style: TextStyle(fontSize: ScreenAdaper.height(30)),
|
||||||
|
),
|
||||||
|
])
|
||||||
|
: null,
|
||||||
focusedBorder: OutlineInputBorder(
|
focusedBorder: OutlineInputBorder(
|
||||||
borderSide: BorderSide(color: AppTheme.primaryColorLight, width: 2),
|
borderSide: BorderSide(color: AppTheme.primaryColorLight, width: 2),
|
||||||
borderRadius: BorderRadius.circular(ScreenAdaper.sp(15))),
|
borderRadius: BorderRadius.circular(ScreenAdaper.sp(15))),
|
||||||
|
|
|
@ -1,22 +1,39 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:sk_base_mobile/app_theme.dart';
|
||||||
import 'package:sk_base_mobile/util/util.dart';
|
import 'package:sk_base_mobile/util/util.dart';
|
||||||
|
|
||||||
class SkAppbar extends StatelessWidget implements PreferredSizeWidget {
|
class SkAppbar extends StatelessWidget implements PreferredSizeWidget {
|
||||||
final String title;
|
final String title;
|
||||||
final List<Widget>? action;
|
final List<Widget>? action;
|
||||||
final bool hideLeading;
|
final bool hideLeading;
|
||||||
|
final PreferredSizeWidget? bottom;
|
||||||
|
final Color? backgroundColor;
|
||||||
|
final Color? iconAndTextColor;
|
||||||
const SkAppbar(
|
const SkAppbar(
|
||||||
{super.key, required this.title, this.action, this.hideLeading = false});
|
{super.key,
|
||||||
|
required this.title,
|
||||||
|
this.action,
|
||||||
|
this.hideLeading = false,
|
||||||
|
this.backgroundColor,
|
||||||
|
this.iconAndTextColor,
|
||||||
|
this.bottom});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return AppBar(
|
return AppBar(
|
||||||
|
titleTextStyle: TextStyle(
|
||||||
|
color: iconAndTextColor,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
letterSpacing: ScreenAdaper.width(2)),
|
||||||
|
backgroundColor: backgroundColor,
|
||||||
|
bottom: bottom,
|
||||||
leading: hideLeading
|
leading: hideLeading
|
||||||
? const SizedBox()
|
? const SizedBox()
|
||||||
: IconButton(
|
: IconButton(
|
||||||
icon: Icon(
|
icon: Icon(
|
||||||
Icons.arrow_back_ios,
|
Icons.arrow_back_ios,
|
||||||
size: ScreenAdaper.height(40),
|
size: ScreenAdaper.height(40),
|
||||||
|
color: iconAndTextColor,
|
||||||
),
|
),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
|
|
Loading…
Reference in New Issue