first commit

This commit is contained in:
编码猿
2024-09-27 01:31:25 +08:00
commit 07c46ac300
558 changed files with 37414 additions and 0 deletions

View File

@@ -0,0 +1 @@
3ab93c5c-ff68-4b41-87a2-fbcbc04b6bdd

View File

@@ -0,0 +1,74 @@
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,119 @@
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';
/*
* 检测新版本
*/
class CheckUpdate {
// 保存升级弹窗
UpdateDialog _dialog;
double _progress = 0.0;
File _apkFile;
Future<bool> check(BuildContext context) async {
// 检查版本
UpdateVersionEntity res = await HomeService.update(params: {});
// 如果需要升级
if (int.parse(Config.packageInfo.buildNumber) < res.versionCode) {
if (_dialog != null && _dialog.isShowing()) {
return false;
}
// 升级的内容信息
String updateContent = "";
res.updateMsg.forEach((v) => updateContent = updateContent + "${v}\n");
// 显示弹窗
_dialog = UpdateDialog.showUpdate(context,
title: "发现新版本v${res.version},请升级!",
updateContent: updateContent,
width: 250,
topImage: Image.asset(R.libStaticImgUpdateBgAppTopPng),
themeColor: ColorConfig.ThemeColor,
updateButtonText: '升级',
isForce: true,
onUpdate: () async {
// 如果是android 那么下载app
if (Config.isAndroid) {
// 获取临时下载地址
_apkFile = await getApkFileByUpdateEntity(res);
await onUpdate(res);
// 如果是ios 那么打开appstore
} else {
InstallPlugin.gotoAppStore(Config.iosDownApkUrl);
}
}
);
return true;
} else {
return false;
}
}
// 下载文件,更新进度条
Future<void> onUpdate(UpdateVersionEntity res) async {
await HttpApi().downloadFile(
res.downUrl, _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(UpdateVersionEntity res) async {
// 获取app文件名
String appName = getApkNameByDownloadUrl(res.downUrl);
// 获取下载的缓存路径
String dirPath = await getDownloadDirPath();
return File("$dirPath/${res.versionCode}/$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,101 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_modular/flutter_modular.dart';
import 'package:peach/config/Colors.dart';
import 'package:peach/entity/_.dart';
import 'package:peach/service/_.dart';
import '_.dart';
/*
* 核心的utils主要封装UI相关的操作
*/
class Core {
static FreeUseEntity freeUseStatus;
/// 修改状态栏颜色
static void SetStatusThemeColor({Color color : ColorConfig.ThemeColor}) {
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
statusBarColor: ColorConfig.ThemeColor
));
}
static void deleteDialog(BuildContext context, Function callback,{ String content: "确认删除该收藏吗?" }) async {
return await showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text('提示'),
content: Text(content),
actions: <Widget>[
FlatButton(
child: Text('取消',style: TextStyle(color: ColorConfig.NoActiveColor),),
onPressed: () {
Navigator.of(context).pop();
}
),
FlatButton(
child: Text('确认',style: TextStyle(color: ColorConfig.ThemeColor),),
onPressed: () async {
callback();
Navigator.of(context).pop();
}
),
],
);
});
}
/// 调用接口,减少免费试看的次数
static Future<FreeUseEntity> freeUse(BuildContext context, Function vipCallBack) async {
freeUseStatus = await UserService.freeUse(params: { 'objectId': Tool.userInfo()['objectId'] });
// 如果已经没有免费试看的次数了,弹窗提醒
if (freeUseStatus.freeNumber == 0) {
await showDialog(
context: context,
builder: (context) {
return WillPopScope(
onWillPop: () async => false,
child: AlertDialog(
title: Text('温馨提示'),
content: Text("免费体验到期请开通VIP享受更多特权和功能"),
actions: <Widget>[
FlatButton(
child: Text('取消',style: TextStyle(color: ColorConfig.NoActiveColor),),
onPressed: () {
Modular.to.pop();
Modular.to.pop();
}
),
FlatButton(
child: Text('开通VIP',style: TextStyle(color: ColorConfig.ThemeColor),),
onPressed: () async {
Modular.to.pushNamed('/vip');
}
),
],
),
);
});
} else {
vipCallBack();
}
}
// -1 表示已经开通了vip
static bool isVip(BuildContext context) {
print("freeUseStatus.freeNumber ======= ${freeUseStatus.freeNumber}");
if (freeUseStatus.freeNumber == -1) {
return true;
} else {
return false;
}
}
/// 复制文字到剪切板
static void copy (String message) {
Clipboard.setData(ClipboardData(text: message));
}
}

View File

@@ -0,0 +1,160 @@
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,
);
}
static Icon ModelIcon ({double size = 24.0, Color color = ColorConfig.WhiteBackColor}) {
return Icon(
const IconData(0xe61f, fontFamily: 'iconfont'),
size: size,
color: color,
);
}
static Icon MeIcon ({double size = 24.0, Color color = ColorConfig.WhiteBackColor}) {
return Icon(
const IconData(0xe611, fontFamily: 'iconfont'),
size: size,
color: color,
);
}
static Icon MechanismIcon ({double size = 24.0, Color color = ColorConfig.WhiteBackColor}) {
return Icon(
const IconData(0xe61a, fontFamily: 'iconfont'),
size: size,
color: color,
);
}
static Icon HomeIcon ({double size = 24.0, Color color = ColorConfig.WhiteBackColor}) {
return Icon(
const IconData(0xe617, fontFamily: 'iconfont'),
size: size,
color: color,
);
}
static Icon HistoryIcon ({double size = 24.0, Color color = ColorConfig.WhiteBackColor}) {
return Icon(
const IconData(0xe600, fontFamily: 'iconfont'),
size: size,
color: color,
);
}
static Icon VipIcon ({double size = 24.0, Color color = ColorConfig.TextColor}) {
return Icon(
const IconData(0xe6ba, fontFamily: 'iconfont'),
size: size,
color: color,
);
}
static Icon DaLiIcon ({double size = 24.0, Color color = ColorConfig.TextColor}) {
return Icon(
const IconData(0xe618, fontFamily: 'iconfont'),
size: size,
color: color,
);
}
static Icon UpdateIcon ({double size = 24.0, Color color = ColorConfig.TextColor}) {
return Icon(
const IconData(0xe63c, fontFamily: 'iconfont'),
size: size,
color: color,
);
}
static Icon ClearIcon ({double size = 22.0, Color color = ColorConfig.TextColor}) {
return Icon(
const IconData(0xe616, fontFamily: 'iconfont'),
size: size,
color: color,
);
}
static Icon XieYiIcon ({double size = 22.0, Color color = ColorConfig.TextColor}) {
return Icon(
const IconData(0xe6b2, fontFamily: 'iconfont'),
size: size,
color: color,
);
}
static Icon AboutIcon ({double size = 22.0, Color color = ColorConfig.TextColor}) {
return Icon(
const IconData(0xe637, fontFamily: 'iconfont'),
size: size,
color: color,
);
}
static Icon NewsIcon ({double size = 22.0, Color color = ColorConfig.TextColor}) {
return Icon(
const IconData(0xe6c0, fontFamily: 'iconfont'),
size: size,
color: color,
);
}
static Icon VideoIcon ({double size = 22.0, Color color = ColorConfig.TextColor}) {
return Icon(
const IconData(0xe60c, fontFamily: 'iconfont'),
size: size,
color: color,
);
}
static Icon PictureIcon ({double size = 20.0, Color color = ColorConfig.TextColor}) {
return Icon(
const IconData(0xe61e, fontFamily: 'iconfont'),
size: size,
color: color,
);
}
static Icon BuyIcon ({double size = 20.0, Color color = ColorConfig.TextColor}) {
return Icon(
const IconData(0xe73b, fontFamily: 'iconfont'),
size: size,
color: color,
);
}
static Icon StatusIcon ({double size = 20.0, Color color = ColorConfig.TextColor}) {
return Icon(
const IconData(0xe655, fontFamily: 'iconfont'),
size: size,
color: color,
);
}
static Icon OrderIcon ({double size = 20.0, Color color = ColorConfig.TextColor}) {
return Icon(
const IconData(0xe620, fontFamily: 'iconfont'),
size: size,
color: color,
);
}
static Icon WeiXinIcon ({double size = 20.0, Color color = ColorConfig.TextColor}) {
return Icon(
const IconData(0xe64f, fontFamily: 'iconfont'),
size: size,
color: color,
);
}
}

View File

@@ -0,0 +1,42 @@
import 'package:jpush_flutter/jpush_flutter.dart';
import 'package:peach/config/_.dart';
/*
* 极光消息推送
*/
class JiGuangPush {
JPush _jpush;
static JiGuangPush _instance = JiGuangPush.instance();
factory JiGuangPush() => _instance;
JiGuangPush.instance() {
if (null == _jpush) {
_jpush = new JPush();
addEventHandler();
_jpush.setup(
appKey: Config.JgConfig['appKey'],
channel: Config.JgConfig['channel'],
production: Config.JgConfig['production'],
debug: Config.JgConfig['debug'],
);
}
}
addEventHandler() {
_jpush.addEventHandler(
// 接收通知回调方法。
onReceiveNotification: (Map<String, dynamic> message) async {
print("收到的消息为:: $message");
},
// 点击通知回调方法。
onOpenNotification: (Map<String, dynamic> message) async {
print("消息被点击了: $message");
},
// 接收自定义消息回调方法。
onReceiveMessage: (Map<String, dynamic> message) async {
print("flutter onReceiveMessage: $message");
},
);
}
}

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, allowFontScalingSelf: true);
}
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,55 @@
import 'package:flutter/material.dart';
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,105 @@
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);
}
}

11
untitled/lib/utils/_.dart Normal file
View File

@@ -0,0 +1,11 @@
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';
export 'JiGuangPush.dart';