下载新版本
This commit is contained in:
parent
36a0e183ff
commit
8cae1ffd7d
|
|
@ -1,8 +1,12 @@
|
||||||
|
import 'package:cashier_reserve/common/print/print.dart';
|
||||||
import 'package:cashier_reserve/common/push/push.dart';
|
import 'package:cashier_reserve/common/push/push.dart';
|
||||||
import 'package:cashier_reserve/data_model/login/login_result.dart';
|
import 'package:cashier_reserve/data_model/login/login_result.dart';
|
||||||
import 'package:cashier_reserve/login/login_view.dart';
|
import 'package:cashier_reserve/login/login_view.dart';
|
||||||
import 'package:cashier_reserve/model/reserve_model.dart';
|
import 'package:cashier_reserve/model/reserve_model.dart';
|
||||||
|
import 'package:cashier_reserve/model/version_model.dart';
|
||||||
|
import 'package:cashier_reserve/update_version/update_version_view.dart';
|
||||||
import 'package:easy_refresh/easy_refresh.dart';
|
import 'package:easy_refresh/easy_refresh.dart';
|
||||||
|
import 'package:package_info_plus/package_info_plus.dart';
|
||||||
|
|
||||||
import '../base/ui.dart';
|
import '../base/ui.dart';
|
||||||
import '../channel/channel_event.dart';
|
import '../channel/channel_event.dart';
|
||||||
|
|
@ -62,6 +66,36 @@ class AppManager {
|
||||||
YJPush.presentWidget(globalContext!, const LoginView());
|
YJPush.presentWidget(globalContext!, const LoginView());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void checkAppVersion() async {
|
||||||
|
final res = await VersionModel.requestNewVersionInfo();
|
||||||
|
yjPrint(res);
|
||||||
|
|
||||||
|
if (res == null || res.version == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PackageInfo packageInfo = await PackageInfo.fromPlatform();
|
||||||
|
yjPrint("version == ${packageInfo.version}");
|
||||||
|
|
||||||
|
List<String> serverList = res.version!.split(".");
|
||||||
|
List<String> localList = packageInfo.version.split(".");
|
||||||
|
|
||||||
|
if (serverList.length != 3 || localList.length != 3) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int serverVersion = int.parse(serverList[0]) * 10000 + int.parse(serverList[1]) * 100 + int.parse(serverList[2]);
|
||||||
|
int localVersion = int.parse(localList[0]) * 10000 + int.parse(localList[1]) * 100 + int.parse(localList[2]);
|
||||||
|
|
||||||
|
if (serverVersion <= localVersion) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
yjPrint("serverVersion == $serverVersion, localVersion == $localVersion");
|
||||||
|
|
||||||
|
YJPush.presentWidget(globalContext!, UpdateVersionView(versionModel: res,));
|
||||||
|
}
|
||||||
|
|
||||||
static void disposeLoginWidget() {
|
static void disposeLoginWidget() {
|
||||||
_isAlertLogin = false;
|
_isAlertLogin = false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,128 @@
|
||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
/// createdAt : 1712455187626
|
||||||
|
/// id : 19
|
||||||
|
/// isUp : 0
|
||||||
|
/// message : "需要更新"
|
||||||
|
/// sel : 1
|
||||||
|
/// source : "PC"
|
||||||
|
/// type : "android"
|
||||||
|
/// updatedAt : 1725353572331
|
||||||
|
/// url : "https://cashier-oss.oss-cn-beijing.aliyuncs.com/upload/version/1.4.20.exe"
|
||||||
|
/// version : "1.4.21"
|
||||||
|
|
||||||
|
UpdateVersionModel updateVersionModelFromJson(String str) =>
|
||||||
|
UpdateVersionModel.fromJson(json.decode(str));
|
||||||
|
|
||||||
|
String updateVersionModelToJson(UpdateVersionModel data) =>
|
||||||
|
json.encode(data.toJson());
|
||||||
|
|
||||||
|
class UpdateVersionModel {
|
||||||
|
UpdateVersionModel({
|
||||||
|
num? createdAt,
|
||||||
|
num? id,
|
||||||
|
num? isUp,
|
||||||
|
String? message,
|
||||||
|
num? sel,
|
||||||
|
String? source,
|
||||||
|
String? type,
|
||||||
|
num? updatedAt,
|
||||||
|
String? url,
|
||||||
|
String? version,
|
||||||
|
}) {
|
||||||
|
_createdAt = createdAt;
|
||||||
|
_id = id;
|
||||||
|
_isUp = isUp;
|
||||||
|
_message = message;
|
||||||
|
_sel = sel;
|
||||||
|
_source = source;
|
||||||
|
_type = type;
|
||||||
|
_updatedAt = updatedAt;
|
||||||
|
_url = url;
|
||||||
|
_version = version;
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateVersionModel.fromJson(dynamic json) {
|
||||||
|
_createdAt = json['createdAt'];
|
||||||
|
_id = json['id'];
|
||||||
|
_isUp = json['isUp'];
|
||||||
|
_message = json['message'];
|
||||||
|
_sel = json['sel'];
|
||||||
|
_source = json['source'];
|
||||||
|
_type = json['type'];
|
||||||
|
_updatedAt = json['updatedAt'];
|
||||||
|
_url = json['url'];
|
||||||
|
_version = json['version'];
|
||||||
|
}
|
||||||
|
|
||||||
|
num? _createdAt;
|
||||||
|
num? _id;
|
||||||
|
num? _isUp;
|
||||||
|
String? _message;
|
||||||
|
num? _sel;
|
||||||
|
String? _source;
|
||||||
|
String? _type;
|
||||||
|
num? _updatedAt;
|
||||||
|
String? _url;
|
||||||
|
String? _version;
|
||||||
|
|
||||||
|
UpdateVersionModel copyWith({
|
||||||
|
num? createdAt,
|
||||||
|
num? id,
|
||||||
|
num? isUp,
|
||||||
|
String? message,
|
||||||
|
num? sel,
|
||||||
|
String? source,
|
||||||
|
String? type,
|
||||||
|
num? updatedAt,
|
||||||
|
String? url,
|
||||||
|
String? version,
|
||||||
|
}) =>
|
||||||
|
UpdateVersionModel(
|
||||||
|
createdAt: createdAt ?? _createdAt,
|
||||||
|
id: id ?? _id,
|
||||||
|
isUp: isUp ?? _isUp,
|
||||||
|
message: message ?? _message,
|
||||||
|
sel: sel ?? _sel,
|
||||||
|
source: source ?? _source,
|
||||||
|
type: type ?? _type,
|
||||||
|
updatedAt: updatedAt ?? _updatedAt,
|
||||||
|
url: url ?? _url,
|
||||||
|
version: version ?? _version,
|
||||||
|
);
|
||||||
|
|
||||||
|
num? get createdAt => _createdAt;
|
||||||
|
|
||||||
|
num? get id => _id;
|
||||||
|
|
||||||
|
num? get isUp => _isUp;
|
||||||
|
|
||||||
|
String? get message => _message;
|
||||||
|
|
||||||
|
num? get sel => _sel;
|
||||||
|
|
||||||
|
String? get source => _source;
|
||||||
|
|
||||||
|
String? get type => _type;
|
||||||
|
|
||||||
|
num? get updatedAt => _updatedAt;
|
||||||
|
|
||||||
|
String? get url => _url;
|
||||||
|
|
||||||
|
String? get version => _version;
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final map = <String, dynamic>{};
|
||||||
|
map['createdAt'] = _createdAt;
|
||||||
|
map['id'] = _id;
|
||||||
|
map['isUp'] = _isUp;
|
||||||
|
map['message'] = _message;
|
||||||
|
map['sel'] = _sel;
|
||||||
|
map['source'] = _source;
|
||||||
|
map['type'] = _type;
|
||||||
|
map['updatedAt'] = _updatedAt;
|
||||||
|
map['url'] = _url;
|
||||||
|
map['version'] = _version;
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -49,6 +49,8 @@ class HomeViewModel extends BaseUIModel {
|
||||||
|
|
||||||
Future.delayed(const Duration(milliseconds: 700), () {
|
Future.delayed(const Duration(milliseconds: 700), () {
|
||||||
_checkLogin();
|
_checkLogin();
|
||||||
|
|
||||||
|
_checkAppVersion();
|
||||||
});
|
});
|
||||||
|
|
||||||
EventManager.addListener<CallStatusChangeEvent>(this, (event) {
|
EventManager.addListener<CallStatusChangeEvent>(this, (event) {
|
||||||
|
|
@ -88,6 +90,10 @@ class HomeViewModel extends BaseUIModel {
|
||||||
yjPrint("is login $flag");
|
yjPrint("is login $flag");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_checkAppVersion() {
|
||||||
|
AppManager.checkAppVersion();
|
||||||
|
}
|
||||||
|
|
||||||
void setIndex(int index) {
|
void setIndex(int index) {
|
||||||
if (_currentIndex == index) {
|
if (_currentIndex == index) {
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,8 @@ import '../common/base/provider.dart';
|
||||||
class OrderView extends BaseUI {
|
class OrderView extends BaseUI {
|
||||||
@override
|
@override
|
||||||
Widget buildBody(BuildContext context) {
|
Widget buildBody(BuildContext context) {
|
||||||
return Container(
|
return const Center(
|
||||||
child: Center(
|
child: Text("Order"),
|
||||||
child: Text("Order"),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:typed_data';
|
|
||||||
|
|
||||||
import 'package:cashier_reserve/common/encrypt/pwd.dart';
|
import 'package:cashier_reserve/common/encrypt/pwd.dart';
|
||||||
import 'package:cashier_reserve/common/manager/app_manager.dart';
|
import 'package:cashier_reserve/common/manager/app_manager.dart';
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
import 'package:cashier_reserve/common/request/request_manager.dart';
|
||||||
|
import 'package:cashier_reserve/data_model/version/update_version_model.dart';
|
||||||
|
|
||||||
|
class VersionModel {
|
||||||
|
static Future<UpdateVersionModel?> requestNewVersionInfo() async {
|
||||||
|
final r = await RequestManager.get("/api/tbVersion/findBySource", params: {"source": "电话机"});
|
||||||
|
if (r is Map) {
|
||||||
|
return UpdateVersionModel.fromJson(r);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,217 @@
|
||||||
|
|
||||||
|
import 'package:cashier_reserve/common/print/print.dart';
|
||||||
|
import 'package:cashier_reserve/data_model/version/update_version_model.dart';
|
||||||
|
import 'package:dio/dio.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:path_provider/path_provider.dart';
|
||||||
|
import 'package:percent_indicator/percent_indicator.dart';
|
||||||
|
|
||||||
|
class UpdateVersionView extends StatefulWidget {
|
||||||
|
final UpdateVersionModel versionModel;
|
||||||
|
|
||||||
|
const UpdateVersionView({super.key, required this.versionModel});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<StatefulWidget> createState() {
|
||||||
|
return _UpdateVersionViewState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _UpdateVersionViewState extends State<UpdateVersionView> {
|
||||||
|
DateTime? lastPopTime;
|
||||||
|
|
||||||
|
double progress = 0;
|
||||||
|
String progressText = "0%";
|
||||||
|
|
||||||
|
bool isDownload = false;
|
||||||
|
|
||||||
|
// 用于控制下载任务取消的CancelToken
|
||||||
|
CancelToken? _cancelToken;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_cancelToken?.cancel();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return PopScope(
|
||||||
|
canPop: (widget.versionModel.isUp ?? 0) != 0,
|
||||||
|
onPopInvokedWithResult: (didPop, result) async {
|
||||||
|
// 点击返回键的操作
|
||||||
|
if (lastPopTime == null ||
|
||||||
|
DateTime.now().difference(lastPopTime!) >
|
||||||
|
const Duration(seconds: 2)) {
|
||||||
|
lastPopTime = DateTime.now();
|
||||||
|
// Utils.toast('再按一次退出', context);
|
||||||
|
} else {
|
||||||
|
lastPopTime = DateTime.now();
|
||||||
|
// 退出app
|
||||||
|
await SystemChannels.platform.invokeMethod('SystemNavigator.pop');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: Scaffold(
|
||||||
|
backgroundColor: Colors.black.withOpacity(0.2),
|
||||||
|
body: GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
FocusScope.of(context).requestFocus(FocusNode());
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
width: MediaQuery.of(context).size.width,
|
||||||
|
height: MediaQuery.of(context).size.height,
|
||||||
|
color: const Color(0x55000000),
|
||||||
|
child: Center(
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.fromLTRB(30, 30, 30, 30),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
borderRadius: BorderRadius.circular(10),
|
||||||
|
),
|
||||||
|
width: 400,
|
||||||
|
// height: 400,
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
const Text(
|
||||||
|
"发现新版本",
|
||||||
|
style:
|
||||||
|
TextStyle(fontSize: 22, color: Color(0xff333333)),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 20,
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
widget.versionModel.message ?? "",
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 16, color: Color(0xff666666)),
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 20,
|
||||||
|
),
|
||||||
|
isDownload
|
||||||
|
? LinearPercentIndicator(
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
|
animation: false,
|
||||||
|
lineHeight: 20.0,
|
||||||
|
// animationDuration: 2500,
|
||||||
|
percent: progress,
|
||||||
|
center: Text(progressText),
|
||||||
|
// linearStrokeCap: LinearStrokeCap.roundAll,
|
||||||
|
progressColor: Colors.green,
|
||||||
|
)
|
||||||
|
: Container(),
|
||||||
|
isDownload
|
||||||
|
? const SizedBox(
|
||||||
|
height: 20,
|
||||||
|
)
|
||||||
|
: Container(),
|
||||||
|
_buildActionViews(context),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildActionViews(BuildContext context) {
|
||||||
|
bool isMustUpdate = widget.versionModel.isUp == 1;
|
||||||
|
return Row(mainAxisAlignment: MainAxisAlignment.center, children: [
|
||||||
|
isMustUpdate
|
||||||
|
? Container()
|
||||||
|
: ElevatedButton(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
style: ButtonStyle(
|
||||||
|
backgroundColor: WidgetStateProperty.all(Colors.white),
|
||||||
|
foregroundColor:
|
||||||
|
WidgetStateProperty.all(const Color(0xff666666)),
|
||||||
|
minimumSize: WidgetStateProperty.all(const Size(100, 40)),
|
||||||
|
shape: WidgetStateProperty.all(const RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(20)),
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
child: const Text("跳过"),
|
||||||
|
),
|
||||||
|
isMustUpdate
|
||||||
|
? Container()
|
||||||
|
: const SizedBox(
|
||||||
|
width: 20,
|
||||||
|
),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () {
|
||||||
|
startDownload();
|
||||||
|
},
|
||||||
|
style: ButtonStyle(
|
||||||
|
backgroundColor: WidgetStateProperty.all(Colors.blue),
|
||||||
|
foregroundColor: WidgetStateProperty.all(Colors.white),
|
||||||
|
minimumSize:
|
||||||
|
WidgetStateProperty.all(Size(isMustUpdate ? 200 : 100, 40)),
|
||||||
|
shape: WidgetStateProperty.all(const RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(20)),
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
child: const Text("立即更新"),
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
startDownload() async {
|
||||||
|
setState(() {
|
||||||
|
isDownload = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
String fileUrl = widget.versionModel.url ?? "";
|
||||||
|
if (fileUrl.isEmpty) {
|
||||||
|
yjPrint("下载地址为空");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_cancelToken?.cancel();
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
progress = 0.0;
|
||||||
|
progressText = "0.0%";
|
||||||
|
});
|
||||||
|
|
||||||
|
yjPrint("fileUrl: $fileUrl");
|
||||||
|
|
||||||
|
Dio dio = Dio();
|
||||||
|
try {
|
||||||
|
String savePath = await getPhoneLocalPath();
|
||||||
|
String appName = "file.apk";
|
||||||
|
_cancelToken = CancelToken(); // 创建CancelToken对象
|
||||||
|
await dio.download(
|
||||||
|
fileUrl, "$savePath$appName", onReceiveProgress: (received, total) {
|
||||||
|
if (total != -1) {
|
||||||
|
///当前下载的百分比例
|
||||||
|
double currentProgress = received / total;
|
||||||
|
setState(() {
|
||||||
|
progressText = "${(currentProgress * 100).toStringAsFixed(2)}%";
|
||||||
|
progress = double.parse(currentProgress.toStringAsFixed(2));
|
||||||
|
});
|
||||||
|
yjPrint(progress);
|
||||||
|
|
||||||
|
_cancelToken = null;
|
||||||
|
}
|
||||||
|
}, cancelToken: _cancelToken);
|
||||||
|
|
||||||
|
yjPrint("文件下载成功");
|
||||||
|
} catch (e) {
|
||||||
|
yjPrint("文件下载失败:$e");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<String> getPhoneLocalPath() async {
|
||||||
|
final directory = await getExternalStorageDirectory();
|
||||||
|
return directory?.path ?? '';
|
||||||
|
}
|
||||||
|
}
|
||||||
24
pubspec.lock
24
pubspec.lock
|
|
@ -418,6 +418,22 @@ packages:
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.0"
|
version: "2.1.0"
|
||||||
|
package_info_plus:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: package_info_plus
|
||||||
|
sha256: da8d9ac8c4b1df253d1a328b7bf01ae77ef132833479ab40763334db13b91cce
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "8.1.1"
|
||||||
|
package_info_plus_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: package_info_plus_platform_interface
|
||||||
|
sha256: ac1f4a4847f1ade8e6a87d1f39f5d7c67490738642e2542f559ec38c37489a66
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "3.0.1"
|
||||||
path:
|
path:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
@ -783,6 +799,14 @@ packages:
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.0"
|
version: "1.1.0"
|
||||||
|
win32:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: win32
|
||||||
|
sha256: "8b338d4486ab3fbc0ba0db9f9b4f5239b6697fcee427939a40e720cbb9ee0a69"
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "5.9.0"
|
||||||
xdg_directories:
|
xdg_directories:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,7 @@ dependencies:
|
||||||
pointycastle: ^3.9.1
|
pointycastle: ^3.9.1
|
||||||
url_launcher: ^6.3.1
|
url_launcher: ^6.3.1
|
||||||
easy_refresh: ^3.4.0
|
easy_refresh: ^3.4.0
|
||||||
|
package_info_plus: ^8.1.1
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue