diff --git a/.gitignore b/.gitignore index 2c3d1f0..ea828da 100644 --- a/.gitignore +++ b/.gitignore @@ -52,3 +52,4 @@ making_school_asignment_app/lib/page/home_page/children/read_over/read_over_view making_school_asignment_app/lib/common/api/retrofit_client.g.dart making_school_asignment_app/lib/page/home_page/children/read_over/read_over_view.g.dart .vscode/settings.json +.vscode/launch.json diff --git a/making_school_asignment_app/android/app/src/main/AndroidManifest.xml b/making_school_asignment_app/android/app/src/main/AndroidManifest.xml index c0d0fae..1ff64ab 100644 --- a/making_school_asignment_app/android/app/src/main/AndroidManifest.xml +++ b/making_school_asignment_app/android/app/src/main/AndroidManifest.xml @@ -31,6 +31,15 @@ + + + + + diff --git a/making_school_asignment_app/android/app/src/main/res/xml/file_paths.xml b/making_school_asignment_app/android/app/src/main/res/xml/file_paths.xml new file mode 100644 index 0000000..b6480f6 --- /dev/null +++ b/making_school_asignment_app/android/app/src/main/res/xml/file_paths.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/making_school_asignment_app/lib/common/api/retrofit_client.dart b/making_school_asignment_app/lib/common/api/retrofit_client.dart index df8e36c..e803f76 100644 --- a/making_school_asignment_app/lib/common/api/retrofit_client.dart +++ b/making_school_asignment_app/lib/common/api/retrofit_client.dart @@ -1,4 +1,5 @@ import 'package:dio/dio.dart' hide Headers; +import 'package:making_school_asignment_app/common/job/app_version.dart'; import 'package:making_school_asignment_app/common/job/marking_models/do_paper_details_param.dart'; import 'package:making_school_asignment_app/common/job/marking_models/do_paper_details_result.dart'; import 'package:making_school_asignment_app/common/job/marking_models/favor_param.dart'; @@ -137,4 +138,8 @@ abstract class RetrofitClient { // OSS 上传key @GET("/api/infra/Oss/GetPresignedUri") Future getOssPresignedUri(@Query('key') String key); + + // 获取APP 版本 + @GET("/api/infra/AppVersion/Get") + Future getLastAppVersion(@Query('appName') String appName, @Query('ftuType') int ftuType); // ftuType 1安卓 2IOS } diff --git a/making_school_asignment_app/lib/common/config/request_config.dart b/making_school_asignment_app/lib/common/config/request_config.dart index 3a04545..32cc6e6 100644 --- a/making_school_asignment_app/lib/common/config/request_config.dart +++ b/making_school_asignment_app/lib/common/config/request_config.dart @@ -11,7 +11,7 @@ import 'package:making_school_asignment_app/common/job/common/base_page.dart'; class RequestConfig { static const _devBaseUrl = "http://192.168.2.119:1091"; // 开发 static const _proBaseUrl = "https://dpc-teacher-api.23544.com"; // 生产 - static const imgUrl = 'https://dpcjob.oss-cn-beijing.aliyuncs.com/'; + static const imgUrl = 'https://dpc-job-oss.23544.com/'; static RequestConfig? _instance; String baseUrl; diff --git a/making_school_asignment_app/lib/common/job/app_version.dart b/making_school_asignment_app/lib/common/job/app_version.dart new file mode 100644 index 0000000..aa8de30 --- /dev/null +++ b/making_school_asignment_app/lib/common/job/app_version.dart @@ -0,0 +1,53 @@ +import 'package:json_annotation/json_annotation.dart'; + +import '../config/request_config.dart'; + +part 'app_version.g.dart'; + +@JsonSerializable() +class AppVersion extends Object { + // @JsonKey(name: 'id') + // String id; + + // @JsonKey(name: 'creatorId') + // int creatorId; + + // @JsonKey(name: 'creatorName') + // String creatorName; + + // @JsonKey(name: 'creationTime') + // String creationTime; + + @JsonKey(name: 'appName') + String appName; + + @JsonKey(name: 'version') + String version; + + @JsonKey(name: 'ftuType') + int ftuType; + + @JsonKey(name: 'downloadUrl') + String downloadUrl; + + @JsonKey(name: 'description') + String? description; + + AppVersion( + // this.id, + // this.creatorId, + // this.creatorName, + // this.creationTime, + this.appName, + this.version, + this.ftuType, + this.downloadUrl, + this.description, + ) { + downloadUrl = RequestConfig.imgUrl + downloadUrl; + } + + factory AppVersion.fromJson(Map srcJson) => _$AppVersionFromJson(srcJson); + + Map toJson() => _$AppVersionToJson(this); +} diff --git a/making_school_asignment_app/lib/common/request/rest_dio.dart b/making_school_asignment_app/lib/common/request/rest_dio.dart index 49c3e8d..e94eba6 100644 --- a/making_school_asignment_app/lib/common/request/rest_dio.dart +++ b/making_school_asignment_app/lib/common/request/rest_dio.dart @@ -11,6 +11,7 @@ import 'package:making_school_asignment_app/common/utils/toast_utils.dart'; import 'package:making_school_asignment_app/routes/app_pages.dart'; import '../job/user_info_detail.dart'; +import '../utils/storage.dart'; class RequestTool { static late Dio _dio; @@ -168,7 +169,11 @@ class TheError extends Interceptor { case 401: message = '用户登录失效,请重新登录'; - Future.delayed(const Duration(seconds: 2), () => getx.Get.offAllNamed(Routes.login)); + Future.delayed(const Duration(seconds: 2), () { + UserStore.to.erase(); + StorageService.to.erase(); + getx.Get.offAllNamed(Routes.login); + }); break; case 404: // message = '用户登录失效,请重新登录'; diff --git a/making_school_asignment_app/lib/common/utils/app_upgrade/DownloadApk.dart b/making_school_asignment_app/lib/common/utils/app_upgrade/DownloadApk.dart new file mode 100644 index 0000000..38dfe18 --- /dev/null +++ b/making_school_asignment_app/lib/common/utils/app_upgrade/DownloadApk.dart @@ -0,0 +1,149 @@ +/* + * @Descripttion: 下载APK + * @version: DownloadApk + * @Author: wy + * @Date: 2020-07-30 15:54:40 + * @LastEditors: wangyang 1147192855@qq.com + * @LastEditTime: 2022-08-02 15:12:21 + */ +import 'dart:io'; + +import 'package:dio/dio.dart'; +import 'package:flutter/material.dart'; +import 'package:making_school_asignment_app/common/utils/utils.dart'; +import 'package:path_provider/path_provider.dart'; +import 'package:app_installer/app_installer.dart'; +import 'package:url_launcher/url_launcher.dart'; + +import 'UpgradePermission.dart'; +import 'model/UpdateAppEvent.dart'; +import 'upgradeLogic.dart'; + +class DownloadApk { + /// 下载安卓更新包 + static Future _downloadAndroid(context, UpdateAppEvent event, UpgradeLogic logic) async { + /// 创建存储文件 + Directory? storageDir = await getExternalStorageDirectory(); + final storagePath = storageDir?.path ?? '/'; + String version = event.version.replaceAll(".", "-"); + File file = new File('$storagePath/${event.appName}v$version.apk'); + if (await file.exists()) await file.delete(); + if (!file.existsSync()) file.createSync(); + try { + /// 发起下载请求 + Response response = await Dio().get( + event.link, + onReceiveProgress: (num received, num total) { + showDownloadProgress(context, received, total, logic); + }, + options: Options( + responseType: ResponseType.bytes, + followRedirects: false, + ), + ); + file.writeAsBytesSync(response.data); + return file; + } catch (e) { + print(e); + // toPrint(val: e); + } + } + + // 安装apk + static Future installApk(context, UpdateAppEvent event, UpgradeLogic logic) async { + try { + logic.loadingApk.value = true; + File? _apkFile = await _downloadAndroid(context, event, logic); + if (_apkFile == null) return false; + String _apkFilePath = _apkFile.path; + if (_apkFilePath.isEmpty) { + debugPrint('make sure the apk file is set'); + return false; + } + + await showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: const Text("未知应用安装权限提示", + style: TextStyle( + fontWeight: FontWeight.bold, + )), + content: const Text("请注意:更新时若出现需要同意“安装未知应用权限”,请同意!!!"), + actions: [ + MaterialButton( + color: Theme.of(context).primaryColor, + child: const Text("我已知晓", style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold)), + onPressed: () => Navigator.of(context).pop(), + ), + ], + ); + }, + ); + await AppInstaller.installApk(_apkFilePath); // 安装APK + // 如果2秒还没有进入安装引导页面 一律视为更新失败,弹出其他方式更新 + Utils.getInstance().setTimeOut(1, () async { + try { + // 其他方式下载 + // await SystemNavigator.pop(); // 退出APP + var options = ['应用市场更新APP', '浏览器下载并安装APP']; + var uri = Uri.parse('market://details?id=com.example.marking_app'); // 应用市场URI + if (!await canLaunchUrl(uri)) options.removeAt(0); // 如果不能打开应用市场 就屏蔽掉 这个安装方式 + String? option = await UpgradePermission.showCustomModalBottomSheet(context, options); + if (option == '应用市场更新APP') await launchUrl(uri); + if (option == '浏览器下载并安装APP') await launchUrl(Uri.parse(event.link)); + } catch (e) {} + }); + + print('安装执行完成了..............0.0'); + } catch (e) { + print('安装进入报错....'); + print(e); + } finally { + logic.loadingApk.value = false; + } + + return false; + } + + /// 展示下载进度 + static void showDownloadProgress(context, num received, num total, UpgradeLogic logic) { + if (total != -1) { + double progress = double.parse((received / total).toStringAsFixed(2)); + // debugPrint('下载进度$progress'); + logic.downloadRatio.value = progress; + } + } +} + +class RestartWidget extends StatefulWidget { + final Widget child; + + const RestartWidget({super.key, required this.child}); + + static restartApp(BuildContext context) { + final _RestartWidgetState? state = context.findAncestorStateOfType<_RestartWidgetState>(); + state?.restartApp(); + } + + @override + State createState() => _RestartWidgetState(); +} + +class _RestartWidgetState extends State { + Key key = UniqueKey(); + + void restartApp() { + setState(() { + key = UniqueKey(); + }); + } + + @override + Widget build(BuildContext context) { + return KeyedSubtree( + key: key, + child: widget.child, + ); + } +} diff --git a/making_school_asignment_app/lib/common/utils/app_upgrade/UpdateDialog.dart b/making_school_asignment_app/lib/common/utils/app_upgrade/UpdateDialog.dart new file mode 100644 index 0000000..4d41354 --- /dev/null +++ b/making_school_asignment_app/lib/common/utils/app_upgrade/UpdateDialog.dart @@ -0,0 +1,212 @@ +/* + * @Author: wangyang 1147192855@qq.com + * @Date: + * @LastEditors: wangyang 1147192855@qq.com + * @LastEditTime: 2022-09-29 10:11:54 + * @FilePath: \marking_app\lib\utils\app_upgrade\UpdateDialog.dart + * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE + */ +/* + * @Descripttion: 版本更新提示弹窗 + * @version: + * @Author: wy + * @Date: 2020-07-30 14:03:28 + * @LastEditors: Please set LastEditors + * @LastEditTime: 2021-01-12 15:08:43 + */ +import 'package:flutter_widget_from_html_core/flutter_widget_from_html_core.dart'; +import 'package:get/get.dart'; +import 'package:making_school_asignment_app/common/utils/app_upgrade/DownloadApk.dart'; +import 'package:making_school_asignment_app/common/utils/app_upgrade/UpgradePermission.dart'; +import 'package:making_school_asignment_app/common/utils/app_upgrade/upgradeLogic.dart'; +import 'package:making_school_asignment_app/page/global_widget/my_text.dart'; +import 'package:percent_indicator/linear_percent_indicator.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:url_launcher/url_launcher.dart'; +import 'package:url_launcher/url_launcher_string.dart'; + +import '../anti_shake_throttling.dart'; +import 'model/UpdateAppEvent.dart'; + +class UpdateDialog extends Dialog { + final UpdateAppEvent updateAppEvent; + final String deviceInfo; + + const UpdateDialog({super.key, required this.updateAppEvent, required this.deviceInfo}); + + @override + Widget build(BuildContext context) { + return Center( + child: Container( + width: 319.w, + height: 440.h, + padding: EdgeInsets.symmetric(vertical: 8.h), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(18.sp), + image: const DecorationImage( + alignment: Alignment.topCenter, + image: AssetImage("assets/images/upgrade_dialog_bgc.png"), + fit: BoxFit.fitWidth, + ), + ), + child: Column( + children: [ + Expanded( + child: ListView( + physics: const BouncingScrollPhysics(), + padding: EdgeInsets.fromLTRB(16.w, 0, 16.w, 0), + children: [ + Container( + alignment: Alignment.center, + margin: EdgeInsets.only(top: 128.h, bottom: 10.h), + child: quickText( + updateAppEvent.title, + size: 18.sp, + fontWeight: FontWeight.w600, + color: const Color.fromRGBO(58, 90, 159, 1), + ), + ), + HtmlWidget( + updateAppEvent.description, + customStylesBuilder: (element) { + return {'color': '#666666', 'font-weight': 'normal', 'text-decoration': 'none'}; + }, + onLoadingBuilder: (context, element, loadingProgress) => const CircularProgressIndicator(), + renderMode: RenderMode.column, + textStyle: TextStyle(fontSize: 14.sp, color: Colors.black87), + ) + ], + ), + ), + DownloadProgress(), + DownloadButton(updateAppEvent, deviceInfo: deviceInfo), + ], + ), + ), + ); + } + + // 调起 + static showUpdateDialog(BuildContext context, UpdateAppEvent updateAppEvent) { + return showDialog( + barrierDismissible: false, + context: context, + builder: (BuildContext context) { + return WillPopScope( + onWillPop: () async => false, + child: UpdateDialog(updateAppEvent: updateAppEvent, deviceInfo: updateAppEvent.deviceInfo), + ); + }, + ); + } +} + +// 进度条 +class DownloadProgress extends StatelessWidget { + DownloadProgress({super.key}); + final logic = Get.find(); + + @override + Widget build(BuildContext context) { + return Obx(() { + var str = (logic.downloadRatio.value * 100).toString().split('.')[0]; + if (logic.downloadRatio.value <= 0) return Container(); + return Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + LinearPercentIndicator( + alignment: MainAxisAlignment.center, + width: 245.w, + animation: false, + lineHeight: 20.0.h, + percent: logic.downloadRatio.value, + center: quickText( + "$str%", + size: 14.sp, + align: TextAlign.center, + color: Colors.white, + ), + linearStrokeCap: LinearStrokeCap.roundAll, + progressColor: Theme.of(context).primaryColor, + ), + Container( + height: 6.h, + ), + quickText('更新中...', size: 12.sp, fontWeight: FontWeight.w500, color: const Color.fromRGBO(90, 90, 90, 1)) + ], + ); + }); + } +} + +// 点击下载按钮 +class DownloadButton extends StatelessWidget { + final UpdateAppEvent updateAppEvent; + final String deviceInfo; + DownloadButton(this.updateAppEvent, {required this.deviceInfo, super.key}); + final logic = Get.find(); + + // 打开浏览器或者对应的对应市场进行下载 + Future toLaunch(UpdateAppEvent data) async { + var uri = Uri.parse('market://details?id=com.yuanxuan.making_school_asignment_app'); + if (await canLaunchUrl(uri)) { + // 跳进对应的应用市场进行更新操作 + return await launchUrl(uri); + } + // 无法进入应用市场就打开浏览器进行下载 + uri = Uri.parse(data.link); + if (await canLaunchUrl(uri)) return await launchUrl(uri); + return false; + } + + @override + Widget build(BuildContext context) { + return Obx(() { + final count = logic.downloadRatio.value; + if (count > 0) return Container(); + var primaryColor = Theme.of(context).primaryColor; + return Container( + height: 38.h, + width: 245.w, + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(42.h)), + gradient: LinearGradient(colors: [ + primaryColor, + primaryColor.withOpacity(0.7), + ]), + ), + child: MaterialButton( + onPressed: () => easyThrottle('DownloadButton_App_Upgrade', duration: const Duration(milliseconds: 1000), () async { + if (deviceInfo == "android" && updateAppEvent.equipment == Equipment.android) { + // 权限检查 判断是否有读写内存的权限 + bool flag = await UpgradePermission(updateAppEvent.deviceInfo).checkPermission(context, updateAppEvent); + if (flag) { + flag = await DownloadApk.installApk(context, updateAppEvent, logic); + if (!flag) { + print('执行到了重置更新按钮的地方....'); + logic.downloadRatio.value = 0.0; // 更新失败重置 更新按钮 + } else { + print('更新成功重新打开APP..............'); + RestartWidget.restartApp(context); // 安装成功 重启APP + } + return; + } + // await FlutterClipboard.copy(updateAppEvent.link); + // setTimeOut(1000, () => ToastUtils.showInfo('下载链接已经复制到设备,可前往浏览器下载安装')); + } else if (deviceInfo == "ios" && updateAppEvent.equipment == Equipment.ios) { + try { + await launchUrlString(updateAppEvent.link); + } catch (e) { + print('进来更新报错$e'); + } + } + }), + child: quickText(!logic.loadingApk.value ? '立即体验' : '正在下载...', size: 16.sp, color: Colors.white, fontWeight: FontWeight.w500), + ), + ); + }); + } +} diff --git a/making_school_asignment_app/lib/common/utils/app_upgrade/UpgradePermission.dart b/making_school_asignment_app/lib/common/utils/app_upgrade/UpgradePermission.dart new file mode 100644 index 0000000..eaa6dda --- /dev/null +++ b/making_school_asignment_app/lib/common/utils/app_upgrade/UpgradePermission.dart @@ -0,0 +1,142 @@ +/* + * @Descripttion: 获取本地权限 + * @version: UpgradePermission + * @Author: wy + * @Date: 2020-07-30 15:41:39 + * @LastEditors: wangyang 1147192855@qq.com + * @LastEditTime: 2022-08-01 14:08:57 + */ +import 'package:app_installer/app_installer.dart'; +import 'package:flutter/material.dart'; +import 'package:permission_handler/permission_handler.dart'; +import 'package:url_launcher/url_launcher.dart'; + +import 'model/UpdateAppEvent.dart'; + +class UpgradePermission { + final String _flatform; + const UpgradePermission(this._flatform); + + /// 检查是否有权限,用于安卓 + /// noExecutions 执行次数 + Future checkPermission(BuildContext context, UpdateAppEvent updateAppEvent, [int? noExecutions]) async { + noExecutions ??= 1; + if (_flatform != 'android') return true; // 非安卓 + var status = await Permission.storage.request(); + if (status.isGranted) return true; + + if (status.isDenied) { + // 普通拒绝 可以再进行提示 + + await showDialog( + context: context, + barrierDismissible: false, + builder: (BuildContext context) { + return AlertDialog( + title: const Text("权限提示"), + content: const Text("无法获取存储权限,请同意获取设备存储权限"), + actions: [ + MaterialButton( + color: Theme.of(context).primaryColor, + child: const Text("同意", style: TextStyle(color: Colors.white)), + onPressed: () => Navigator.of(context).pop(), + ), + ], + ); + }, + ); + + if (noExecutions < 2) return checkPermission(context, updateAppEvent, ++noExecutions); + // 执行次数大于2次,就不再询问直接打开设置权限页面(防止某些机型不会弹起权限询问交互弹框) + } + + // 拒绝并不再提示 + bool? res = await showDialog( + context: context, + barrierDismissible: false, + builder: (BuildContext context) { + return AlertDialog( + title: const Text("权限提示"), + content: const Text("储存权限被永久拒绝,并且不再提示。请前往设置页面同意储存权限"), + actions: [ + MaterialButton( + color: Colors.green.shade900, + child: const Text("其它方式更新", style: TextStyle(color: Colors.white)), + onPressed: () => Navigator.of(context).pop(false), + ), + MaterialButton( + color: Theme.of(context).primaryColor, + child: const Text("前往设置", style: TextStyle(color: Colors.white)), + onPressed: () => Navigator.of(context).pop(true), + ), + ], + ); + }, + ); + if (res == null || !res) { + // 其他方式下载 + // await SystemNavigator.pop(); // 退出APP + var options = ['应用市场更新APP', '浏览器下载并安装APP']; + var uri = Uri.parse('market://details?id=com.example.marking_app'); // 应用市场URI + // if (!await canLaunchUrl(uri)) options.removeAt(0); // 如果不能打开应用市场 就屏蔽掉 这个安装方式 + String? option = await showCustomModalBottomSheet(context, options); + if (option == '应用市场更新APP') { + if (await canLaunchUrl(uri)) + await launchUrl(uri); + else + await AppInstaller.goStore('com.example.marking_app', 'iOSAppId'); + } + if (option == '浏览器下载并安装APP') await launchUrl(Uri.parse(updateAppEvent.link)); + } else + await openAppSettings(); + return false; + } + + // 其他方式下载选择 + static Future showCustomModalBottomSheet(context, List options) async { + return showModalBottomSheet( + backgroundColor: Colors.transparent, + isScrollControlled: true, + context: context, + builder: (BuildContext context) { + return Container( + clipBehavior: Clip.antiAlias, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.only( + topLeft: const Radius.circular(20.0), + topRight: const Radius.circular(20.0), + ), + ), + height: MediaQuery.of(context).size.height / 4.0, + child: Column(children: [ + SizedBox( + height: 50, + child: Stack( + textDirection: TextDirection.rtl, + children: [ + Center(child: Text('选择其它方式更新APP', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16.0))), + IconButton(icon: Icon(Icons.close), onPressed: () => Navigator.of(context).pop()), + ], + ), + ), + Divider(height: 1.0), + Expanded( + child: ListView.builder( + itemCount: options.length, + itemBuilder: (BuildContext context, int index) { + var name = options[index]; + return ListTile( + title: Text(name), + trailing: Icon(name.contains('浏览器') ? Icons.browser_updated_outlined : Icons.local_grocery_store_outlined), + onTap: () => Navigator.of(context).pop(name), + ); + }, + ), + ), + ]), + ); + }, + ); + } +} diff --git a/making_school_asignment_app/lib/common/utils/app_upgrade/model/UpdateAppEvent.dart b/making_school_asignment_app/lib/common/utils/app_upgrade/model/UpdateAppEvent.dart new file mode 100644 index 0000000..581721f --- /dev/null +++ b/making_school_asignment_app/lib/common/utils/app_upgrade/model/UpdateAppEvent.dart @@ -0,0 +1,83 @@ +/* + * @Descripttion: + * @version: + * @Author: wy + * @Date: 2020-07-30 14:10:44 + * @LastEditors: wangyang 1147192855@qq.com + * @LastEditTime: 2022-09-28 18:20:11 + */ + +class UpdateAppEvent { + final String version; + final String title; + final String description; + final String link; + final bool upgrade; + final String deviceInfo; + final String appName; + final String packageName; + final Equipment equipment; + num? v; + num? lv; + + UpdateAppEvent({ + required this.version, + required this.title, + required this.description, + required this.link, + required this.upgrade, + required this.deviceInfo, + required this.appName, + required this.packageName, + this.v, + this.lv, + int type = 0, + }) : equipment = Equipment.values[type]; + + factory UpdateAppEvent.fromJson(Map json, String localVersion, String deviceInfo, String appName, String packageName, + {String keyStr = "version", String typeName = "packageNameType"}) { + String version = json[keyStr]; // 版本号 + String? descriptionStr = json["description"]; + + String newDescription = '系统有更新,请立即下载'; + bool upgrade = false; + num? v; + num? lv; + // 版本号 + if (version != '') { + v = num.parse(version.replaceAll(".", "")); + lv = num.parse(localVersion.replaceAll(".", "")); + + // if (lv < v) upgrade = true; + //当前版本不等于线上版本更新为线上版本 + if (lv != v) upgrade = true; + } + + // 升级说明 + if (descriptionStr != null && descriptionStr.isNotEmpty) { + newDescription = descriptionStr; + } + + return UpdateAppEvent( + version: version, // 版本号 + title: json["title"] ?? "发现新版本", // title + description: newDescription, //说明 + link: json["downloadPath"], // 链接地址 + upgrade: upgrade, + deviceInfo: deviceInfo, + appName: appName, + packageName: packageName, + type: json[typeName] ?? 0, + v: v, + lv: lv, + ); + } + + @override + String toString() { + return "UpdateAppEvent { version: $version, title: $title, description: $description, link: $link}"; + } +} + +// 设备枚举 +enum Equipment { other, android, ios } diff --git a/making_school_asignment_app/lib/common/utils/app_upgrade/upgradeLogic.dart b/making_school_asignment_app/lib/common/utils/app_upgrade/upgradeLogic.dart new file mode 100644 index 0000000..8bd7ee6 --- /dev/null +++ b/making_school_asignment_app/lib/common/utils/app_upgrade/upgradeLogic.dart @@ -0,0 +1,63 @@ +import 'dart:io'; +import 'package:flutter/widgets.dart'; +import 'package:get/get.dart'; +import 'package:making_school_asignment_app/common/job/app_version.dart'; +import 'package:making_school_asignment_app/common/mixins/request_tool_mixin.dart'; +import 'package:package_info_plus/package_info_plus.dart'; + +import 'UpdateDialog.dart'; +import 'model/UpdateAppEvent.dart'; + +class UpgradeLogic extends GetxController with RequestToolMixin { + Rx showUpgrade = false.obs; // 是否已经显示升级弹窗 + Rx loadingApk = false.obs; // 是否已经显示升级弹窗 + Rx downloadRatio = 0.0.obs; // 下载比例 + + // @override + // void onInit() { + + // super.onInit(); + // } + + void getAppUpgrade(BuildContext context) async { + // if (!const bool.fromEnvironment('dart.vm.product')) return; + try { + showUpgrade.value = true; + // if (['18888888888'].contains(user.loginName)) return; + // 获取设备信息 + String deviceInfo; + int deviceType; + if (Platform.isAndroid) { + deviceInfo = "android"; + deviceType = 1; + } else if (Platform.isIOS) { + deviceInfo = "ios"; + deviceType = 2; + } else { + return; + } + + AppVersion? result = await getClient().getLastAppVersion('making_school_asignment_app', deviceType); + if (result != null) { + //获取当前版本 + PackageInfo packageInfo = await PackageInfo.fromPlatform(); + //获取当前版本 + String localVersion = packageInfo.version; + String appName = packageInfo.appName; //应用名称 + String packageName = packageInfo.packageName; //包名称 + // String buildNumber = packageInfo.buildNumber; //小版本号 + + Map json = { + 'downloadPath': result.downloadUrl, + 'version': result.version, + 'systemType': deviceType, + 'description': result.description ?? 'APP新版本更新' + }; + UpdateAppEvent updateAppEvent = UpdateAppEvent.fromJson(json, localVersion, deviceInfo, appName, packageName, typeName: 'systemType'); + if (updateAppEvent.upgrade) await UpdateDialog.showUpdateDialog(context, updateAppEvent); + } + } finally { + showUpgrade.value = false; + } + } +} diff --git a/making_school_asignment_app/lib/common/utils/utils.dart b/making_school_asignment_app/lib/common/utils/utils.dart index dcfed42..d59af4e 100644 --- a/making_school_asignment_app/lib/common/utils/utils.dart +++ b/making_school_asignment_app/lib/common/utils/utils.dart @@ -7,7 +7,13 @@ import 'package:making_school_asignment_app/page/home_page/children/quick_data_c import 'dart:math'; class Utils { + static Utils? _instance; Utils._internal(); + static Utils getInstance() { + _instance ??= Utils._internal(); + + return _instance!; + } /// 关闭键盘 static void hideKeyboard() { @@ -20,6 +26,8 @@ class Utils { } } + void setTimeOut(int seconds, call) => Future.delayed(Duration(seconds: seconds), call); + // 是否是平板 static bool isPad([double mobilePhoneScale = 1.2]) { return ScreenUtil().scaleWidth > mobilePhoneScale; @@ -82,38 +90,26 @@ class Utils { dataCount.kgtAnswerCount = kgt.where((w) => w.state != 0).length; dataCount.kgtOkCount = kgt.where((w) => w.state == 3).length; dataCount.kgtDtlCount = kgt.length; - dataCount.kgtAnswerRate = - Utils.calcRate(dataCount.kgtAnswerCount!, dataCount.kgtDtlCount!); - dataCount.kgtOkRate = - Utils.calcRate(dataCount.kgtOkCount!, dataCount.kgtDtlCount!); - dataCount.kgtCount = - data.questions.where((w) => w.questionType == 1).length; + dataCount.kgtAnswerRate = Utils.calcRate(dataCount.kgtAnswerCount!, dataCount.kgtDtlCount!); + dataCount.kgtOkRate = Utils.calcRate(dataCount.kgtOkCount!, dataCount.kgtDtlCount!); + dataCount.kgtCount = data.questions.where((w) => w.questionType == 1).length; List zgt = data.dtls.where((w) => w.questionType == 2).toList(); dataCount.zgtAnswerCount = zgt.where((w) => w.state != 0).length; dataCount.zgtOkCount = zgt.where((w) => w.state == 3).length; dataCount.zgtDtlCount = zgt.length; - dataCount.zgtAnswerRate = - Utils.calcRate(dataCount.zgtAnswerCount!, dataCount.zgtDtlCount!); - dataCount.zgtOkRate = - Utils.calcRate(dataCount.zgtOkCount!, dataCount.zgtDtlCount!); - dataCount.zgtCount = - data.questions.where((w) => w.questionType == 2).length; + dataCount.zgtAnswerRate = Utils.calcRate(dataCount.zgtAnswerCount!, dataCount.zgtDtlCount!); + dataCount.zgtOkRate = Utils.calcRate(dataCount.zgtOkCount!, dataCount.zgtDtlCount!); + dataCount.zgtCount = data.questions.where((w) => w.questionType == 2).length; dataCount.studentCount = data.students.length; - dataCount.priorityStudents = - data.students.where((w) => w.priorityAnnotate!).toList(); - + dataCount.priorityStudents = data.students.where((w) => w.priorityAnnotate!).toList(); //已提交学生数 - dataCount.studentSubmitCount = - data.students.where((s) => s.state != 0).length; - dataCount.studentSubmitStudents = - data.students.where((s) => s.state != 0).toList(); + dataCount.studentSubmitCount = data.students.where((s) => s.state != 0).length; + dataCount.studentSubmitStudents = data.students.where((s) => s.state != 0).toList(); //未提交学生数 - dataCount.noAnswerCount = - data.students.length - dataCount.studentSubmitCount!; - dataCount.noAnswerStudents = - data.students.where((s) => s.state == 0).toList(); + dataCount.noAnswerCount = data.students.length - dataCount.studentSubmitCount!; + dataCount.noAnswerStudents = data.students.where((s) => s.state == 0).toList(); for (var stu in data.students) { stu.kgtStu = kgt.where((w) => w.studentId == stu.studentId).toList(); @@ -128,17 +124,13 @@ class Utils { stu.zgtErrorCount = stu.zgtStu!.where((w) => w.state == 2).length; stu.zgtUnrated = stu.zgtStu!.where((w) => w.state == 1).length; stu.zgtAnswerCount = stu.zgtStu!.where((w) => w.state != 0).length; - stu.isAllCorrect = - stu.kgtOkCount! + stu.zgtOkCount! == kgt.length + zgt.length - ? true - : false; + stu.isAllCorrect = stu.kgtOkCount! + stu.zgtOkCount! == kgt.length + zgt.length ? true : false; stu.allOk = data.dtls.where((w) { if (stu.studentId == w.studentId) { stu.useTime = w.useTime; } for (var que in data.questions) { - if (w.templateId == que.templateId && - w.questionNo == que.questionNo) { + if (w.templateId == que.templateId && w.questionNo == que.questionNo) { w.answer = que.answer; w.questionPicture = que.questionPicture; } @@ -146,25 +138,16 @@ class Utils { return w.studentId == stu.studentId && w.state != 3; }).length ?? 0; - if ((stu.kgtStu!.length - stu.kgtAnswerCount!) + - (stu.zgtStu!.length - stu.zgtAnswerCount!) == - (stu.kgtStu!.length + stu.zgtStu!.length)) { + if ((stu.kgtStu!.length - stu.kgtAnswerCount!) + (stu.zgtStu!.length - stu.zgtAnswerCount!) == (stu.kgtStu!.length + stu.zgtStu!.length)) { stu.allNotDone = true; } else { stu.allNotDone = false; } - stu.noAnswerCount = data.dtls - .where((w) => w.state == 0 && stu.studentId == w.studentId) - .length; + stu.noAnswerCount = data.dtls.where((w) => w.state == 0 && stu.studentId == w.studentId).length; List ques = data.questions; stu.queDtls = data.dtls - .where((w) => - w.studentId == stu.studentId && - ques.indexWhere((q) => - w.templateId == q.templateId && - w.questionNo == q.questionNo) > - -1) + .where((w) => w.studentId == stu.studentId && ques.indexWhere((q) => w.templateId == q.templateId && w.questionNo == q.questionNo) > -1) .toList(); int okCount = stu.queDtls!.where((w) => w.state == 3).length; int ttlCount = stu.queDtls!.length; @@ -177,57 +160,41 @@ class Utils { return num2.compareTo(num1); }); //全对 - dataCount.allCorrect = - data.students.where((w) => w.isAllCorrect == true).length; - dataCount.allCorrectStudents = - data.students.where((w) => w.isAllCorrect == true).toList(); + dataCount.allCorrect = data.students.where((w) => w.isAllCorrect == true).length; + dataCount.allCorrectStudents = data.students.where((w) => w.isAllCorrect == true).toList(); //优 - dataCount.levelOneCount = - data.students.where((s) => s.okRate! >= 85).length; - dataCount.levelOneStudents = - data.students.where((s) => s.okRate! >= 85).toList(); + dataCount.levelOneCount = data.students.where((s) => s.okRate! >= 85).length; + dataCount.levelOneStudents = data.students.where((s) => s.okRate! >= 85).toList(); //良 - dataCount.levelTwoCount = - data.students.where((s) => s.okRate! < 85 && s.okRate! >= 55).length; - dataCount.levelTwoStudents = - data.students.where((s) => s.okRate! < 85 && s.okRate! >= 55).toList(); + dataCount.levelTwoCount = data.students.where((s) => s.okRate! < 85 && s.okRate! >= 55).length; + dataCount.levelTwoStudents = data.students.where((s) => s.okRate! < 85 && s.okRate! >= 55).toList(); //中 - dataCount.levelThreeCount = - data.students.where((s) => s.okRate! < 55 && s.okRate! >= 25).length; - dataCount.levelThreeStudents = - data.students.where((s) => s.okRate! < 55 && s.okRate! >= 25).toList(); + dataCount.levelThreeCount = data.students.where((s) => s.okRate! < 55 && s.okRate! >= 25).length; + dataCount.levelThreeStudents = data.students.where((s) => s.okRate! < 55 && s.okRate! >= 25).toList(); //差 - dataCount.levelFourCount = - data.students.where((s) => s.okRate! < 25).length; - dataCount.levelFourStudents = - data.students.where((s) => s.okRate! < 25).toList(); + dataCount.levelFourCount = data.students.where((s) => s.okRate! < 25).length; + dataCount.levelFourStudents = data.students.where((s) => s.okRate! < 25).toList(); for (var que in data.questions) { - List ques = data.dtls - .where((w) => - w.templateId == que.templateId && w.questionNo == que.questionNo) - .toList(); + List ques = data.dtls.where((w) => w.templateId == que.templateId && w.questionNo == que.questionNo).toList(); que.answerCount = ques.where((w) => w.state != 0).length; - que.answerRate = - Utils.calcRate(que.answerCount!, dataCount.studentCount!); + que.answerRate = Utils.calcRate(que.answerCount!, dataCount.studentCount!); int okCount = ques.where((w) => w.state == 3).length; que.okRate = Utils.calcRate(okCount, dataCount.studentCount!); que.priorityInfo = ques.where((w) { return dataCount.priorityStudents!.indexWhere((s) { - w.studentName = s.studentName; - return s.studentId == w.studentId; - }) > - -1 && + w.studentName = s.studentName; + return s.studentId == w.studentId; + }) > + -1 && w.state != 3; }).toList(); que.answerNgStudents = ques.where((w) { - w.studentName = data.students - .firstWhere((s) => s.studentId == w.studentId) - .studentName; + w.studentName = data.students.firstWhere((s) => s.studentId == w.studentId).studentName; return w.state == 2; }).toList(); @@ -238,18 +205,14 @@ class Utils { return w.state == 3; }).toList(); - //作答效率 int middleTime = 0; if (ques.length % 2 == 0) { int index = (ques.length / 2).ceil(); - middleTime = ((ques[index].useTime + - ques[index - 1].useTime) / - 2) - .ceil(); + middleTime = ((ques[index].useTime + ques[index - 1].useTime) / 2).ceil(); } else { - int index = ((ques.length + 1) / 2).ceil() ; - middleTime = ques[index - 1 ].useTime; + int index = ((ques.length + 1) / 2).ceil(); + middleTime = ques[index - 1].useTime; } var excellent = ques.where((w) => w.state == 3 && w.useTime <= middleTime).length; @@ -257,26 +220,12 @@ class Utils { var middle = ques.where((w) => w.state != 3 && w.useTime <= middleTime).length; var differ = ques.where((w) => w.state != 3 && w.useTime > middleTime).length; - que.overallTitles = [OverallTitles('优秀',excellent),OverallTitles('良好',good), - OverallTitles('中',middle),OverallTitles('差',differ)]; - - + que.overallTitles = [OverallTitles('优秀', excellent), OverallTitles('良好', good), OverallTitles('中', middle), OverallTitles('差', differ)]; } - - for (var know in data.knows) { - List ques = data.questions - .where((w) => - w.knows.indexWhere((k) => k.knowledgeId == know.knowledgeId) > -1) - .toList(); - List queDtls = data.dtls - .where((w) => - ques.indexWhere((q) => - w.templateId == q.templateId && - w.questionNo == q.questionNo) > - -1) - .toList(); + List ques = data.questions.where((w) => w.knows.indexWhere((k) => k.knowledgeId == know.knowledgeId) > -1).toList(); + List queDtls = data.dtls.where((w) => ques.indexWhere((q) => w.templateId == q.templateId && w.questionNo == q.questionNo) > -1).toList(); know.okCount = queDtls.where((w) => w.state == 3).length; know.ttlCount = queDtls.length; know.okRate = Utils.calcRate(know.okCount!, know.ttlCount!); @@ -311,7 +260,6 @@ bool isPad([double mobilePhoneScale = 1.2]) { return ScreenUtil().scaleWidth > mobilePhoneScale; } -void toUpState( - Function(void Function()) setState, VoidCallback fn, bool mounted) { +void toUpState(Function(void Function()) setState, VoidCallback fn, bool mounted) { if (mounted) setState(fn); -} \ No newline at end of file +} diff --git a/making_school_asignment_app/lib/main.dart b/making_school_asignment_app/lib/main.dart index 414aa32..477f302 100644 --- a/making_school_asignment_app/lib/main.dart +++ b/making_school_asignment_app/lib/main.dart @@ -11,6 +11,8 @@ import 'package:making_school_asignment_app/common/utils/utils.dart'; import 'package:making_school_asignment_app/routes/app_pages.dart'; import 'package:flutter_easyloading/flutter_easyloading.dart'; +import 'common/utils/app_upgrade/upgradeLogic.dart'; + void main() async { // 在测试模式下运行Get Get.testMode = true; @@ -20,6 +22,7 @@ void main() async { /// 初始化UserStore Get.put(UserStore().init()); + Get.put(UpgradeLogic()); WidgetsFlutterBinding.ensureInitialized(); SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle( statusBarColor: Colors.transparent, //状态栏背景颜色 diff --git a/making_school_asignment_app/lib/page/global_widget/start_page.dart b/making_school_asignment_app/lib/page/global_widget/start_page.dart index 1b6953c..f978920 100644 --- a/making_school_asignment_app/lib/page/global_widget/start_page.dart +++ b/making_school_asignment_app/lib/page/global_widget/start_page.dart @@ -1,17 +1,14 @@ -import 'dart:io'; +import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; -import 'package:package_info_plus/package_info_plus.dart'; -import 'package:making_school_asignment_app/common/config/app_config.dart'; -import 'package:making_school_asignment_app/common/job/common/app_version_model.dart'; -import 'package:making_school_asignment_app/common/job/common/base_app_version.dart'; -import 'package:making_school_asignment_app/common/job/common/base_page_data.dart'; +import 'package:making_school_asignment_app/common/utils/app_upgrade/upgradeLogic.dart'; import 'package:making_school_asignment_app/common/job/user_info.dart'; import 'package:making_school_asignment_app/common/job/user_info_detail.dart'; import 'package:making_school_asignment_app/common/mixins/request_tool_mixin.dart'; import 'package:making_school_asignment_app/common/store/user_store.dart'; +import 'package:making_school_asignment_app/common/utils/storage.dart'; import 'package:making_school_asignment_app/common/utils/toast_utils.dart'; import 'package:making_school_asignment_app/page/home_page/children/my_info.dart'; import 'package:making_school_asignment_app/page/home_page/home_logic.dart'; @@ -27,22 +24,30 @@ class StartPage extends StatefulWidget { State createState() => _StartPageState(); } -class _StartPageState extends State { +class _StartPageState extends State with RequestToolMixin { + Timer? _timer; DateTime? lastPopTime; final _pageController = Get.find(); + final _upgradeLogic = Get.find(); + late final List _bodyList; @override void initState() { super.initState(); + Get.put(HomeLogic()); Get.put(WorkLogic()); - _bodyList = [ - const HomePage(), - const WorkPage(), - const MyInfo(), - ]; + _bodyList = [const HomePage(), const WorkPage(), const MyInfo()]; + // TODO 启动APP 后直接请求更新 + if (!_upgradeLogic.showUpgrade.value) _upgradeLogic.getAppUpgrade(context); + + _timer?.cancel(); + _timer = Timer.periodic(const Duration(seconds: 40), (e) { + if (Get.currentRoute == Routes.login) return; // 在登录页面不更新APP + if (!_upgradeLogic.showUpgrade.value) _upgradeLogic.getAppUpgrade(context); + }); String? token = UserStore.to.token; UserInfo? userInfo = UserStore.to.userInfo.value; @@ -55,13 +60,18 @@ class _StartPageState extends State { // 更新用户信息 if (userInfoDetail == null) UserStore.to.updateUserInfo(); } else { - Future.delayed(const Duration(milliseconds: 100)).then((e) => Get.offAllNamed(Routes.login)); + Future.delayed(const Duration(milliseconds: 100)).then((e) { + UserStore.to.erase(); + StorageService.to.erase(); + Get.offAllNamed(Routes.login); + }); } } @override void dispose() { Get.delete(); + _timer?.cancel(); super.dispose(); } @@ -146,44 +156,6 @@ class PageIndexState { class PageIndexController extends GetxController with RequestToolMixin { late PageIndexState _pageIndexState; - void getAppUpgrade(UserInfoDetail user) async { - try { - _pageIndexState.showUpgrade = true; - if (user.name == AppConfig.SKIP_UPDATING_USER) return; - // 获取设备信息 - String deviceInfo = "android"; - int deviceType; - if (Platform.isAndroid) { - deviceType = 1; - } else if (Platform.isIOS) { - deviceInfo = "ios"; - deviceType = 2; - } else { - return; - } - var params = BaseAppVersion(AppConfig.APP_NAME, deviceType, 1, 1); - BasePageData? result = await getClient().getAppVersions(params); - if (result != null && result.total == 1) { - //获取当前版本 - PackageInfo packageInfo = await PackageInfo.fromPlatform(); - //获取当前版本 - String localVersion = packageInfo.version; - String appName = packageInfo.appName; //应用名称 - String packageName = packageInfo.packageName; //包名称 - // String buildNumber = packageInfo.buildNumber; //小版本号 - AppVersionModel data = result.items[0]; - // Map json = {'downloadPath': data.apkUrl, 'version': data.version, 'systemType': deviceType, 'description': data.description}; - // UpdateAppEvent updateAppEvent = UpdateAppEvent.fromJson(json, localVersion, deviceInfo, appName, packageName, typeName: 'systemType'); - // if (updateAppEvent.upgrade) { - // await UpdateDialog.showUpdateDialog(context, updateAppEvent); - // } - } - } catch (e) { - } finally { - _pageIndexState.showUpgrade = false; - } - } - @override void onInit() { _pageIndexState = PageIndexState(pageController: PageController()); diff --git a/making_school_asignment_app/lib/page/home_page/children/job_report/widget/top_count.dart b/making_school_asignment_app/lib/page/home_page/children/job_report/widget/top_count.dart index 7d95009..1f6a954 100644 --- a/making_school_asignment_app/lib/page/home_page/children/job_report/widget/top_count.dart +++ b/making_school_asignment_app/lib/page/home_page/children/job_report/widget/top_count.dart @@ -6,6 +6,7 @@ import 'package:making_school_asignment_app/page/global_widget/MyEmptyWidget.dar import 'package:making_school_asignment_app/page/global_widget/show_student_list.dart'; import 'package:making_school_asignment_app/page/home_page/children/quick_data_check/quick_data_check_state.dart'; +part 'top_count.g.dart'; class TopCount extends StatelessWidget { final CountData data; @@ -14,7 +15,7 @@ class TopCount extends StatelessWidget { const TopCount(this.data, this.className, this.jobId, {Key? key}) : super(key: key); - void showStudentListDialog({required BuildContext context, required String title, required List students}) { + void showStudentListDialog({required BuildContext context, required String title, required List students}) { showDialog( context: context, builder: (BuildContext context) { @@ -58,11 +59,11 @@ class TopCount extends StatelessWidget { AnswerOkStudents item = arr[index]; return InkWell( onTap: () { - *//*RouterManager.router.navigateTo( + */ /*RouterManager.router.navigateTo( context, RouterManager.quickCheckPersonalPath + '?jobId=$jobId&studentId=${item.id}', transition: getTransition(), - );*//* + );*/ /* }, child: Container( padding: EdgeInsets.symmetric(vertical: 5.r, horizontal: 15.r), @@ -142,8 +143,7 @@ class TopCount extends StatelessWidget { onTap: () { showStudentListDialog(context: context, title: '中等作业学生', students: data.levelThreeStudents!); }, - child: - rightContainer(count: data.levelThreeCount!, bgColor: Color(0xFFD3FF93), nameColor: Color(0xFF3F6605), name: '中'), + child: rightContainer(count: data.levelThreeCount!, bgColor: Color(0xFFD3FF93), nameColor: Color(0xFF3F6605), name: '中'), )), ], ), @@ -159,16 +159,14 @@ class TopCount extends StatelessWidget { onTap: () { showStudentListDialog(context: context, title: '良等作业学生', students: data.levelTwoStudents!); }, - child: - rightContainer(count: data.levelTwoCount!, bgColor: Color(0xFFFFC38C), nameColor: Color(0xFFD36500), name: '良'), + child: rightContainer(count: data.levelTwoCount!, bgColor: Color(0xFFFFC38C), nameColor: Color(0xFFD36500), name: '良'), )), Expanded( child: InkWell( onTap: () { showStudentListDialog(context: context, title: '差等作业学生', students: data.levelFourStudents!); }, - child: - rightContainer(count: data.levelFourCount!, bgColor: Color(0xFFFF9D94), nameColor: Color(0xFFD12616), name: '差'), + child: rightContainer(count: data.levelFourCount!, bgColor: Color(0xFFFF9D94), nameColor: Color(0xFFD12616), name: '差'), )), ], ), diff --git a/making_school_asignment_app/lib/page/login_page/login_view.dart b/making_school_asignment_app/lib/page/login_page/login_view.dart index 9109e46..27b3c8a 100644 --- a/making_school_asignment_app/lib/page/login_page/login_view.dart +++ b/making_school_asignment_app/lib/page/login_page/login_view.dart @@ -3,6 +3,7 @@ import 'package:flutter/services.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; import 'package:making_school_asignment_app/common/const_text.dart'; +import 'package:making_school_asignment_app/common/utils/app_upgrade/upgradeLogic.dart'; import 'package:making_school_asignment_app/common/utils/utils.dart'; import 'package:making_school_asignment_app/page/global_widget/my_text.dart'; import 'package:making_school_asignment_app/routes/app_pages.dart'; @@ -18,8 +19,21 @@ class LoginPage extends StatefulWidget { class _LoginPageState extends State { final logic = Get.find(); + final upgradeLogic = Get.find(); final state = Get.find().state; + @override + void initState() { + Future.delayed(Duration.zero, () => upgradeLogic.getAppUpgrade(context)); + super.initState(); + } + + @override + void dispose() { + Get.delete(); + super.dispose(); + } + @override Widget build(BuildContext context) { return GestureDetector( @@ -151,7 +165,7 @@ class _LoginPageState extends State { decoration: InputDecoration( hintText: "请输入密码", prefix: Padding( - padding: EdgeInsets.only(right:5.r), + padding: EdgeInsets.only(right: 5.r), child: Image.asset( 'assets/images/login_pwd.png', width: 15.r, @@ -254,7 +268,7 @@ class _LoginPageState extends State { Row( children: [ Container( - width: 25 .w, + width: 25.w, padding: EdgeInsets.only(right: 0.w), child: Obx(() { return Transform.scale( @@ -301,10 +315,4 @@ class _LoginPageState extends State { ), ); } - - @override - void dispose() { - Get.delete(); - super.dispose(); - } } diff --git a/making_school_asignment_app/linux/flutter/generated_plugin_registrant.cc b/making_school_asignment_app/linux/flutter/generated_plugin_registrant.cc index e71a16d..f6f23bf 100644 --- a/making_school_asignment_app/linux/flutter/generated_plugin_registrant.cc +++ b/making_school_asignment_app/linux/flutter/generated_plugin_registrant.cc @@ -6,6 +6,10 @@ #include "generated_plugin_registrant.h" +#include void fl_register_plugins(FlPluginRegistry* registry) { + g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin"); + url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar); } diff --git a/making_school_asignment_app/linux/flutter/generated_plugins.cmake b/making_school_asignment_app/linux/flutter/generated_plugins.cmake index 2e1de87..f16b4c3 100644 --- a/making_school_asignment_app/linux/flutter/generated_plugins.cmake +++ b/making_school_asignment_app/linux/flutter/generated_plugins.cmake @@ -3,6 +3,7 @@ # list(APPEND FLUTTER_PLUGIN_LIST + url_launcher_linux ) list(APPEND FLUTTER_FFI_PLUGIN_LIST diff --git a/making_school_asignment_app/pubspec.yaml b/making_school_asignment_app/pubspec.yaml index 0fc5086..3cf7843 100644 --- a/making_school_asignment_app/pubspec.yaml +++ b/making_school_asignment_app/pubspec.yaml @@ -88,6 +88,9 @@ dependencies: flutter_echarts: ^2.4.0 # 饼图 flutter_echart: ^2.0.0 + url_launcher: ^6.1.11 + app_installer: ^1.1.0 + permission_handler: ^11.0.1 dev_dependencies: flutter_test: diff --git a/making_school_asignment_app/windows/flutter/generated_plugin_registrant.cc b/making_school_asignment_app/windows/flutter/generated_plugin_registrant.cc index 8777c93..51b78a6 100644 --- a/making_school_asignment_app/windows/flutter/generated_plugin_registrant.cc +++ b/making_school_asignment_app/windows/flutter/generated_plugin_registrant.cc @@ -7,8 +7,14 @@ #include "generated_plugin_registrant.h" #include +#include +#include void RegisterPlugins(flutter::PluginRegistry* registry) { ConnectivityPlusWindowsPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("ConnectivityPlusWindowsPlugin")); + PermissionHandlerWindowsPluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("PermissionHandlerWindowsPlugin")); + UrlLauncherWindowsRegisterWithRegistrar( + registry->GetRegistrarForPlugin("UrlLauncherWindows")); } diff --git a/making_school_asignment_app/windows/flutter/generated_plugins.cmake b/making_school_asignment_app/windows/flutter/generated_plugins.cmake index cc1361d..9678546 100644 --- a/making_school_asignment_app/windows/flutter/generated_plugins.cmake +++ b/making_school_asignment_app/windows/flutter/generated_plugins.cmake @@ -4,6 +4,8 @@ list(APPEND FLUTTER_PLUGIN_LIST connectivity_plus + permission_handler_windows + url_launcher_windows ) list(APPEND FLUTTER_FFI_PLUGIN_LIST