first commit

This commit is contained in:
编码猿
2024-09-27 01:32:49 +08:00
commit 28ebe05a64
7399 changed files with 1174529 additions and 0 deletions

View File

@@ -0,0 +1 @@
c443c883-414a-4e80-b0c1-168bc79f4c8b

View File

@@ -0,0 +1,87 @@
import 'package:flutter/material.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:peach/config/_.dart';
/*
* 动态申请App的权限
*/
class AuthorityApplication {
/// App需要动态申请的权限
static List<Permission> permissionList = [
Permission.storage,
Permission.photos
];
static Future<bool> init(BuildContext context) async {
if (Config.isAndroid) {
Map<Permission, PermissionStatus> status = await permissionList.request();
if (status[Permission.storage].isGranted) {
print("用户同意了权限");
return true;
} else if (status[Permission.storage].isDenied) {
print("用户拒绝了权限");
AuthorityApplication.ShowTips(
context: context,
content: "请允许App获取权限否则App功能不能正常使用",
isShowcancel: false,
confirmCall: () async {
AuthorityApplication.init(context);
},
);
return false;
} else if (status[Permission.storage].isPermanentlyDenied) {
print("用户永久拒绝了权限");
AuthorityApplication.ShowTips(
context: context,
content: "您禁用了应用的必要权限,请到设置里开启!",
isShowcancel: false,
confirmText: '打开设置',
confirmCall: () async {
await openAppSettings();
},
);
return false;
}
}
}
static Future ShowTips(
{BuildContext context,
String content,
bool isShowcancel: true,
Function confirmCall,
confirmText = "重新请求",
title = '提示'}) async {
await showDialog(
context: context,
barrierDismissible: false,
builder: (context) => WillPopScope(
onWillPop: () async => false,
child: AlertDialog(
title: Text(title),
content: Text(content),
actions: <Widget>[
isShowcancel
? FlatButton(
child: Text(
'取消',
style: TextStyle(color: ColorConfig.NoActiveColor),
),
onPressed: () {
Navigator.of(context).pop();
})
: Text(''),
FlatButton(
child: Text(
confirmText,
style: TextStyle(color: ColorConfig.ThemeColor),
),
onPressed: () async {
confirmCall();
Navigator.of(context).pop();
}),
],
),
));
}
}

View File

@@ -0,0 +1,94 @@
import 'dart:io';
import 'package:path_provider/path_provider.dart';
/*
* 计算清除缓存
*/
class ClearCache {
///加载缓存
static Future<String> loadCache() async {
try {
Directory tempDir = await getTemporaryDirectory();
double value = await ClearCache._getTotalSizeOfFilesInDir(tempDir);
// tempDir.list(followLinks: false,recursive: true).listen((file){
// //打印每个缓存文件的路径
// print(file.path);
// });
return ClearCache._renderSize(value);
} catch (err) {
print(err);
}
}
// 清理缓存
static Future<bool> clearCache() async {
//此处展示加载loading
try {
Directory tempDir = await getTemporaryDirectory();
//删除缓存目录
await ClearCache.delDir(tempDir);
await ClearCache.loadCache();
return true;
} catch (e) {
print(e);
return false;
} finally {
//此处隐藏加载loading
}
}
/// 递归方式 计算文件的大小
static Future<double> _getTotalSizeOfFilesInDir(final FileSystemEntity file) async {
try {
if (file is File) {
int length = await file.length();
return double.parse(length.toString());
}
if (file is Directory) {
final List<FileSystemEntity> children = file.listSync();
double total = 0;
if (children != null)
for (final FileSystemEntity child in children)
total += await ClearCache._getTotalSizeOfFilesInDir(child);
return total;
}
return 0;
} catch (e) {
print(e);
return 0;
}
}
///递归方式删除目录
static Future<Null> delDir(FileSystemEntity file) async {
try {
if (file is Directory) {
final List<FileSystemEntity> children = file.listSync();
for (final FileSystemEntity child in children) {
await delDir(child);
}
}
await file.delete();
} catch (e) {
print(e);
}
}
/// 格式化文件大小
static String _renderSize(double value) {
if (null == value) {
return '0';
}
List<String> unitArr = List()..add('B')..add('K')..add('M')..add('G');
int index = 0;
while (value > 1024) {
index++;
value = value / 1024;
// value = value / 8024;
}
String size = value.toStringAsFixed(2);
return size + unitArr[index];
}
}

View File

@@ -0,0 +1,128 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_update_dialog/update_dialog.dart';
import 'package:install_plugin/install_plugin.dart';
import 'package:path_provider/path_provider.dart';
import 'package:peach/R.dart';
import 'package:peach/config/_.dart';
import 'package:peach/entity/_.dart';
import 'package:peach/http/Dio.dart';
import 'package:peach/service/_.dart';
import 'package:peach/utils/_.dart';
/*
* 检测新版本
*/
class CheckUpdate {
// 保存升级弹窗
UpdateDialog _dialog;
double _progress = 0.0;
bool force; // false 不强制升级 true 强制升级
File _apkFile;
Future<bool> check(BuildContext context) async {
// 检查版本
Data res = await PublicService.update(params: {});
if (res.updateForce == 0) {
force = false;
} else {
force = true;
}
// 如果需要升级
if (int.parse(Config.packageInfo.buildNumber) < res.updateVersionCode) {
if (_dialog != null && _dialog.isShowing()) {
return false;
}
// 显示弹窗
_dialog = UpdateDialog.showUpdate(context,
title: "发现新版本 v${res.updateVersion},请升级!",
updateContent: res.updateContent,
width: Screen.setWidth(280),
topImage: Image.asset(R.libStaticImgUpdateBgAppTopPng),
themeColor: ColorConfig.ThemeColor,
updateButtonText: '升级到最新版',
ignoreButtonText: '忽略',
enableIgnore: !force, // true 可以忽略,不强制升级
onIgnore: () {
_dialog.dismiss();
},
isForce: force, // false 显示关闭按钮 不强制升级
onUpdate: () async {
// 如果是android 那么下载app
if (Config.isAndroid) {
print("如果是android 那么下载app");
// 获取临时下载地址
_apkFile = await getApkFileByUpdateEntity(res);
await onUpdate(res);
// 如果是ios 那么打开appstore
} else {
InstallPlugin.gotoAppStore(Config.iosDownApkUrl);
}
}
);
return true;
} else {
return false;
}
}
// 下载文件,更新进度条
Future<void> onUpdate(Data res) async {
await HttpApi().downloadFile(
res.updateDownUrl, _apkFile.path,
onReceiveProgress: (int count, int total) {
_progress = count.toDouble() / total;
if (_progress <= 1.0001) {
_dialog.update(_progress);
}
}).then((value) {
_dialog.dismiss();
installAPP();
}).catchError((value) {
_dialog.dismiss();
});
}
/// android 安装app
void installAPP() async {
String packageName = Config.packageInfo.packageName;
InstallPlugin.installApk(_apkFile.path, packageName);
}
/// 根据更新信息获取apk安装文件
Future<File> getApkFileByUpdateEntity(Data res) async {
// 获取app文件名
String appName = getApkNameByDownloadUrl(res.updateDownUrl);
// 获取下载的缓存路径
String dirPath = await getDownloadDirPath();
return File("$dirPath/${res.updateVersion}/$appName");
}
///获取下载缓存路径
Future<String> getDownloadDirPath() async {
Directory directory = Config.isAndroid
? await getExternalStorageDirectory()
: await getApplicationDocumentsDirectory();
return directory.path;
}
///根据下载地址获取文件名
String getApkNameByDownloadUrl(String downloadUrl) {
if (downloadUrl.isEmpty) {
return "temp_${currentTimeMillis()}.apk";
} else {
String appName = downloadUrl.substring(downloadUrl.lastIndexOf("/") + 1);
if (!appName.endsWith(".apk")) {
appName = "temp_${currentTimeMillis()}.apk";
}
return appName;
}
}
/// 返回随机文件名
int currentTimeMillis() {
return DateTime.now().millisecondsSinceEpoch;
}
}

View File

@@ -0,0 +1,20 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
/*
* 核心的utils主要封装UI相关的操作
*/
class Core {
//修改状态栏颜色
static void barColor(Color color) {
SystemUiOverlayStyle uiStyle = SystemUiOverlayStyle.light.copyWith(
statusBarColor: color,
);
SystemChrome.setSystemUIOverlayStyle(uiStyle);
}
/// 复制文字到剪切板
static void copy(String message) {
Clipboard.setData(ClipboardData(text: message));
}
}

View File

@@ -0,0 +1,16 @@
import 'package:flutter/material.dart';
import 'package:peach/config/_.dart';
/*
* IconFont 字体图标
*/
class IconFont {
static Icon LogoIcon(
{double size = 24.0, Color color = ColorConfig.WhiteBackColor}) {
return Icon(
const IconData(0xe61c, fontFamily: 'iconfont'),
size: size,
color: color,
);
}
}

View File

@@ -0,0 +1,27 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
/*
* 尺寸兼容类似前端的rem
*/
class Screen {
static double setWidth(double width) {
return ScreenUtil().setWidth(width);
}
static double setHeight(double height) {
return ScreenUtil().setHeight(height);
}
static double setFontSize(double Size) {
return ScreenUtil().setSp(Size);
}
static double width(BuildContext context) {
return MediaQuery.of(context).size.width;
}
static double height(BuildContext context) {
return MediaQuery.of(context).size.height;
}
}

View File

@@ -0,0 +1,51 @@
import 'package:shared_preferences/shared_preferences.dart';
/*
* shared_preferences 配置
*/
class SPreferences {
static final SPreferences _instance = SPreferences._();
factory SPreferences() => _instance;
SPreferences._();
static SharedPreferences _prefs;
static Future<void> init() async {
if (_prefs == null) {
_prefs = await SharedPreferences.getInstance();
}
}
// 设置数字类型
Future<bool> setInt(String key, int value) async {
return await _prefs.setInt(key, value);
}
// 设置bool
Future<bool> setBool(String key, bool value) async {
return await _prefs.setBool(key, value);
}
// 设置String
Future<bool> setString(String key, String value) async {
return await _prefs.setString(key, value);
}
String getString(String key) {
return _prefs.getString(key);
}
bool getIsLogin() {
if (_prefs.containsKey("isLogin")) {
return _prefs.getBool("isLogin");
}
return false;
}
bool getBool(String key) {
if (!(_prefs.containsKey(key))) {
_prefs.setBool(key, true);
return false;
}
return _prefs.getBool(key);
}
}

View File

@@ -0,0 +1,200 @@
import 'dart:async';
import 'dart:convert';
import 'package:convert/convert.dart';
import 'package:crypto/crypto.dart';
import 'dart:io';
import 'dart:math';
import 'package:path_provider/path_provider.dart';
import 'package:peach/config/_.dart';
import 'package:peach/utils/_.dart';
/*
* 工具函数主要给dart逻辑使用
*/
class Tool {
/// 按照指定下标将数组分割为二维数组
static List<List<T>> splitList<T>(List<T> list, int len) {
if (len <= 1) {
return [list];
}
List<List<T>> result = List();
int index = 1;
while (true) {
if (index * len < list.length) {
List<T> temp = list.skip((index - 1) * len).take(len).toList();
result.add(temp);
index++;
continue;
}
List<T> temp = list.skip((index - 1) * len).toList();
result.add(temp);
break;
}
return result;
}
/// 生成N位随机数
static String randomBit([int len = 15]) {
String scopeF = '123456789'; //首位
String scopeC = '0123456789'; //中间
String result = '';
for (int i = 0; i < len; i++) {
if (i == 0) {
result = scopeF[Random().nextInt(scopeF.length)];
} else {
result = result + scopeC[Random().nextInt(scopeC.length)];
}
}
return result;
}
/// 检查用户是否有权限打开【单手模式】
/// 权限规则:
/// 1对弹窗给的 androidid 进行 MD5 加密
/// 2在 com.example.untitled/files 文件夹中 用第一步的密文来创建文件
/// 3向文件中 写入 设备的 androidid
/// 通过验证,正常访问..
static Future<bool> checkIsOpen() async {
String androidId = Config.androidDeviceInfo.androidId;
Directory filesPath = await getExternalStorageDirectory();
File completePath = File("${filesPath.path}/${generateMd5(androidId)}");
if (completePath.existsSync()) {
String textMessage = await completePath.readAsString();
return textMessage == androidId ? true : false;
} else {
return false;
}
}
/*
* md5 加密
*/
static String generateMd5(String data) {
var content = new Utf8Encoder().convert(data);
var digest = md5.convert(content);
// 这里其实就是 digest.toString()
return hex.encode(digest.bytes);
}
/// 从本地读取用户信息
static Map userInfo() {
String username = SPreferences().getString("username");
String objectId = SPreferences().getString("objectId");
String createdAt = SPreferences().getString("createdAt");
String userType = SPreferences().getString("userType");
String userWeiXin = SPreferences().getString("userWeiXin");
Map info = new Map();
info.addAll({
'username': username,
'objectId': objectId,
'createdAt': createdAt,
'userType': userType,
'userWeiXin': userWeiXin,
});
return info;
}
/// 验证是否为合法的手机号
static bool isPhone(String str) {
return new RegExp(
'^((13[0-9])|(15[^4])|(166)|(17[0-8])|(18[0-9])|(19[8-9])|(147,145))\\d{8}\$')
.hasMatch(str);
}
// 防抖
// // const Duration(milliseconds: 2000)
static debounce(Function func, Duration mill) {
Timer timer;
Duration delay = mill;
Function target = () {
if (timer?.isActive ?? false) {
timer?.cancel();
}
timer = Timer(delay, () {
func?.call();
});
};
return target;
}
/* 时间戳转字符串
* timestamp 时间戳
* formart "y-m":年和月之间的符号,
* "m-d":月和日之间的符号
* "h-m":时和分之间的符号,
* "m-s":分和秒之间的符号;
* "m-a":是否显示上午和下午
*/
static String dateAndTimeToString(var timestamp,
{Map<String, String> formart}) {
if (timestamp == null || timestamp == "") {
return "";
}
String targetString = "";
final date = new DateTime.fromMicrosecondsSinceEpoch(timestamp * 1000);
// final String tmp = date.toString();
String year = date.year.toString();
String month = date.month.toString();
if (date.month <= 9) {
month = "0" + month;
}
String day = date.day.toString();
if (date.day <= 9) {
day = "0" + day;
}
String hour = date.hour.toString();
if (date.hour <= 9) {
hour = "0" + hour;
}
String minute = date.minute.toString();
if (date.minute <= 9) {
minute = "0" + minute;
}
String second = date.second.toString();
if (date.second <= 9) {
second = "0" + second;
}
// String millisecond = date.millisecond.toString();
String morningOrafternoon = "上午";
if (date.hour >= 12) {
morningOrafternoon = "下午";
}
if (formart["y-m"] != null && formart["m-d"] != null) {
targetString = year + formart["y-m"] + month + formart["m-d"] + day;
} else if (formart["y-m"] == null && formart["m-d"] != null) {
targetString = month + formart["m-d"] + day;
} else if (formart["y-m"] != null && formart["m-d"] == null) {
targetString = year + formart["y-m"] + month;
}
targetString += " ";
if (formart["m-a"] != null) {
targetString += morningOrafternoon + " ";
}
if (formart["h-m"] != null && formart["m-s"] != null) {
targetString += hour + formart["h-m"] + minute + formart["m-s"] + second;
} else if (formart["h-m"] == null && formart["m-s"] != null) {
targetString += minute + formart["m-s"] + second;
} else if (formart["h-m"] != null && formart["m-s"] == null) {
targetString += hour + formart["h-m"] + minute;
}
return targetString;
}
/*
* 2021-05-22T10:37:06.000+00:00 => 1621679826000
* 把标准时间格式转换成时间戳
*/
static int timeToStamp(String str) {
String _time = str;
int _intendtime = DateTime.parse(_time).millisecondsSinceEpoch;
return _intendtime;
}
}

View File

@@ -0,0 +1,10 @@
library utils;
export 'Screen.dart';
export 'IconFont.dart';
export 'Core.dart';
export 'Tool.dart';
export 'AuthorityApplication.dart';
export 'CLearCache.dart';
export 'SharedPreferences.dart';
export 'CheckUpdate.dart';