flutter_integrated_whb/lib/tools/tools.dart

393 lines
10 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

import 'dart:math';
import 'package:flutter/material.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
int getRandomWithNum(int min, int max) {
final random = Random();
return random.nextInt(max) + min; // 生成随机数
}
double screenWidth(BuildContext context) {
double screenWidth = MediaQuery.of(context).size.width;
return screenWidth;
}
Future<T?> pushPage<T>(Widget page, BuildContext context) {
return Navigator.push<T>(
context,
MaterialPageRoute(builder: (_) => page),
);
}
void present(Widget page, BuildContext context) {
Navigator.of(context).push(
PageRouteBuilder(
pageBuilder: (context, animation, secondaryAnimation) => page,
transitionDuration: Duration.zero,
reverseTransitionDuration: Duration.zero,
),
);
}
void presentOpaque(Widget page, BuildContext context) {
Navigator.of(context).push(
PageRouteBuilder(
opaque: false, // 允许下层透出
barrierColor: Colors.black.withOpacity(0.5), //路由遮罩色
pageBuilder: (context, animation, secondaryAnimation) => page,
transitionDuration: Duration.zero,
reverseTransitionDuration: Duration.zero,
),
);
}
class FocusHelper {
static final FocusNode _emptyNode = FocusNode();
/// 延迟一帧后再移交焦点,避免不生效的问题
static void clearFocus(BuildContext context) {
WidgetsBinding.instance.addPostFrameCallback((_) {
FocusScope.of(context).requestFocus(_emptyNode);
});
}
}
/// 文本样式工具类,返回 Text Widget
class HhTextStyleUtils {
/// 主要标题,返回 Text
/// [text]: 文本内容
/// [color]: 文本颜色,默认黑色
/// [fontSize]: 字体大小默认16.0
/// [bold]: 是否加粗默认true
static Text mainTitle(
String text, {
Color color = Colors.black,
double fontSize = 16.0,
bool bold = true,
}) {
return Text(
text,
style: TextStyle(
color: color,
fontSize: fontSize,
fontWeight: bold ? FontWeight.bold : FontWeight.normal,
),
);
}
static TextStyle secondaryTitleStyle = TextStyle(
color: Colors.black54,
fontSize: 15.0,
);
/// 次要标题,返回 Text
/// [text]: 文本内容
/// [color]: 文本颜色,默认深灰
/// [fontSize]: 字体大小默认14.0
/// [bold]: 是否加粗默认false
static Text secondaryTitle(
String text, {
Color color = Colors.black54,
double fontSize = 14.0,
bool bold = false,
}) {
return Text(
text,
style: TextStyle(
color: color,
fontSize: fontSize,
fontWeight: bold ? FontWeight.bold : FontWeight.normal,
),
);
}
/// 小文字,返回 Text
/// [text]: 文本内容
/// [color]: 文本颜色,默认灰色
/// [fontSize]: 字体大小默认12.0
/// [bold]: 是否加粗默认false
static Text smallText(
String text, {
Color color = Colors.black54,
double fontSize = 12.0,
bool bold = false,
}) {
return Text(
text,
style: TextStyle(
color: color,
fontSize: fontSize,
fontWeight: bold ? FontWeight.bold : FontWeight.normal,
),
);
}
}
/// 版本信息模型类
class AppVersionInfo {
final String versionName; // 版本名称(如 1.0.0
final String buildNumber; // 构建号(如 1
final String fullVersion; // 完整版本(如 1.0.0+1
AppVersionInfo({
required this.versionName,
required this.buildNumber,
required this.fullVersion,
});
@override
String toString() {
return fullVersion;
}
}
// 获取应用版本信息的方法
Future<AppVersionInfo> getAppVersion() async {
try {
final packageInfo = await PackageInfo.fromPlatform();
return AppVersionInfo(
versionName: packageInfo.version,
buildNumber: packageInfo.buildNumber,
fullVersion: '${packageInfo.version}+${packageInfo.buildNumber}',
);
} catch (e) {
// 获取失败时返回默认值
return AppVersionInfo(
versionName: '1.0.0',
buildNumber: '1',
fullVersion: '1.0.0+0',
);
}
}
/// ------------------------------------------------------
/// 全局会话管理
/// ------------------------------------------------------
class SessionService {
SessionService._();
static final SessionService instance = SessionService._();
String? corpinfoId;
String? loginUserId;
Map<String, dynamic>? loginUser;
String? deptId;
String? deptLevel;
String? postId;
String? username;
String? version;
String? basePath;
String? isRest;
List<dynamic>? permission;
bool updateInfo = false;
String? dangerJson;
String? riskJson;
String? departmentJsonStr;
String? departmentHiddenTypeJsonStr;
String? customRecordDangerJson;
String? unqualifiedInspectionItemID;
String? listItemNameJson;
/// 如果以下任何一项为空,则跳转到登录页
void loginSession(BuildContext context) {
if (corpinfoId == null || loginUserId == null || loginUser == null) {
Navigator.pushReplacementNamed(context, '/login');
}
}
// setters
void setLoginUser(Map<String, dynamic> user) => loginUser = user;
void setLoginUserId(String id) => loginUserId = id;
void setCorpinfoId(String id) => corpinfoId = id;
void setDeptId(String id) => deptId = id;
void setDeptLevel(String level) => deptLevel = level;
void setPostId(String id) => postId = id;
void setUsername(String name) => username = name;
void setVersion(String ver) => version = ver;
void setBasePath(String url) => basePath = url;
void setIsRest(String rest) => isRest = rest;
void setPermission(List<dynamic> list) => permission = list;
void setUpdateInfo(bool flag) => updateInfo = flag;
void setDangerWaitInfo(String json) => dangerJson = json;
void setRiskWaitInfo(String json) => riskJson = json;
void setDepartmentJsonStr(String json) => departmentJsonStr = json;
void setCustomRecordDangerJson(String json) => customRecordDangerJson = json;
void setUnqualifiedInspectionItemIDJson(String json) => unqualifiedInspectionItemID = json;
void setListItemNameJson(String json) => listItemNameJson = json;
}
/// ------------------------------------------------------
/// 日期格式化
/// ------------------------------------------------------
String formatDate(DateTime? date, String fmt) {
if (date == null) return '';
String twoDigits(int n) => n.toString().padLeft(2, '0');
final replacements = <String, String>{
'yyyy': date.year.toString(),
'yy': date.year.toString().substring(2),
'MM': twoDigits(date.month),
'M': date.month.toString(),
'dd': twoDigits(date.day),
'd': date.day.toString(),
'hh': twoDigits(date.hour),
'h': date.hour.toString(),
'mm': twoDigits(date.minute),
'm': date.minute.toString(),
'ss': twoDigits(date.second),
's': date.second.toString(),
};
String result = fmt;
replacements.forEach((key, value) {
result = result.replaceAllMapped(RegExp(key), (_) => value);
});
return result;
}
/// ------------------------------------------------------
/// 防多次点击
/// ------------------------------------------------------
class ClickUtil {
ClickUtil._();
static bool _canClick = true;
/// 调用示例:
/// ClickUtil.noMultipleClicks(() { /* your code */ });
static void noMultipleClicks(VoidCallback fn, {int delayMs = 2000}) {
if (_canClick) {
_canClick = false;
fn();
Future.delayed(Duration(milliseconds: delayMs), () {
_canClick = true;
});
} else {
debugPrint('请稍后点击');
}
}
}
void presentPage(BuildContext context, Widget page) {
Navigator.push(
context,
MaterialPageRoute(fullscreenDialog: true, builder: (_) => page),
);
}
class LoadingDialogHelper {
// 显示加载框
static void show({String? message}) {
if (message != null) {
EasyLoading.show(status: message);
} else {
EasyLoading.show();
}
}
// 隐藏加载框
static void hide() {
if (EasyLoading.isShow) {
EasyLoading.dismiss();
}
}
}
/// 将秒数转换为 “HH:MM:SS” 格式
String secondsCount(dynamic seconds) {
// 先尝试解析出一个 double 值
double totalSeconds;
if (seconds == null) {
totalSeconds = 0;
} else if (seconds is num) {
totalSeconds = seconds.toDouble();
} else {
// seconds 是字符串或其他,尝试 parse
totalSeconds = double.tryParse(seconds.toString()) ?? 0.0;
}
// 取整秒,向下取整
final int secs = totalSeconds.floor();
final int h = (secs ~/ 3600) % 24;
final int m = (secs ~/ 60) % 60;
final int s = secs % 60;
// padLeft 保证两位数
final String hh = h.toString().padLeft(2, '0');
final String mm = m.toString().padLeft(2, '0');
final String ss = s.toString().padLeft(2, '0');
return '$hh:$mm:$ss';
}
void printLongString(String text, {int chunkSize = 800}) {
final pattern = RegExp('.{1,$chunkSize}'); // 每 chunkSize 个字符一组
for (final match in pattern.allMatches(text)) {
print(match.group(0));
}
}
/// 表单处理
class FormUtils {
/// 判断 [data] 中的 [key] 是否存在“有效值”:
/// - key 不存在或值为 null -> false
/// - String去掉首尾空白后非空 -> true
/// - Iterable / Map非空 -> true
/// - 其它类型int、double、bool 等)只要不为 null 就算有值 -> true
static bool hasValue(Map<String, dynamic> data, String key) {
if (!data.containsKey(key)) return false;
final val = data[key];
if (val == null) return false;
if (val is String) {
return val.trim().isNotEmpty;
}
if (val is Iterable || val is Map) {
return val.isNotEmpty;
}
// 数字、布尔等其它非空即可
return true;
}
/// 在list中根据一个 keyvalue找到对应的map
static Map findMapForKeyValue(List list,String key, String value) {
Map target = list.firstWhere(
(item) => item[key] == value,
orElse: () => {},
);
return target ?? {};
}
}
class NoDataWidget {
static Widget show() {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.asset('assets/images/null.png', width: 200,),
Text('暂无数据', style: TextStyle(color: Colors.grey)),
],
),
);
}
}