Compare commits
8 Commits
d5083c1939
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| a497bc6469 | |||
| 3f282d15c1 | |||
| 03b35f660c | |||
| 9b6f93ca95 | |||
| eb41ecaec4 | |||
| 384de27f2c | |||
| 84b174c4a5 | |||
| 02e1946319 |
@@ -61,48 +61,6 @@
|
|||||||
<meta-data
|
<meta-data
|
||||||
android:name="com.alibaba.app.appsecret"
|
android:name="com.alibaba.app.appsecret"
|
||||||
android:value="39628204345a4240b5b645b68a5896c7" />
|
android:value="39628204345a4240b5b645b68a5896c7" />
|
||||||
<!-- 华为通道的参数appid -->
|
|
||||||
<meta-data
|
|
||||||
android:name="com.huawei.hms.client.appid"
|
|
||||||
android:value="" />
|
|
||||||
|
|
||||||
<!-- vivo通道的参数api_key为appkey -->
|
|
||||||
<meta-data
|
|
||||||
android:name="com.vivo.push.api_key"
|
|
||||||
android:value="" />
|
|
||||||
<meta-data
|
|
||||||
android:name="com.vivo.push.app_id"
|
|
||||||
android:value="" />
|
|
||||||
|
|
||||||
<!-- honor通道的参数-->
|
|
||||||
<meta-data
|
|
||||||
android:name="com.hihonor.push.app_id"
|
|
||||||
android:value="" />
|
|
||||||
|
|
||||||
<!-- oppo -->
|
|
||||||
<meta-data
|
|
||||||
android:name="com.oppo.push.key"
|
|
||||||
android:value="" />
|
|
||||||
<meta-data
|
|
||||||
android:name="com.oppo.push.secret"
|
|
||||||
android:value="" />
|
|
||||||
|
|
||||||
<!-- 小米-->
|
|
||||||
<meta-data
|
|
||||||
android:name="com.xiaomi.push.id"
|
|
||||||
android:value="id=2222222222222222222" />
|
|
||||||
<meta-data
|
|
||||||
android:name="com.xiaomi.push.key"
|
|
||||||
android:value="id=5555555555555" />
|
|
||||||
|
|
||||||
<!-- 魅族-->
|
|
||||||
<meta-data
|
|
||||||
android:name="com.meizu.push.id"
|
|
||||||
android:value="" />
|
|
||||||
<meta-data
|
|
||||||
android:name="com.meizu.push.key"
|
|
||||||
android:value="" />
|
|
||||||
|
|
||||||
|
|
||||||
<!-- 接收推送消息 -->
|
<!-- 接收推送消息 -->
|
||||||
<receiver
|
<receiver
|
||||||
|
|||||||
@@ -21,9 +21,7 @@
|
|||||||
.amap-callamap,
|
.amap-callamap,
|
||||||
.amap-lib-driving-callBtn,
|
.amap-lib-driving-callBtn,
|
||||||
.amap-copyright,
|
.amap-copyright,
|
||||||
.amap-logo {
|
.amap-logo{bottom: 60px}
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 去除高德默认的 label 边框 and 背景 */
|
/* 去除高德默认的 label 边框 and 背景 */
|
||||||
.amap-marker-label {
|
.amap-marker-label {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
PODS:
|
PODS:
|
||||||
- AlicloudELS (1.0.3)
|
- AlicloudELS (1.0.3)
|
||||||
- AlicloudPush (3.2.3):
|
- AlicloudPush (3.2.3):
|
||||||
- AlicloudELS (= 1.0.3)
|
- AlicloudELS (~> 1.0.3)
|
||||||
- AlicloudUTDID (~> 1.0)
|
- AlicloudUTDID (~> 1.0)
|
||||||
- AlicloudUTDID (1.6.1)
|
- AlicloudUTDID (1.6.1)
|
||||||
- aliyun_push_flutter (0.0.1):
|
- aliyun_push_flutter (0.0.1):
|
||||||
@@ -115,11 +115,11 @@ EXTERNAL SOURCES:
|
|||||||
|
|
||||||
SPEC CHECKSUMS:
|
SPEC CHECKSUMS:
|
||||||
AlicloudELS: fbf821383330465a5af84a033f36f263ae46ca41
|
AlicloudELS: fbf821383330465a5af84a033f36f263ae46ca41
|
||||||
AlicloudPush: 95150880af380f64cf1741f5586047c17d36c1d9
|
AlicloudPush: 52cbf38ffc20c07f039cbc72d5738745fd986215
|
||||||
AlicloudUTDID: 5d2f22d50e11eecd38f30bc7a48c71925ea90976
|
AlicloudUTDID: 5d2f22d50e11eecd38f30bc7a48c71925ea90976
|
||||||
aliyun_push_flutter: 0fc2f048a08687ef256c0cfdd72dd7a550ef3347
|
aliyun_push_flutter: 0fc2f048a08687ef256c0cfdd72dd7a550ef3347
|
||||||
connectivity_plus: cb623214f4e1f6ef8fe7403d580fdad517d2f7dd
|
connectivity_plus: cb623214f4e1f6ef8fe7403d580fdad517d2f7dd
|
||||||
device_info_plus: 71ffc6ab7634ade6267c7a93088ed7e4f74e5896
|
device_info_plus: 21fcca2080fbcd348be798aa36c3e5ed849eefbe
|
||||||
Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467
|
Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467
|
||||||
flutter_app_update: 816fdb2e30e4832a7c45e3f108d391c42ef040a9
|
flutter_app_update: 816fdb2e30e4832a7c45e3f108d391c42ef040a9
|
||||||
flutter_inappwebview_ios: b89ba3482b96fb25e00c967aae065701b66e9b99
|
flutter_inappwebview_ios: b89ba3482b96fb25e00c967aae065701b66e9b99
|
||||||
|
|||||||
@@ -1,9 +1,13 @@
|
|||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:flutter/gestures.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:getx_scaffold/getx_scaffold.dart';
|
import 'package:getx_scaffold/getx_scaffold.dart';
|
||||||
import 'package:ln_jq_app/common/login_util.dart';
|
import 'package:ln_jq_app/common/login_util.dart';
|
||||||
import 'package:ln_jq_app/pages/b_page/reservation/controller.dart';
|
import 'package:ln_jq_app/pages/b_page/reservation/controller.dart';
|
||||||
import 'package:ln_jq_app/pages/c_page/message/view.dart';
|
import 'package:ln_jq_app/pages/c_page/message/view.dart';
|
||||||
|
import 'package:ln_jq_app/pages/common/webview/view.dart';
|
||||||
|
|
||||||
class ReservationPage extends GetView<ReservationController> {
|
class ReservationPage extends GetView<ReservationController> {
|
||||||
const ReservationPage({super.key});
|
const ReservationPage({super.key});
|
||||||
@@ -36,6 +40,30 @@ class ReservationPage extends GetView<ReservationController> {
|
|||||||
_buildSystemTips(),
|
_buildSystemTips(),
|
||||||
SizedBox(height: 24),
|
SizedBox(height: 24),
|
||||||
_buildLogoutButton(),
|
_buildLogoutButton(),
|
||||||
|
SizedBox(height: 15.h),
|
||||||
|
Text.rich(
|
||||||
|
TextSpan(
|
||||||
|
style: const TextStyle(color: Colors.grey, fontSize: 13),
|
||||||
|
children: [
|
||||||
|
TextSpan(
|
||||||
|
text: '《用户协议》',
|
||||||
|
style: TextStyle(color: Colors.blue, fontSize: 13),
|
||||||
|
recognizer: TapGestureRecognizer()
|
||||||
|
..onTap = () {
|
||||||
|
openPage("用户协议", "https://lnh2e.com/user_agreement.html");
|
||||||
|
},
|
||||||
|
),
|
||||||
|
TextSpan(
|
||||||
|
text: '《隐私政策》',
|
||||||
|
style: TextStyle(color: Colors.blue, fontSize: 13),
|
||||||
|
recognizer: TapGestureRecognizer()
|
||||||
|
..onTap = () {
|
||||||
|
openPage("隐私政策", "https://lnh2e.com/privacy_agreement.html");
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
SizedBox(height: 95.h),
|
SizedBox(height: 95.h),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -48,6 +76,14 @@ class ReservationPage extends GetView<ReservationController> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void openPage(String title, String url) {
|
||||||
|
if (Platform.isIOS) {
|
||||||
|
openWebPage(url);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Get.to(() => const WebViewPage(), arguments: {'title': title, 'url': url});
|
||||||
|
}
|
||||||
|
|
||||||
/// 1. 顶部个人信息及统计栏
|
/// 1. 顶部个人信息及统计栏
|
||||||
Widget _buildTopSection(BuildContext context) {
|
Widget _buildTopSection(BuildContext context) {
|
||||||
return Container(
|
return Container(
|
||||||
@@ -78,11 +114,15 @@ class ReservationPage extends GetView<ReservationController> {
|
|||||||
children: [
|
children: [
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Flexible(
|
||||||
controller.name,
|
child: Text(
|
||||||
style: const TextStyle(
|
controller.name,
|
||||||
fontSize: 18,
|
style: const TextStyle(
|
||||||
fontWeight: FontWeight.bold,
|
fontSize: 18,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
@@ -98,12 +138,11 @@ class ReservationPage extends GetView<ReservationController> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
IconButton(
|
IconButton(
|
||||||
onPressed: () async{
|
onPressed: () async {
|
||||||
var scanResult = await Get.to(() => const MessagePage());
|
var scanResult = await Get.to(() => const MessagePage());
|
||||||
if (scanResult == null) {
|
if (scanResult == null) {
|
||||||
controller.msgNotice();
|
controller.msgNotice();
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
style: IconButton.styleFrom(
|
style: IconButton.styleFrom(
|
||||||
backgroundColor: Colors.grey[100],
|
backgroundColor: Colors.grey[100],
|
||||||
@@ -111,9 +150,7 @@ class ReservationPage extends GetView<ReservationController> {
|
|||||||
),
|
),
|
||||||
icon: Badge(
|
icon: Badge(
|
||||||
smallSize: 8,
|
smallSize: 8,
|
||||||
backgroundColor: controller.isNotice
|
backgroundColor: controller.isNotice ? Colors.red : Colors.transparent,
|
||||||
? Colors.red
|
|
||||||
: Colors.transparent,
|
|
||||||
child: const Icon(
|
child: const Icon(
|
||||||
Icons.notifications_outlined,
|
Icons.notifications_outlined,
|
||||||
color: Colors.black87,
|
color: Colors.black87,
|
||||||
@@ -232,12 +269,17 @@ class ReservationPage extends GetView<ReservationController> {
|
|||||||
label,
|
label,
|
||||||
style: TextStyle(color: Colors.grey, fontSize: 11.sp),
|
style: TextStyle(color: Colors.grey, fontSize: 11.sp),
|
||||||
),
|
),
|
||||||
Text(
|
Expanded(
|
||||||
value,
|
child: Text(
|
||||||
style: TextStyle(
|
value,
|
||||||
color: Color(0xFF333333),
|
textAlign: TextAlign.right,
|
||||||
fontSize: 12.sp,
|
overflow: TextOverflow.ellipsis,
|
||||||
fontWeight: FontWeight.bold,
|
maxLines: 1,
|
||||||
|
style: TextStyle(
|
||||||
|
color: const Color(0xFF333333),
|
||||||
|
fontSize: 12.sp,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -515,14 +557,15 @@ class ReservationPage extends GetView<ReservationController> {
|
|||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: kPrimaryColor,
|
backgroundColor: kPrimaryColor,
|
||||||
minimumSize: const Size(double.infinity, 50),
|
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)),
|
child: const Text("发送广播", style: TextStyle(color: Colors.white)),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,10 +1,15 @@
|
|||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:flutter/gestures.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:getx_scaffold/common/index.dart';
|
import 'package:getx_scaffold/common/index.dart';
|
||||||
import 'package:getx_scaffold/common/widgets/index.dart';
|
import 'package:getx_scaffold/common/widgets/index.dart';
|
||||||
import 'package:ln_jq_app/common/login_util.dart';
|
import 'package:ln_jq_app/common/login_util.dart';
|
||||||
|
import 'package:ln_jq_app/common/styles/theme.dart';
|
||||||
import 'package:ln_jq_app/pages/c_page/message/view.dart';
|
import 'package:ln_jq_app/pages/c_page/message/view.dart';
|
||||||
|
import 'package:ln_jq_app/pages/common/webview/view.dart';
|
||||||
import 'package:ln_jq_app/storage_service.dart';
|
import 'package:ln_jq_app/storage_service.dart';
|
||||||
import 'controller.dart';
|
import 'controller.dart';
|
||||||
|
|
||||||
@@ -38,6 +43,30 @@ class MinePage extends GetView<MineController> {
|
|||||||
_buildSafetyReminderCard(),
|
_buildSafetyReminderCard(),
|
||||||
SizedBox(height: 24.h),
|
SizedBox(height: 24.h),
|
||||||
_buildLogoutButton(),
|
_buildLogoutButton(),
|
||||||
|
SizedBox(height: 15.h),
|
||||||
|
Text.rich(
|
||||||
|
TextSpan(
|
||||||
|
style: const TextStyle(color: Colors.grey, fontSize: 13),
|
||||||
|
children: [
|
||||||
|
TextSpan(
|
||||||
|
text: '《用户协议》',
|
||||||
|
style: TextStyle(color: Colors.blue, fontSize: 13),
|
||||||
|
recognizer: TapGestureRecognizer()
|
||||||
|
..onTap = () {
|
||||||
|
openPage("用户协议", "https://lnh2e.com/user_agreement.html");
|
||||||
|
},
|
||||||
|
),
|
||||||
|
TextSpan(
|
||||||
|
text: '《隐私政策》',
|
||||||
|
style: TextStyle(color: Colors.blue, fontSize: 13),
|
||||||
|
recognizer: TapGestureRecognizer()
|
||||||
|
..onTap = () {
|
||||||
|
openPage("隐私政策", "https://lnh2e.com/privacy_agreement.html");
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
SizedBox(height: 95.h),
|
SizedBox(height: 95.h),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -51,6 +80,15 @@ class MinePage extends GetView<MineController> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void openPage(String title, String url) {
|
||||||
|
if (Platform.isIOS) {
|
||||||
|
openWebPage(url);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Get.to(() => const WebViewPage(), arguments: {'title': title, 'url': url});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// 构建顶部用户信息卡片
|
/// 构建顶部用户信息卡片
|
||||||
Widget _buildUserInfoCard() {
|
Widget _buildUserInfoCard() {
|
||||||
return Card(
|
return Card(
|
||||||
|
|||||||
@@ -29,8 +29,6 @@ class HomeController extends GetxController with BaseControllerMixin {
|
|||||||
@override
|
@override
|
||||||
void onInit() {
|
void onInit() {
|
||||||
super.onInit();
|
super.onInit();
|
||||||
initAliyunPush();
|
|
||||||
addPushCallback();
|
|
||||||
FlutterNativeSplash.remove();
|
FlutterNativeSplash.remove();
|
||||||
log('page-init');
|
log('page-init');
|
||||||
|
|
||||||
@@ -152,8 +150,14 @@ class HomeController extends GetxController with BaseControllerMixin {
|
|||||||
|
|
||||||
// 根据登录状态和登录渠道返回不同的首页
|
// 根据登录状态和登录渠道返回不同的首页
|
||||||
Widget getHomePage() {
|
Widget getHomePage() {
|
||||||
requestPermission();
|
|
||||||
if (StorageService.to.isLoggedIn) {
|
if (StorageService.to.isLoggedIn) {
|
||||||
|
// 检查是否同意过隐私政策,只有同意后才初始化推送
|
||||||
|
if (StorageService.to.isPrivacyAgreed) {
|
||||||
|
requestPermission();
|
||||||
|
initAliyunPush();
|
||||||
|
addPushCallback();
|
||||||
|
}
|
||||||
|
|
||||||
if (StorageService.to.loginChannel == LoginChannel.station) {
|
if (StorageService.to.loginChannel == LoginChannel.station) {
|
||||||
return B_BaseWidgetsPage();
|
return B_BaseWidgetsPage();
|
||||||
} else if (StorageService.to.loginChannel == LoginChannel.driver) {
|
} else if (StorageService.to.loginChannel == LoginChannel.driver) {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:getx_scaffold/getx_scaffold.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/login_util.dart';
|
||||||
import 'package:ln_jq_app/common/model/base_model.dart';
|
import 'package:ln_jq_app/common/model/base_model.dart';
|
||||||
import 'package:ln_jq_app/common/model/vehicle_info.dart';
|
import 'package:ln_jq_app/common/model/vehicle_info.dart';
|
||||||
@@ -17,6 +18,8 @@ import 'package:ln_jq_app/pages/login/controller.dart';
|
|||||||
import 'package:ln_jq_app/pages/url_host/view.dart';
|
import 'package:ln_jq_app/pages/url_host/view.dart';
|
||||||
import 'package:ln_jq_app/storage_service.dart';
|
import 'package:ln_jq_app/storage_service.dart';
|
||||||
|
|
||||||
|
import '../c_page/message/view.dart';
|
||||||
|
|
||||||
class LoginPage extends StatefulWidget {
|
class LoginPage extends StatefulWidget {
|
||||||
const LoginPage({super.key});
|
const LoginPage({super.key});
|
||||||
|
|
||||||
@@ -30,6 +33,7 @@ class _LoginPageState extends State<LoginPage> with SingleTickerProviderStateMix
|
|||||||
bool _obscureText = true;
|
bool _obscureText = true;
|
||||||
bool _rememberPassword = true;
|
bool _rememberPassword = true;
|
||||||
bool _credentialsLoaded = false;
|
bool _credentialsLoaded = false;
|
||||||
|
bool isPushInitialized = false;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@@ -136,9 +140,29 @@ class _LoginPageState extends State<LoginPage> with SingleTickerProviderStateMix
|
|||||||
children: [
|
children: [
|
||||||
const SizedBox(height: 30),
|
const SizedBox(height: 30),
|
||||||
// 根据 Tab 显示不同的输入框
|
// 根据 Tab 显示不同的输入框
|
||||||
_tabController.index == 0
|
!_isAgreed
|
||||||
|
? GestureDetector(
|
||||||
|
onTap: () => _handleLogin(controller),
|
||||||
|
behavior: HitTestBehavior.opaque,
|
||||||
|
child: Container(
|
||||||
|
width: double.infinity,
|
||||||
|
height: 55.h,
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 24,
|
||||||
|
),
|
||||||
|
alignment: Alignment.centerLeft,
|
||||||
|
child: Text(
|
||||||
|
"请先阅读并同意用户协议和隐私政策",
|
||||||
|
style: TextStyle(
|
||||||
|
color: Colors.grey,
|
||||||
|
fontSize: 16,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: (_tabController.index == 0
|
||||||
? _buildDriverInputFields(controller)
|
? _buildDriverInputFields(controller)
|
||||||
: _buildStationInputFields(controller),
|
: _buildStationInputFields(controller)),
|
||||||
|
|
||||||
const SizedBox(height: 30),
|
const SizedBox(height: 30),
|
||||||
// 统一登录按钮
|
// 统一登录按钮
|
||||||
@@ -146,7 +170,8 @@ class _LoginPageState extends State<LoginPage> with SingleTickerProviderStateMix
|
|||||||
|
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
buildAgreement(),
|
buildAgreement(),
|
||||||
const SizedBox(height: 40),
|
const SizedBox(height: 80),
|
||||||
|
_buildFooterSlogan(),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -155,7 +180,6 @@ class _LoginPageState extends State<LoginPage> with SingleTickerProviderStateMix
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Positioned(left: 0, right: 0, bottom: 33.h, child: _buildFooterSlogan()),
|
|
||||||
if (AppTheme.is_show_host)
|
if (AppTheme.is_show_host)
|
||||||
Positioned(
|
Positioned(
|
||||||
top: 40.h,
|
top: 40.h,
|
||||||
@@ -388,13 +412,28 @@ class _LoginPageState extends State<LoginPage> with SingleTickerProviderStateMix
|
|||||||
content: _buildDialogContent(),
|
content: _buildDialogContent(),
|
||||||
confirmText: '同意',
|
confirmText: '同意',
|
||||||
cancelText: '拒绝',
|
cancelText: '拒绝',
|
||||||
onConfirm: () {
|
onConfirm: () async {
|
||||||
_isAgreed = true;
|
_isAgreed = true;
|
||||||
controller.updateUi();
|
controller.updateUi();
|
||||||
|
|
||||||
|
// 保存隐私政策同意状态
|
||||||
|
await StorageService.to.savePrivacyAgreed(true);
|
||||||
|
|
||||||
|
// 申请通知权限
|
||||||
|
await _requestNotificationPermission();
|
||||||
|
|
||||||
|
// 初始化阿里云推送
|
||||||
|
await _initPushService();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 如果已经同意过,但推送还没初始化,则初始化
|
||||||
|
if (!isPushInitialized) {
|
||||||
|
await _initPushService();
|
||||||
|
}
|
||||||
|
|
||||||
_tabController.index == 0
|
_tabController.index == 0
|
||||||
? _handleDriverLogin(controller)
|
? _handleDriverLogin(controller)
|
||||||
: _handleStationLogin(controller);
|
: _handleStationLogin(controller);
|
||||||
@@ -456,7 +495,6 @@ class _LoginPageState extends State<LoginPage> with SingleTickerProviderStateMix
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
_processLoginResponse(responseData, "station", account);
|
_processLoginResponse(responseData, "station", account);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
dismissLoading();
|
dismissLoading();
|
||||||
@@ -520,7 +558,6 @@ class _LoginPageState extends State<LoginPage> with SingleTickerProviderStateMix
|
|||||||
Logger.d("暂时不处理 查询车辆信息失败的情况");
|
Logger.d("暂时不处理 查询车辆信息失败的情况");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
dismissLoading();
|
dismissLoading();
|
||||||
Get.offAll(() => BaseWidgetsPage());
|
Get.offAll(() => BaseWidgetsPage());
|
||||||
} else {
|
} else {
|
||||||
@@ -536,6 +573,60 @@ class _LoginPageState extends State<LoginPage> with SingleTickerProviderStateMix
|
|||||||
addAlias(identifier);
|
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();
|
final _aliyunPush = AliyunPushFlutter();
|
||||||
|
|
||||||
void addAlias(String alias) async {
|
void addAlias(String alias) async {
|
||||||
|
|||||||
@@ -1,16 +1,103 @@
|
|||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_native_splash/flutter_native_splash.dart';
|
import 'package:flutter_native_splash/flutter_native_splash.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
|
import 'package:getx_scaffold/common/components/index.dart';
|
||||||
|
import 'package:getx_scaffold/common/widgets/rich_text_x.dart';
|
||||||
import 'package:ln_jq_app/pages/home/view.dart';
|
import 'package:ln_jq_app/pages/home/view.dart';
|
||||||
import 'package:ln_jq_app/pages/login/view.dart';
|
import 'package:ln_jq_app/pages/login/view.dart';
|
||||||
import 'package:ln_jq_app/storage_service.dart';
|
import 'package:ln_jq_app/storage_service.dart';
|
||||||
|
|
||||||
|
import '../common/webview/view.dart';
|
||||||
|
|
||||||
class WelcomeController extends GetxController {
|
class WelcomeController extends GetxController {
|
||||||
@override
|
@override
|
||||||
void onReady() {
|
void onReady() {
|
||||||
super.onReady();
|
super.onReady();
|
||||||
// 移除原生闪屏页(如果有的话)
|
// 移除原生闪屏页(如果有的话)
|
||||||
FlutterNativeSplash.remove();
|
FlutterNativeSplash.remove();
|
||||||
_startTimer();
|
|
||||||
|
if (Platform.isAndroid) {
|
||||||
|
if (StorageService.to.isPrivacyAgreed) {
|
||||||
|
_startTimer();
|
||||||
|
} else {
|
||||||
|
showPrivacyDialog();
|
||||||
|
}
|
||||||
|
} else if (Platform.isIOS) {
|
||||||
|
_startTimer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void showPrivacyDialog() {
|
||||||
|
DialogX.to.showConfirmDialog(
|
||||||
|
title: "个人信息保护提示",
|
||||||
|
content: _buildDialogContent(),
|
||||||
|
confirmText: '同意',
|
||||||
|
cancelText: '不同意',
|
||||||
|
onConfirm: () async {
|
||||||
|
await StorageService.to.savePrivacyAgreed(true);
|
||||||
|
Get.offAll(() => const HomePage());
|
||||||
|
},
|
||||||
|
onCancel: () {
|
||||||
|
DialogX.to.showConfirmDialog(
|
||||||
|
title: "温馨提示",
|
||||||
|
content: RichTextX(
|
||||||
|
children: [
|
||||||
|
TextSpanItem('如果您不同意'),
|
||||||
|
TextSpanItem(
|
||||||
|
'《隐私协议》',
|
||||||
|
onTap: () => openPage("隐私政策", "https://lnh2e.com/privacy_agreement.html"),
|
||||||
|
),
|
||||||
|
TextSpanItem('和'),
|
||||||
|
TextSpanItem(
|
||||||
|
'《用户政策》',
|
||||||
|
onTap: () => openPage("用户协议", "https://lnh2e.com/user_agreement.html"),
|
||||||
|
),
|
||||||
|
TextSpanItem(
|
||||||
|
',很遗憾我们将无法为您提供服务。您需要同意以上协议后,才能使用本应用。\n\n我们将严格按照相关法律法规要求,坚决保护您的个人隐私和信息安全。',
|
||||||
|
),
|
||||||
|
TextSpanItem('\n点击“同意”按钮,表示您已知情并同意以上协议。'),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
confirmText: '同意并继续',
|
||||||
|
cancelText: '不同意',
|
||||||
|
onConfirm: () async {
|
||||||
|
await StorageService.to.savePrivacyAgreed(true);
|
||||||
|
Get.offAll(() => const HomePage());
|
||||||
|
},
|
||||||
|
onCancel: () {
|
||||||
|
SystemNavigator.pop();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildDialogContent() {
|
||||||
|
return RichTextX(
|
||||||
|
children: [
|
||||||
|
TextSpanItem('欢迎使用小羚羚!\n我们将通过'),
|
||||||
|
TextSpanItem(
|
||||||
|
'《隐私协议》',
|
||||||
|
onTap: () => openPage("隐私政策", "https://lnh2e.com/privacy_agreement.html"),
|
||||||
|
),
|
||||||
|
TextSpanItem('和'),
|
||||||
|
TextSpanItem(
|
||||||
|
'《用户政策》',
|
||||||
|
onTap: () => openPage("用户协议", "https://lnh2e.com/user_agreement.html"),
|
||||||
|
),
|
||||||
|
TextSpanItem(
|
||||||
|
',帮助您了解我们为您提供的服务、我们如何处理个人信息以及您享有的权利。我们会严格按照相关法律法规要求,采取各种安全措施来保护您的个人信息。',
|
||||||
|
),
|
||||||
|
TextSpanItem('\n点击“同意”按钮,表示您已知情并同意以上协议。'),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void openPage(String title, String url) {
|
||||||
|
Get.to(() => const WebViewPage(), arguments: {'title': title, 'url': url});
|
||||||
}
|
}
|
||||||
|
|
||||||
void _startTimer() {
|
void _startTimer() {
|
||||||
|
|||||||
@@ -25,11 +25,14 @@ class StorageService extends GetxService {
|
|||||||
static const String _stationAccountKey = 'station_account';
|
static const String _stationAccountKey = 'station_account';
|
||||||
static const String _stationPasswordKey = 'station_password';
|
static const String _stationPasswordKey = 'station_password';
|
||||||
|
|
||||||
// 新增:用于标记“绑定车辆”弹窗是否已在本会话中显示过
|
// 新增:用于标记”绑定车辆”弹窗是否已在本会话中显示过
|
||||||
static const String _bindDialogShownKey = 'bind_vehicle_dialog_shown';
|
static const String _bindDialogShownKey = 'bind_vehicle_dialog_shown';
|
||||||
|
|
||||||
static const String _hostUrlKey = 'host_url';
|
static const String _hostUrlKey = 'host_url';
|
||||||
|
|
||||||
|
// 隐私政策相关
|
||||||
|
static const String _privacyAgreedKey = 'privacy_agreed';
|
||||||
|
|
||||||
static StorageService get to => Get.find();
|
static StorageService get to => Get.find();
|
||||||
|
|
||||||
Future<StorageService> init() async {
|
Future<StorageService> init() async {
|
||||||
@@ -63,9 +66,12 @@ class StorageService extends GetxService {
|
|||||||
|
|
||||||
String? get stationPassword => _box.read<String?>(_stationPasswordKey);
|
String? get stationPassword => _box.read<String?>(_stationPasswordKey);
|
||||||
|
|
||||||
// 新增:获取“绑定车辆”弹窗是否已显示的标志
|
// 新增:获取”绑定车辆”弹窗是否已显示的标志
|
||||||
bool get hasShownBindVehicleDialog => _box.read<bool>(_bindDialogShownKey) ?? false;
|
bool get hasShownBindVehicleDialog => _box.read<bool>(_bindDialogShownKey) ?? false;
|
||||||
|
|
||||||
|
// 获取隐私政策是否已同意
|
||||||
|
bool get isPrivacyAgreed => _box.read<bool>(_privacyAgreedKey) ?? false;
|
||||||
|
|
||||||
VehicleInfo? get vehicleInfo {
|
VehicleInfo? get vehicleInfo {
|
||||||
final vehicleJson = _box.read<String?>(_vehicleInfoKey);
|
final vehicleJson = _box.read<String?>(_vehicleInfoKey);
|
||||||
if (vehicleJson != null) {
|
if (vehicleJson != null) {
|
||||||
@@ -110,6 +116,11 @@ class StorageService extends GetxService {
|
|||||||
await _box.write(_stationPasswordKey, password);
|
await _box.write(_stationPasswordKey, password);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 保存隐私政策同意状态
|
||||||
|
Future<void> savePrivacyAgreed(bool agreed) async {
|
||||||
|
await _box.write(_privacyAgreedKey, agreed);
|
||||||
|
}
|
||||||
|
|
||||||
// 新增:标记“绑定车辆”弹窗已显示
|
// 新增:标记“绑定车辆”弹窗已显示
|
||||||
Future<void> markBindVehicleDialogAsShown() async {
|
Future<void> markBindVehicleDialogAsShown() async {
|
||||||
await _box.write(_bindDialogShownKey, true);
|
await _box.write(_bindDialogShownKey, true);
|
||||||
|
|||||||
@@ -162,13 +162,13 @@ packages:
|
|||||||
source: hosted
|
source: hosted
|
||||||
version: "3.2.4"
|
version: "3.2.4"
|
||||||
device_info_plus:
|
device_info_plus:
|
||||||
dependency: transitive
|
dependency: "direct overridden"
|
||||||
description:
|
description:
|
||||||
name: device_info_plus
|
name: device_info_plus
|
||||||
sha256: a7fd703482b391a87d60b6061d04dfdeab07826b96f9abd8f5ed98068acc0074
|
sha256: "4df8babf73058181227e18b08e6ea3520cf5fc5d796888d33b7cb0f33f984b7c"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "10.1.2"
|
version: "12.3.0"
|
||||||
device_info_plus_platform_interface:
|
device_info_plus_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -741,14 +741,6 @@ packages:
|
|||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.0"
|
version: "2.0.0"
|
||||||
mobile_scanner:
|
|
||||||
dependency: "direct main"
|
|
||||||
description:
|
|
||||||
name: mobile_scanner
|
|
||||||
sha256: c6184bf2913dd66be244108c9c27ca04b01caf726321c44b0e7a7a1e32d41044
|
|
||||||
url: "https://pub.flutter-io.cn"
|
|
||||||
source: hosted
|
|
||||||
version: "7.1.4"
|
|
||||||
modal_bottom_sheet:
|
modal_bottom_sheet:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -1230,10 +1222,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: win32_registry
|
name: win32_registry
|
||||||
sha256: "21ec76dfc731550fd3e2ce7a33a9ea90b828fdf19a5c3bcf556fa992cfa99852"
|
sha256: "6f1b564492d0147b330dd794fee8f512cec4977957f310f9951b5f9d83618dae"
|
||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.5"
|
version: "2.1.0"
|
||||||
xdg_directories:
|
xdg_directories:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|||||||
@@ -45,7 +45,6 @@ dependencies:
|
|||||||
dropdown_button2: ^2.3.8
|
dropdown_button2: ^2.3.8
|
||||||
image_picker: ^1.2.1 # 用于从相册选择图片
|
image_picker: ^1.2.1 # 用于从相册选择图片
|
||||||
image: ^4.5.4
|
image: ^4.5.4
|
||||||
mobile_scanner: ^7.1.4
|
|
||||||
flutter_pdfview: 1.4.3 #显示pdf
|
flutter_pdfview: 1.4.3 #显示pdf
|
||||||
photo_view: ^0.15.0 #操作图片
|
photo_view: ^0.15.0 #操作图片
|
||||||
flutter_inappwebview: ^6.1.5 # WebView插件
|
flutter_inappwebview: ^6.1.5 # WebView插件
|
||||||
@@ -65,6 +64,7 @@ dev_dependencies:
|
|||||||
|
|
||||||
dependency_overrides:
|
dependency_overrides:
|
||||||
intl: 0.19.0
|
intl: 0.19.0
|
||||||
|
device_info_plus: ^12.3.0
|
||||||
|
|
||||||
flutter:
|
flutter:
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user