Compare commits
6 Commits
dev
...
d5083c1939
| Author | SHA1 | Date | |
|---|---|---|---|
| d5083c1939 | |||
| 35bd3a78a5 | |||
| 032e60d362 | |||
| 45f5035d1b | |||
| f792915429 | |||
| edbacc502b |
|
Before Width: | Height: | Size: 6.0 KiB |
BIN
ln_jq_app/android/app/src/main/res/mipmap-xhdpi/logo.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
@@ -13,7 +13,7 @@
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"filename" : "Icon-App-29x29@1x.png",
|
||||
"filename" : "Icon-App-29x29 1.png",
|
||||
"idiom" : "iphone",
|
||||
"scale" : "1x",
|
||||
"size" : "29x29"
|
||||
@@ -31,25 +31,25 @@
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"filename" : "Icon-App-80x80.jpg",
|
||||
"filename" : "Icon-App-80x80.png",
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"filename" : "Icon-App-120x120.jpg",
|
||||
"filename" : "Icon-App-120x120.png",
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"filename" : "Icon-App-120x120 1.jpg",
|
||||
"filename" : "Icon-App-120x120 1.png",
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "60x60"
|
||||
},
|
||||
{
|
||||
"filename" : "Icon-App-180.jpg",
|
||||
"filename" : "Icon-App-180.png",
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x",
|
||||
"size" : "60x60"
|
||||
@@ -61,19 +61,19 @@
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"filename" : "Icon-App-20x20@2x.png",
|
||||
"filename" : "Icon-App-20x20@2x 1.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"filename" : "Icon-App-29x29@1x.png",
|
||||
"filename" : "Icon-App-29x29.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "1x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"filename" : "Icon-App-29x29@2x.png",
|
||||
"filename" : "Icon-App-29x29@2x 1.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "2x",
|
||||
"size" : "29x29"
|
||||
@@ -91,7 +91,7 @@
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"filename" : "Icon-App-76x76@1x.png",
|
||||
"filename" : "Icon-App-76x76.png",
|
||||
"idiom" : "ipad",
|
||||
"scale" : "1x",
|
||||
"size" : "76x76"
|
||||
|
||||
|
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 4.0 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 4.0 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 6.0 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 509 B After Width: | Height: | Size: 465 B |
|
After Width: | Height: | Size: 849 B |
|
Before Width: | Height: | Size: 848 B After Width: | Height: | Size: 849 B |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 613 B |
|
After Width: | Height: | Size: 613 B |
|
Before Width: | Height: | Size: 707 B |
|
After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 2.6 KiB |
@@ -8,11 +8,11 @@ class AppTheme {
|
||||
static const Color themeColor = Color(0xFF017137);
|
||||
|
||||
//是否开放域名切换
|
||||
static const bool is_show_host = true;
|
||||
static const bool is_show_host = false;
|
||||
|
||||
//http://192.168.110.222:8080/
|
||||
//http://192.168.110.44:8080/
|
||||
static String test_service_url = "https://beta-esg.api.lnh2e.com/";
|
||||
static String test_service_url = "http://47.101.201.13:8443/api/";
|
||||
static const String release_service_url = "";
|
||||
|
||||
//加氢站相关查询
|
||||
|
||||
@@ -17,7 +17,7 @@ void main() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
WidgetsBinding widgetsBinding = await init(
|
||||
isDebug: true,
|
||||
isDebug: false,
|
||||
logTag: '小羚羚',
|
||||
supportedLocales: [const Locale('zh', 'CN')],
|
||||
);
|
||||
@@ -35,7 +35,7 @@ void main() async {
|
||||
// 设计稿尺寸 单位:dp
|
||||
designSize: const Size(390, 844),
|
||||
// Getx Log
|
||||
enableLog: true,
|
||||
enableLog: false,
|
||||
// 默认的跳转动画
|
||||
defaultTransition: Transition.rightToLeft,
|
||||
// 主题模式
|
||||
@@ -71,6 +71,9 @@ void initHttpSet() {
|
||||
HttpService.to.dio.interceptors.add(TokenInterceptor(tokenKey: 'asoco-token'));
|
||||
HttpService.to.setOnResponseHandler((response) async {
|
||||
try {
|
||||
if (response.data == null) {
|
||||
return null;
|
||||
}
|
||||
final baseModel = BaseModel.fromJson(response.data);
|
||||
if (baseModel.code == 0 || baseModel.code == 200) {
|
||||
return null;
|
||||
|
||||
@@ -78,15 +78,11 @@ class ReservationPage extends GetView<ReservationController> {
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Flexible(
|
||||
child: Text(
|
||||
controller.name,
|
||||
style: const TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
Text(
|
||||
controller.name,
|
||||
style: const TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
@@ -102,11 +98,12 @@ class ReservationPage extends GetView<ReservationController> {
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
onPressed: () async {
|
||||
onPressed: () async{
|
||||
var scanResult = await Get.to(() => const MessagePage());
|
||||
if (scanResult == null) {
|
||||
controller.msgNotice();
|
||||
}
|
||||
|
||||
},
|
||||
style: IconButton.styleFrom(
|
||||
backgroundColor: Colors.grey[100],
|
||||
@@ -114,7 +111,9 @@ class ReservationPage extends GetView<ReservationController> {
|
||||
),
|
||||
icon: Badge(
|
||||
smallSize: 8,
|
||||
backgroundColor: controller.isNotice ? Colors.red : Colors.transparent,
|
||||
backgroundColor: controller.isNotice
|
||||
? Colors.red
|
||||
: Colors.transparent,
|
||||
child: const Icon(
|
||||
Icons.notifications_outlined,
|
||||
color: Colors.black87,
|
||||
@@ -233,17 +232,12 @@ class ReservationPage extends GetView<ReservationController> {
|
||||
label,
|
||||
style: TextStyle(color: Colors.grey, fontSize: 11.sp),
|
||||
),
|
||||
Expanded(
|
||||
child: Text(
|
||||
value,
|
||||
textAlign: TextAlign.right,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
maxLines: 1,
|
||||
style: TextStyle(
|
||||
color: const Color(0xFF333333),
|
||||
fontSize: 12.sp,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
Text(
|
||||
value,
|
||||
style: TextStyle(
|
||||
color: Color(0xFF333333),
|
||||
fontSize: 12.sp,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -521,15 +515,14 @@ class ReservationPage extends GetView<ReservationController> {
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: kPrimaryColor,
|
||||
minimumSize: const Size(double.infinity, 50),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
|
||||
),
|
||||
child: const Text("发送广播", style: TextStyle(color: Colors.white)),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
@@ -29,14 +29,8 @@ class HomeController extends GetxController with BaseControllerMixin {
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
|
||||
// 检查是否同意过隐私政策,只有同意后才初始化推送
|
||||
if (StorageService.to.isPrivacyAgreed) {
|
||||
requestPermission();
|
||||
initAliyunPush();
|
||||
addPushCallback();
|
||||
}
|
||||
|
||||
initAliyunPush();
|
||||
addPushCallback();
|
||||
FlutterNativeSplash.remove();
|
||||
log('page-init');
|
||||
|
||||
@@ -158,6 +152,7 @@ class HomeController extends GetxController with BaseControllerMixin {
|
||||
|
||||
// 根据登录状态和登录渠道返回不同的首页
|
||||
Widget getHomePage() {
|
||||
requestPermission();
|
||||
if (StorageService.to.isLoggedIn) {
|
||||
if (StorageService.to.loginChannel == LoginChannel.station) {
|
||||
return B_BaseWidgetsPage();
|
||||
|
||||
@@ -6,7 +6,6 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:getx_scaffold/getx_scaffold.dart';
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
import 'package:ln_jq_app/common/login_util.dart';
|
||||
import 'package:ln_jq_app/common/model/base_model.dart';
|
||||
import 'package:ln_jq_app/common/model/vehicle_info.dart';
|
||||
@@ -18,8 +17,6 @@ import 'package:ln_jq_app/pages/login/controller.dart';
|
||||
import 'package:ln_jq_app/pages/url_host/view.dart';
|
||||
import 'package:ln_jq_app/storage_service.dart';
|
||||
|
||||
import '../c_page/message/view.dart';
|
||||
|
||||
class LoginPage extends StatefulWidget {
|
||||
const LoginPage({super.key});
|
||||
|
||||
@@ -33,7 +30,6 @@ class _LoginPageState extends State<LoginPage> with SingleTickerProviderStateMix
|
||||
bool _obscureText = true;
|
||||
bool _rememberPassword = true;
|
||||
bool _credentialsLoaded = false;
|
||||
bool isPushInitialized = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@@ -392,28 +388,13 @@ class _LoginPageState extends State<LoginPage> with SingleTickerProviderStateMix
|
||||
content: _buildDialogContent(),
|
||||
confirmText: '同意',
|
||||
cancelText: '拒绝',
|
||||
onConfirm: () async {
|
||||
onConfirm: () {
|
||||
_isAgreed = true;
|
||||
controller.updateUi();
|
||||
|
||||
// 保存隐私政策同意状态
|
||||
await StorageService.to.savePrivacyAgreed(true);
|
||||
|
||||
// 申请通知权限
|
||||
await _requestNotificationPermission();
|
||||
|
||||
// 初始化阿里云推送
|
||||
await _initPushService();
|
||||
},
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果已经同意过,但推送还没初始化,则初始化
|
||||
if (!isPushInitialized) {
|
||||
await _initPushService();
|
||||
}
|
||||
|
||||
_tabController.index == 0
|
||||
? _handleDriverLogin(controller)
|
||||
: _handleStationLogin(controller);
|
||||
@@ -555,62 +536,6 @@ class _LoginPageState extends State<LoginPage> with SingleTickerProviderStateMix
|
||||
addAlias(identifier);
|
||||
}
|
||||
|
||||
// 申请通知权限
|
||||
Future<void> _requestNotificationPermission() async {
|
||||
final PermissionStatus status = await Permission.notification.request();
|
||||
if (status.isGranted) {
|
||||
Logger.d('通知权限已授予');
|
||||
} else if (status.isPermanentlyDenied) {
|
||||
Logger.d('通知权限被永久拒绝');
|
||||
}
|
||||
}
|
||||
|
||||
// 初始化推送服务
|
||||
Future<void> _initPushService() async {
|
||||
try {
|
||||
final _aliyunPush = AliyunPushFlutter();
|
||||
|
||||
// 初始化推送
|
||||
final String appKey = Platform.isIOS ? AppTheme.ios_key : AppTheme.android_key;
|
||||
final String appSecret = Platform.isIOS
|
||||
? AppTheme.ios_appsecret
|
||||
: AppTheme.android_appsecret;
|
||||
|
||||
final result = await _aliyunPush.initPush(appKey: appKey, appSecret: appSecret);
|
||||
if (result['code'] != kAliyunPushSuccessCode) {
|
||||
Logger.d('推送初始化失败: ${result['errorMsg']}');
|
||||
return;
|
||||
}
|
||||
|
||||
// 配置平台特定设置
|
||||
if (Platform.isIOS) {
|
||||
await _aliyunPush.showIOSNoticeWhenForeground(true);
|
||||
} else if (Platform.isAndroid) {
|
||||
await _aliyunPush.setNotificationInGroup(true);
|
||||
await _aliyunPush.createAndroidChannel(
|
||||
"xll_push_android",
|
||||
'新消息通知',
|
||||
4,
|
||||
'用于接收加氢站实时状态提醒',
|
||||
);
|
||||
}
|
||||
|
||||
// 添加推送回调
|
||||
_aliyunPush.addMessageReceiver(
|
||||
onNotificationOpened: _onNotificationOpened,
|
||||
);
|
||||
|
||||
isPushInitialized = true;
|
||||
Logger.d('推送服务初始化成功');
|
||||
} catch (e) {
|
||||
Logger.d('推送服务初始化异常: $e');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _onNotificationOpened(Map<dynamic, dynamic> message) async {
|
||||
await Get.to(() => const MessagePage());
|
||||
}
|
||||
|
||||
final _aliyunPush = AliyunPushFlutter();
|
||||
|
||||
void addAlias(String alias) async {
|
||||
|
||||
@@ -25,14 +25,11 @@ class StorageService extends GetxService {
|
||||
static const String _stationAccountKey = 'station_account';
|
||||
static const String _stationPasswordKey = 'station_password';
|
||||
|
||||
// 新增:用于标记”绑定车辆”弹窗是否已在本会话中显示过
|
||||
// 新增:用于标记“绑定车辆”弹窗是否已在本会话中显示过
|
||||
static const String _bindDialogShownKey = 'bind_vehicle_dialog_shown';
|
||||
|
||||
static const String _hostUrlKey = 'host_url';
|
||||
|
||||
// 隐私政策相关
|
||||
static const String _privacyAgreedKey = 'privacy_agreed';
|
||||
|
||||
static StorageService get to => Get.find();
|
||||
|
||||
Future<StorageService> init() async {
|
||||
@@ -66,12 +63,9 @@ class StorageService extends GetxService {
|
||||
|
||||
String? get stationPassword => _box.read<String?>(_stationPasswordKey);
|
||||
|
||||
// 新增:获取”绑定车辆”弹窗是否已显示的标志
|
||||
// 新增:获取“绑定车辆”弹窗是否已显示的标志
|
||||
bool get hasShownBindVehicleDialog => _box.read<bool>(_bindDialogShownKey) ?? false;
|
||||
|
||||
// 获取隐私政策是否已同意
|
||||
bool get isPrivacyAgreed => _box.read<bool>(_privacyAgreedKey) ?? false;
|
||||
|
||||
VehicleInfo? get vehicleInfo {
|
||||
final vehicleJson = _box.read<String?>(_vehicleInfoKey);
|
||||
if (vehicleJson != null) {
|
||||
@@ -116,11 +110,6 @@ class StorageService extends GetxService {
|
||||
await _box.write(_stationPasswordKey, password);
|
||||
}
|
||||
|
||||
// 保存隐私政策同意状态
|
||||
Future<void> savePrivacyAgreed(bool agreed) async {
|
||||
await _box.write(_privacyAgreedKey, agreed);
|
||||
}
|
||||
|
||||
// 新增:标记“绑定车辆”弹窗已显示
|
||||
Future<void> markBindVehicleDialogAsShown() async {
|
||||
await _box.write(_bindDialogShownKey, true);
|
||||
|
||||