Merge branch 'release' of https://gitee.com/starlock-cn/app-starlock into release

This commit is contained in:
魏少阳 2024-06-12 09:51:53 +08:00
commit 3e04c0de5f
17 changed files with 641 additions and 153 deletions

View File

@ -1,115 +1,145 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" package="com.example.star_lock"> <manifest xmlns:android="http://schemas.android.com/apk/res/android"
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation"/> xmlns:tools="http://schemas.android.com/tools"
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/> package="com.example.star_lock">
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<!-- <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" android:maxSdkVersion="30" />-->
<!-- <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" android:maxSdkVersion="30" />-->
<!--允许访问网络,必选权限-->
<uses-permission android:name="android.permission.INTERNET"/>
<!--允许获取精确位置,精准定位必选-->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<!--允许获取粗略位置,粗略定位必选-->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<!--允许获取设备和运营商信息用于问题排查和网络定位无gps情况下的定位若需网络定位功能则必选-->
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.READ_PHONE_NUMBERS"/>
<!--允许获取网络状态用于网络定位无gps情况下的定位若需网络定位功能则必选-->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<!--允许获取wifi网络信息用于网络定位无gps情况下的定位若需网络定位功能则必选-->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<!--允许获取wifi状态改变用于网络定位无gps情况下的定位若需网络定位功能则必选-->
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
<!--允许写设备缓存,用于问题排查-->
<uses-permission android:name="android.permission.WRITE_SETTINGS"/>
<!--允许读设备日志,用于问题排查-->
<uses-permission android:name="android.permission.READ_LOGS" />
<!--相机--> <uses-permission
<uses-permission android:name="android.permission.CAMERA"/> android:name="android.permission.BLUETOOTH_SCAN"
android:usesPermissionFlags="neverForLocation" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<!-- <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" android:maxSdkVersion="30" />-->
<!-- <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" android:maxSdkVersion="30" />-->
<!--允许访问网络,必选权限-->
<uses-permission android:name="android.permission.INTERNET" />
<!--允许获取精确位置,精准定位必选-->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<!--允许获取粗略位置,粗略定位必选-->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!--允许获取设备和运营商信息用于问题排查和网络定位无gps情况下的定位若需网络定位功能则必选-->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_NUMBERS" />
<!--允许获取网络状态用于网络定位无gps情况下的定位若需网络定位功能则必选-->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!--允许获取wifi网络信息用于网络定位无gps情况下的定位若需网络定位功能则必选-->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<!--允许获取wifi状态改变用于网络定位无gps情况下的定位若需网络定位功能则必选-->
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<!--允许写设备缓存,用于问题排查-->
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<!--允许读设备日志,用于问题排查-->
<uses-permission android:name="android.permission.READ_LOGS" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <!--相机-->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
<!--允许麦克风权限,用于录音发送--> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.RECORD_AUDIO"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WAKE_LOCK"/> <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" /> <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<uses-permission android:name="android.permission.GET_ACCOUNTS"/> <uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.REORDER_TASKS"/>
<!-- 相册权限 34适配 --> <!--允许麦克风权限,用于录音发送-->
<uses-permission android:name="android.permission.READ_MEDIA_VISUAL_USER_SELECTED" /> <uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.REORDER_TASKS" />
<!-- 相册权限 34适配 -->
<uses-permission android:name="android.permission.READ_MEDIA_VISUAL_USER_SELECTED" />
<application android:usesCleartextTraffic="true" android:label="@string/app_name" android:name="android.app.Application" android:icon="@mipmap/ic_launcher"> <!-- 移除 QUERY_ALL_PACKAGES 权限 -->
<meta-data <uses-permission
android:name="flutterEmbedding" android:name="android.permission.QUERY_ALL_PACKAGES"
android:value="2" /> tools:node="remove" />
<meta-data
android:name="com.google.firebase.messaging.default_notification_channel_id" <application
android:value="1"/> <!-- 将您的通知渠道ID替换为您的实际ID --> android:name="android.app.Application"
<meta-data android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:usesCleartextTraffic="true">
<meta-data
android:name="flutterEmbedding"
android:value="2" />
<meta-data
android:name="com.google.firebase.messaging.default_notification_channel_id"
android:value="1" /> <!-- 将您的通知渠道ID替换为您的实际ID -->
<meta-data
android:name="com.huawei.hms.client.appid" android:name="com.huawei.hms.client.appid"
android:value="110798531"/> android:value="110798531" />
<meta-data <meta-data
android:name="com.huawei.hms.client.cpid" android:name="com.huawei.hms.client.cpid"
android:value="1406555529261648640"/> android:value="1406555529261648640" />
<meta-data android:name="OPPO_APPKEY" <meta-data
android:value="OP-47f668c9943248118502aa58d066393b" /> android:name="OPPO_APPKEY"
android:value="OP-47f668c9943248118502aa58d066393b" />
<meta-data android:name="OPPO_APPID" <meta-data
android:name="OPPO_APPID"
android:value="OP-31726001" /> android:value="OP-31726001" />
<meta-data android:name="OPPO_APPSECRET" <meta-data
android:name="OPPO_APPSECRET"
android:value="OP-05723986bba64183a71530b496922450" /> android:value="OP-05723986bba64183a71530b496922450" />
<!-- 配置定位Service --> <!-- 配置定位Service -->
<service android:name="com.amap.api.location.APSService"/> <service android:name="com.amap.api.location.APSService" />
<!-- since JPushv3.6.8 oppov2.1.0 oppo 核心功能--> <!-- since JPushv3.6.8 oppov2.1.0 oppo 核心功能-->
<service android:name="cn.jpush.android.service.PluginOppoPushService" <service
android:permission="com.coloros.mcs.permission.SEND_MCS_MESSAGE" android:name="cn.jpush.android.service.PluginOppoPushService"
android:exported="true"> android:exported="true"
<intent-filter> android:permission="com.coloros.mcs.permission.SEND_MCS_MESSAGE">
<action android:name="com.coloros.mcs.action.RECEIVE_MCS_MESSAGE" /> <intent-filter>
</intent-filter> <action android:name="com.coloros.mcs.action.RECEIVE_MCS_MESSAGE" />
</service> </intent-filter>
</service>
<!-- since JPushv3.6.8 oppov2.1.0 oppo 核心功能--> <!-- since JPushv3.6.8 oppov2.1.0 oppo 核心功能-->
<service <service
android:name="com.heytap.msp.push.service.DataMessageCallbackService" android:name="com.heytap.msp.push.service.DataMessageCallbackService"
android:permission="com.heytap.mcs.permission.SEND_PUSH_MESSAGE" android:exported="true"
android:exported="true"> android:permission="com.heytap.mcs.permission.SEND_PUSH_MESSAGE">
<intent-filter> <intent-filter>
<action android:name="com.heytap.mcs.action.RECEIVE_MCS_MESSAGE"/> <action android:name="com.heytap.mcs.action.RECEIVE_MCS_MESSAGE" />
<action android:name="com.heytap.msp.push.RECEIVE_MCS_MESSAGE"/> <action android:name="com.heytap.msp.push.RECEIVE_MCS_MESSAGE" />
</intent-filter> </intent-filter>
</service> <!--兼容Q版本--> </service> <!--兼容Q版本-->
<activity android:name="com.skychip.lock.MainActivity" android:exported="true" android:screenOrientation="portrait" android:launchMode="singleTop" android:theme="@style/LaunchTheme" android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode" android:hardwareAccelerated="true" android:windowSoftInputMode="adjustResize"> <activity
<!-- Specifies an Android theme to apply to this Activity as soon as android:name="com.skychip.lock.MainActivity"
the Android process has started. This theme is visible to the user android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
while the Flutter UI initializes. After that, this theme continues android:exported="true"
to determine the Window background behind the Flutter UI. --> android:hardwareAccelerated="true"
<meta-data android:name="io.flutter.embedding.android.NormalTheme" android:resource="@style/NormalTheme"/> android:launchMode="singleTop"
<intent-filter> android:screenOrientation="portrait"
<action android:name="android.intent.action.MAIN"/> android:theme="@style/LaunchTheme"
<category android:name="android.intent.category.LAUNCHER"/> android:windowSoftInputMode="adjustResize">
</intent-filter> <!-- Specifies an Android theme to apply to this Activity as soon as
<intent-filter> the Android process has started. This theme is visible to the user
<action android:name="android.intent.action.VIEW" /> while the Flutter UI initializes. After that, this theme continues
<category android:name="android.intent.category.DEFAULT" /> to determine the Window background behind the Flutter UI. -->
<category android:name="android.intent.category.BROWSABLE" /> <meta-data
<data android:scheme="skysmartlock" /> android:name="io.flutter.embedding.android.NormalTheme"
</intent-filter> android:resource="@style/NormalTheme" />
</activity> <intent-filter>
</application> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="skysmartlock" />
</intent-filter>
</activity>
</application>
</manifest> </manifest>

View File

@ -102,15 +102,14 @@ class StarLockLoginLogic extends BaseGetXController {
super.onClose(); super.onClose();
} }
@override //
void onReady() { void flushedDeviceInfo(){
super.onReady();
XSConstantMacro().getDeviceInfoData().then((Map<String, dynamic> data) { XSConstantMacro().getDeviceInfoData().then((Map<String, dynamic> data) {
state.deviceInfoMap.value = data; state.deviceInfoMap.value = data;
}).catchError((error) { }).catchError((dynamic error) {
// //
AppLog.log('获取设备信息时出错: $error'); AppLog.log('获取设备信息时出错: $error');
}); });
} }
} }

View File

@ -29,15 +29,17 @@ class AuthorizedAdminSendEntity {
class Data { class Data {
int? receiverUid; int? receiverUid;
ReceiverUser? receiverUser; ReceiverUser? receiverUser;
int? usernameType;
int? keyId; int? keyId;
Data({this.receiverUid, this.receiverUser, this.keyId}); Data({this.receiverUid, this.receiverUser, this.usernameType, this.keyId});
Data.fromJson(Map<String, dynamic> json) { Data.fromJson(Map<String, dynamic> json) {
receiverUid = json['receiverUid']; receiverUid = json['receiverUid'];
receiverUser = json['receiverUser'] != null receiverUser = json['receiverUser'] != null
? ReceiverUser.fromJson(json['receiverUser']) ? ReceiverUser.fromJson(json['receiverUser'])
: null; : null;
usernameType = json['usernameType'];
keyId = json['keyId']; keyId = json['keyId'];
} }
@ -47,6 +49,7 @@ class Data {
if (receiverUser != null) { if (receiverUser != null) {
data['receiverUser'] = receiverUser!.toJson(); data['receiverUser'] = receiverUser!.toJson();
} }
data['usernameType'] = usernameType;
data['keyId'] = keyId; data['keyId'] = keyId;
return data; return data;
} }

View File

@ -185,6 +185,7 @@ class SendElectronicKeyViewLogic extends BaseGetXController {
state.createUser.value = 0; state.createUser.value = 0;
state.isSendSuccess = true; state.isSendSuccess = true;
keyId = entity.data!.keyId; keyId = entity.data!.keyId;
state.userNameType.value = entity.data?.usernameType ?? 0;
resetData(); resetData();
update(); update();
eventBus.fire(ElectronicKeyListRefreshUI()); eventBus.fire(ElectronicKeyListRefreshUI());

View File

@ -424,10 +424,11 @@ class _SendElectronicKeyViewState extends State<SendElectronicKeyView>
// ), // ),
if (logic.emailOrPhone != null) if (logic.emailOrPhone != null)
OutLineBtn( OutLineBtn(
btnName: logic.emailOrPhone!.contains('@') ? '邮件通知' : '短信通知', btnName: logic.state.userNameType.value == 1 ? '短信通知' : '邮件通知',
onClick: () { onClick: () {
if (logic.emailOrPhone!.contains('@')) { if (logic.state.userNameType.value == 2) {
Get.toNamed(Routers.sendEmailNotificationPage); Get.toNamed(Routers.sendEmailNotificationPage,
arguments: <String, String?>{'email': logic.emailOrPhone});
} else { } else {
logic.sendMsg(isPhone: true); logic.sendMsg(isPhone: true);
} }

View File

@ -32,6 +32,7 @@ class SendElectronicKeyViewState {
RxInt createUser = 0.obs; //1 0 RxInt createUser = 0.obs; //1 0
bool isDemoMode = false; bool isDemoMode = false;
RxBool isRequireAuth = false.obs; // RxBool isRequireAuth = false.obs; //
RxInt userNameType = 0.obs; //1: 2:
final String timeLimitTips = '接收者在有效期内可以不限次数使用'; // final String timeLimitTips = '接收者在有效期内可以不限次数使用'; //
final String permanentTips = '接收者可以使用此App开关锁'; // final String permanentTips = '接收者可以使用此App开关锁'; //

View File

@ -0,0 +1,79 @@
class SendEmailNotificationEntity {
SendEmailNotificationEntity(
{this.errorCode, this.description, this.errorMsg, this.data});
SendEmailNotificationEntity.fromJson(Map<String, dynamic> json) {
errorCode = json['errorCode'];
description = json['description'];
errorMsg = json['errorMsg'];
data = json['data'] != null
? EmailNotificationData.fromJson(json['data'])
: null;
}
int? errorCode;
String? description;
String? errorMsg;
EmailNotificationData? data;
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['errorCode'] = errorCode;
data['description'] = description;
data['errorMsg'] = errorMsg;
if (this.data != null) {
data['data'] = this.data!.toJson();
}
return data;
}
}
class EmailNotificationData {
EmailNotificationData({this.list});
EmailNotificationData.fromJson(Map<String, dynamic> json) {
if (json['list'] != null) {
list = <EmailNotificationItem>[];
json['list'].forEach((v) {
list!.add(EmailNotificationItem.fromJson(v));
});
}
}
List<EmailNotificationItem>? list;
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
if (list != null) {
data['list'] =
list!.map((EmailNotificationItem v) => v.toJson()).toList();
}
return data;
}
}
class EmailNotificationItem {
EmailNotificationItem(
{this.type, this.name, this.template, this.isUse, this.fee});
EmailNotificationItem.fromJson(Map<String, dynamic> json) {
type = json['type'];
name = json['name'];
template = json['template'];
isUse = json['isUse'];
fee = json['fee'];
}
String? type;
String? name;
String? template;
int? isUse;
int? fee;
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['type'] = type;
data['name'] = name;
data['template'] = template;
data['isUse'] = isUse;
data['fee'] = fee;
return data;
}
}

View File

@ -0,0 +1,25 @@
import 'package:get_storage/get_storage.dart';
import 'package:star_lock/main/lockDetail/electronicKey/sendEmailNotification/sendEmailNotification_entity.dart';
import 'package:star_lock/main/lockDetail/electronicKey/sendEmailNotification/sendEmailNotification_state.dart';
import 'package:star_lock/network/api_repository.dart';
import 'package:star_lock/tools/baseGetXController.dart';
import 'package:star_lock/tools/commonDataManage.dart';
class SendEmailNotificationLogic extends BaseGetXController {
final SendEmailNotificationState state = SendEmailNotificationState();
// 1 2
Future<void> getKeyNoticeTemplate() async {
final SendEmailNotificationEntity entity =
await ApiRepository.to.getKeyNoticeTemplate(
lockId: CommonDataManage().currentKeyInfo.lockId ?? 0,
keyId: CommonDataManage().currentKeyInfo.keyId ?? 0,
channelType: 2,
);
if (entity.errorCode!.codeIsSuccessful) {
state.emailTemplateList.value =
entity.data?.list ?? <EmailNotificationItem>[];
state.emailTemplateList.refresh();
}
}
}

View File

@ -1,6 +1,11 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get_utils/get_utils.dart'; import 'package:get/get.dart';
import 'package:star_lock/main/lockDetail/electronicKey/sendEmailNotification/SendEmailNotification_logic.dart';
import 'package:star_lock/main/lockDetail/electronicKey/sendEmailNotification/sendEmailNotification_state.dart';
import 'package:star_lock/tools/emailNotifyTypeSelectAlert.dart';
import 'package:star_lock/tools/pickers/pickers.dart';
import 'package:star_lock/tools/pickers/style/default_style.dart';
import 'package:star_lock/translations/trans_lib.dart'; import 'package:star_lock/translations/trans_lib.dart';
import '../../../../app_settings/app_colors.dart'; import '../../../../app_settings/app_colors.dart';
@ -12,42 +17,71 @@ class SendEmailNotificationPage extends StatefulWidget {
const SendEmailNotificationPage({Key? key}) : super(key: key); const SendEmailNotificationPage({Key? key}) : super(key: key);
@override @override
State<SendEmailNotificationPage> createState() => _SendEmailNotificationPageState(); State<SendEmailNotificationPage> createState() =>
_SendEmailNotificationPageState();
} }
class _SendEmailNotificationPageState extends State<SendEmailNotificationPage> { class _SendEmailNotificationPageState extends State<SendEmailNotificationPage> {
final TextEditingController _emailController = TextEditingController(); final SendEmailNotificationLogic logic =
Get.put(SendEmailNotificationLogic());
final SendEmailNotificationState state =
Get.find<SendEmailNotificationLogic>().state;
@override
void initState() {
super.initState();
logic.getKeyNoticeTemplate();
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
_emailController.text = "亲爱的用户 \n\n你收到电子钥匙请试用APP(www.baidu.com)或小程序开锁 \n\n星锁";
return Scaffold( return Scaffold(
backgroundColor: AppColors.mainBackgroundColor, backgroundColor: AppColors.mainBackgroundColor,
appBar: TitleAppBar(barTitle: "邮件通知", haveBack: true, backgroundColor: AppColors.mainColor), appBar: TitleAppBar(
barTitle: '邮件通知',
haveBack: true,
backgroundColor: AppColors.mainColor),
body: SingleChildScrollView( body: SingleChildScrollView(
child: Column( child: Column(
children: [ children: <Widget>[
CommonItem( Obx(() => CommonItem(
leftTitel: TranslationLoader.lanKeys!.receiver!.tr, leftTitel: TranslationLoader.lanKeys!.receiver!.tr,
rightTitle: "786612630@qq.com", rightTitle: state.getEmail.value,
isHaveLine: true, isHaveLine: true,
), )),
CommonItem( Obx(() => CommonItem(
leftTitel: "类型", leftTitel: '类型',
rightTitle: "个人邮件", rightTitle:
isHaveDirection: true, state.emailNotifyType.value == 1 ? '系统邮件' : '个人邮件',
), isHaveDirection: true,
action: () {
EmailNotifyTypeSelectAlert.showEmailNotifyTypeSelectAlert(
context, (int value) {
state.emailNotifyType.value = value;
});
},
)),
Container(height: 10.h), Container(height: 10.h),
CommonItem(leftTitel: "模板", rightTitle: "默认模板", isHaveDirection: true, isHaveLine: true), Obx(() => CommonItem(
leftTitel: '模板',
rightTitle: state.selectEmailTemplate.value,
isHaveDirection: true,
isHaveLine: true,
action: () {
openBottomItemSheet(context);
},
)),
Container( Container(
height: 360.h, height: 360.h,
color: Colors.white, color: Colors.white,
padding: EdgeInsets.only(left: 20.w, right: 20.w, top: 20.h, bottom: 20.h), padding: EdgeInsets.only(
left: 20.w, right: 20.w, top: 20.h, bottom: 20.h),
child: TextField( child: TextField(
maxLines: 8, maxLines: 8,
maxLength: 1000, maxLength: 1000,
textAlign: TextAlign.start, textAlign: TextAlign.start,
controller: _emailController, controller: state.emailController,
style: TextStyle( style: TextStyle(
color: Colors.black, color: Colors.black,
fontSize: 22.sp, fontSize: 22.sp,
@ -86,7 +120,7 @@ class _SendEmailNotificationPageState extends State<SendEmailNotificationPage> {
), ),
Container(height: 40.h), Container(height: 40.h),
SubmitBtn( SubmitBtn(
btnName: '发送', btnName: '发送'.tr,
fontSize: 28.sp, fontSize: 28.sp,
borderRadius: 20.w, borderRadius: 20.w,
margin: EdgeInsets.only(left: 30.w, right: 30.w, top: 30.w), margin: EdgeInsets.only(left: 30.w, right: 30.w, top: 30.w),
@ -97,4 +131,16 @@ class _SendEmailNotificationPageState extends State<SendEmailNotificationPage> {
), ),
); );
} }
// pickerView
void openBottomItemSheet(BuildContext context) {
final List nameList =
state.emailTemplateList.map((item) => item.name!).toList();
Pickers.showSinglePicker(context,
data: nameList,
pickerStyle: DefaultPickerStyle(), onConfirm: (p, int position) {
state.selectEmailTemplate.value = nameList[position];
});
}
} }

View File

@ -0,0 +1,17 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:star_lock/main/lockDetail/electronicKey/sendEmailNotification/sendEmailNotification_entity.dart';
class SendEmailNotificationState {
SendEmailNotificationState() {
if (Get.arguments['email'] != null) {
getEmail.value = Get.arguments['email'];
}
}
RxString getEmail = ''.obs;
final TextEditingController emailController = TextEditingController();
RxInt emailNotifyType = 1.obs; //1 2
RxList emailTemplateList = <EmailNotificationItem>[].obs;
RxString selectEmailTemplate = '默认模版'.obs;
}

View File

@ -254,4 +254,5 @@ abstract class Api {
final String deleteTemplateURL = '/v2/service/delete'; // final String deleteTemplateURL = '/v2/service/delete'; //
final String checkIpURL = '/checkIp/ip'; final String checkIpURL = '/checkIp/ip';
final String keyNoticeTemplateURL = '/key/getNoticeTemplate'; //
} }

View File

@ -595,8 +595,9 @@ class ApiProvider extends BaseProvider {
'lockIds': lockIds, 'lockIds': lockIds,
})); }));
Future<Response> selectLockList(String searchStr) => Future<Response> selectLockList(String searchStr) => post(
post(selectLockListURL.toUrl, jsonEncode({ selectLockListURL.toUrl,
jsonEncode({
'searchStr': searchStr, 'searchStr': searchStr,
})); }));
@ -841,7 +842,8 @@ class ApiProvider extends BaseProvider {
// //
Future<Response> getServerDatetimeLoadData(bool isUnShowLoading) => Future<Response> getServerDatetimeLoadData(bool isUnShowLoading) =>
post(getServerDatetimeUrl.toUrl, jsonEncode({}), isUnShowLoading: isUnShowLoading); post(getServerDatetimeUrl.toUrl, jsonEncode({}),
isUnShowLoading: isUnShowLoading);
// //
Future<Response> setLockDiagnoseData( Future<Response> setLockDiagnoseData(
@ -2227,10 +2229,22 @@ class ApiProvider extends BaseProvider {
); );
Future<Response<dynamic>> checkIpAction(String ip) => post( Future<Response<dynamic>> checkIpAction(String ip) => post(
checkIpURL.toUrl, checkIpURL.toUrl,
jsonEncode(<String, dynamic>{'ip': ip}), jsonEncode(<String, dynamic>{'ip': ip}),
isUnShowLoading: true, isUnShowLoading: true,
); );
Future<Response<dynamic>> getKeyNoticeTemplate(
int lockId, int keyId, int channelType) =>
post(
keyNoticeTemplateURL.toUrl,
jsonEncode(<String, dynamic>{
'lockId': lockId,
'keyId': keyId,
'channelType': channelType
}),
isUnShowLoading: true,
);
} }
extension ExtensionString on String { extension ExtensionString on String {

View File

@ -8,6 +8,7 @@ import 'package:star_lock/main/lockDetail/electronicKey/electronicKeyList/entity
import 'package:star_lock/main/lockDetail/electronicKey/electronicKeyList/entity/ElectronicKeyListEntity.dart'; import 'package:star_lock/main/lockDetail/electronicKey/electronicKeyList/entity/ElectronicKeyListEntity.dart';
import 'package:star_lock/main/lockDetail/electronicKey/massSendElectronicKey/massSendLockGroupList/lockUserList/lockUserList_entity.dart'; import 'package:star_lock/main/lockDetail/electronicKey/massSendElectronicKey/massSendLockGroupList/lockUserList/lockUserList_entity.dart';
import 'package:star_lock/main/lockDetail/electronicKey/massSendElectronicKey/massSendLockGroupList/massSendLockGroupListEntity.dart'; import 'package:star_lock/main/lockDetail/electronicKey/massSendElectronicKey/massSendLockGroupList/massSendLockGroupListEntity.dart';
import 'package:star_lock/main/lockDetail/electronicKey/sendEmailNotification/sendEmailNotification_entity.dart';
import 'package:star_lock/main/lockDetail/face/addFace/addFace_entity.dart'; import 'package:star_lock/main/lockDetail/face/addFace/addFace_entity.dart';
import 'package:star_lock/main/lockDetail/fingerprint/fingerprintList/fingerprint_entity.dart'; import 'package:star_lock/main/lockDetail/fingerprint/fingerprintList/fingerprint_entity.dart';
import 'package:star_lock/main/lockDetail/lockSet/basicInformation/basicInformation/KeyDetailEntity.dart'; import 'package:star_lock/main/lockDetail/lockSet/basicInformation/basicInformation/KeyDetailEntity.dart';
@ -892,8 +893,10 @@ class ApiRepository {
} }
// //
Future<GetServerDatetimeEntity> getServerDatetimeData({bool? isUnShowLoading}) async { Future<GetServerDatetimeEntity> getServerDatetimeData(
final res = await apiProvider.getServerDatetimeLoadData(isUnShowLoading ?? true); {bool? isUnShowLoading}) async {
final res =
await apiProvider.getServerDatetimeLoadData(isUnShowLoading ?? true);
return GetServerDatetimeEntity.fromJson(res.body); return GetServerDatetimeEntity.fromJson(res.body);
} }
@ -2245,4 +2248,15 @@ class ApiRepository {
final Response<dynamic> res = await apiProvider.checkIpAction(ip); final Response<dynamic> res = await apiProvider.checkIpAction(ip);
return CheckIPEntity.fromJson(res.body); return CheckIPEntity.fromJson(res.body);
} }
//
Future<SendEmailNotificationEntity> getKeyNoticeTemplate({
required int lockId,
required int keyId,
required int channelType,
}) async {
final Response<dynamic> res =
await apiProvider.getKeyNoticeTemplate(lockId, keyId, channelType);
return SendEmailNotificationEntity.fromJson(res.body);
}
} }

View File

@ -10,6 +10,7 @@ import 'package:star_lock/app_settings/app_settings.dart';
import 'package:star_lock/common/XSConstantMacro/XSConstantMacro.dart'; import 'package:star_lock/common/XSConstantMacro/XSConstantMacro.dart';
import 'package:star_lock/flavors.dart'; import 'package:star_lock/flavors.dart';
import 'package:star_lock/login/login/app_get_version.dart'; import 'package:star_lock/login/login/app_get_version.dart';
import 'package:star_lock/login/login/starLock_login_logic.dart';
import 'package:star_lock/main.dart'; import 'package:star_lock/main.dart';
import 'package:star_lock/network/api_repository.dart'; import 'package:star_lock/network/api_repository.dart';
import 'package:star_lock/tools/customer_tool.dart'; import 'package:star_lock/tools/customer_tool.dart';
@ -30,6 +31,9 @@ class AppFirstEnterHandle {
} }
getAppInfo(); getAppInfo();
await privacySDKInitialization(); await privacySDKInitialization();
if (Get.isRegistered<StarLockLoginLogic>()) {
Get.find<StarLockLoginLogic>().flushedDeviceInfo();
}
break; break;
case isAgreePosition: // case isAgreePosition: //
if (getFlag != isAgreePosition) { if (getFlag != isAgreePosition) {
@ -87,10 +91,11 @@ class AppFirstEnterHandle {
recognizer: TapGestureRecognizer() recognizer: TapGestureRecognizer()
..onTap = () { ..onTap = () {
// //
Get.toNamed(Routers.webviewShowPage, arguments: <String, String>{ Get.toNamed(Routers.webviewShowPage,
"url": XSConstantMacro.userAgreementURL, arguments: <String, String>{
"title": '用户协议'.tr "url": XSConstantMacro.userAgreementURL,
}); "title": '用户协议'.tr
});
}, },
), ),
TextSpan(text: ''.tr), TextSpan(text: ''.tr),
@ -101,10 +106,11 @@ class AppFirstEnterHandle {
recognizer: TapGestureRecognizer() recognizer: TapGestureRecognizer()
..onTap = () { ..onTap = () {
// //
Get.toNamed(Routers.webviewShowPage, arguments: <String, String>{ Get.toNamed(Routers.webviewShowPage,
"url": XSConstantMacro.privacyPolicyURL, arguments: <String, String>{
"title": '隐私政策'.tr "url": XSConstantMacro.privacyPolicyURL,
}); "title": '隐私政策'.tr
});
}, },
), ),
TextSpan( TextSpan(
@ -154,10 +160,11 @@ class AppFirstEnterHandle {
recognizer: TapGestureRecognizer() recognizer: TapGestureRecognizer()
..onTap = () { ..onTap = () {
// //
Get.toNamed(Routers.webviewShowPage, arguments: <String, String>{ Get.toNamed(Routers.webviewShowPage,
"url": XSConstantMacro.userAgreementURL, arguments: <String, String>{
"title": '用户协议'.tr "url": XSConstantMacro.userAgreementURL,
}); "title": '用户协议'.tr
});
}, },
), ),
TextSpan(text: ''.tr), TextSpan(text: ''.tr),
@ -169,10 +176,11 @@ class AppFirstEnterHandle {
recognizer: TapGestureRecognizer() recognizer: TapGestureRecognizer()
..onTap = () { ..onTap = () {
// //
Get.toNamed(Routers.webviewShowPage, arguments: <String, String>{ Get.toNamed(Routers.webviewShowPage,
"url": XSConstantMacro.privacyPolicyURL, arguments: <String, String>{
"title": '隐私政策'.tr "url": XSConstantMacro.privacyPolicyURL,
}); "title": '隐私政策'.tr
});
}, },
), ),
TextSpan( TextSpan(

View File

@ -0,0 +1,135 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:star_lock/app_settings/app_colors.dart';
class EmailNotifyTypeSelectAlert extends StatelessWidget {
const EmailNotifyTypeSelectAlert({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
//
throw UnimplementedError();
}
static void showEmailNotifyTypeSelectAlert(
BuildContext context, Function(int) onSelected) {
bool isSystemEmailSelected = true; //
showCupertinoDialog(
context: context,
builder: (BuildContext context) {
return StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
return CupertinoAlertDialog(
title: const Text('类型选择'),
content: Column(
children: <Widget>[
Padding(
padding: EdgeInsets.only(
left: 10.w, top: 8.h, bottom: 16.h, right: 10.w),
child: Align(
alignment: Alignment.centerLeft,
child:
Text('请选择要使用哪种类型', style: TextStyle(fontSize: 20.sp)),
),
),
GestureDetector(
onTap: () {
setState(() {
isSystemEmailSelected = true;
});
},
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Image.asset(
isSystemEmailSelected
? 'images/icon_round_select.png'
: 'images/icon_round_unSelect.png',
width: 30.w,
height: 30.w,
),
Padding(
padding: EdgeInsets.only(left: 10.w),
child: Text(
'系统邮件(推荐)',
style: TextStyle(
fontSize: 22.sp, fontWeight: FontWeight.bold),
),
),
],
),
),
Padding(
padding: EdgeInsets.only(top: 6.h, left: 10.w, bottom: 10.h),
child: Align(
alignment: Alignment.centerLeft,
child: Text(
'邮件将从软件平台直接发给用户,请根据需要在软件那里购买邮件数量',
style: TextStyle(fontSize: 18.sp),
textAlign: TextAlign.left,
),
),
),
GestureDetector(
onTap: () {
setState(() {
isSystemEmailSelected = false;
});
},
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Image.asset(
!isSystemEmailSelected
? 'images/icon_round_select.png'
: 'images/icon_round_unSelect.png',
width: 30.w,
height: 30.w,
),
Padding(
padding: EdgeInsets.only(left: 10.w),
child: Text(
'个人邮件',
style: TextStyle(
fontSize: 22.sp, fontWeight: FontWeight.bold),
),
),
],
),
),
Padding(
padding: EdgeInsets.only(top: 6.h, left: 10.w),
child: Align(
alignment: Alignment.centerLeft,
child: Text(
'邮件将从你的个人邮箱发给用户',
style: TextStyle(fontSize: 18.sp),
),
),
),
],
),
actions: <Widget>[
CupertinoDialogAction(
onPressed: () {
final int selectedType =
isSystemEmailSelected ? 1 : 2; // 1 2
onSelected(selectedType);
Get.back();
},
child: Text(
'确定'.tr,
style: TextStyle(color: AppColors.mainColor),
),
),
],
);
});
},
);
}
}

View File

@ -10,6 +10,8 @@ import 'package:star_lock/common/XSConstantMacro/XSConstantMacro.dart';
typedef AuthInfoCallback = void Function(String? idCard, String? name); typedef AuthInfoCallback = void Function(String? idCard, String? name);
class ShowCupertinoAlertView { class ShowCupertinoAlertView {
bool isSystemEmailSelected = true; //
// //
void showQRImageAlert(BuildContext widgetContext, String qrCodeUrl) { void showQRImageAlert(BuildContext widgetContext, String qrCodeUrl) {
showCupertinoModalPopup( showCupertinoModalPopup(
@ -398,4 +400,114 @@ class ShowCupertinoAlertView {
}, },
); );
} }
// //
// void emailNotifyTypeSlectAlert() {
// showCupertinoDialog(
// context: Get.context!,
// builder: (BuildContext context) {
// return CupertinoAlertDialog(
// title: const Text('类型选择'),
// content: Column(
// children: <Widget>[
// Padding(
// padding: EdgeInsets.only(
// left: 10.w, top: 8.h, bottom: 16.h, right: 10.w),
// child: Align(
// alignment: Alignment.centerLeft,
// child: Text('请选择要使用哪种类型', style: TextStyle(fontSize: 20.sp)),
// ),
// ),
// GestureDetector(
// onTap: () {
// setState(() {
// isSystemEmailSelected = true;
// });
// },
// child: Row(
// mainAxisAlignment: MainAxisAlignment.start,
// crossAxisAlignment: CrossAxisAlignment.center,
// children: <Widget>[
// Image.asset(
// isSystemEmailSelected
// ? 'images/icon_round_select.png'
// : 'images/icon_round_unSelect.png',
// width: 30.w,
// height: 30.w,
// ),
// Padding(
// padding: EdgeInsets.only(left: 10.w),
// child: Text(
// '系统邮件(推荐)',
// style: TextStyle(
// fontSize: 22.sp, fontWeight: FontWeight.bold),
// ),
// ),
// ],
// ),
// ),
// Padding(
// padding: EdgeInsets.only(top: 6.h, left: 10.w, bottom: 10.h),
// child: Align(
// alignment: Alignment.centerLeft,
// child: Text(
// '邮件将从软件平台直接发给用户,请根据需要在软件那里购买邮件数量',
// style: TextStyle(fontSize: 18.sp),
// textAlign: TextAlign.left,
// ),
// ),
// ),
// GestureDetector(
// onTap: () {
// setState(() {
// isSystemEmailSelected = false;
// });
// },
// child: Row(
// mainAxisAlignment: MainAxisAlignment.start,
// crossAxisAlignment: CrossAxisAlignment.center,
// children: <Widget>[
// Image.asset(
// !isSystemEmailSelected
// ? 'images/icon_round_select.png'
// : 'images/icon_round_unSelect.png',
// width: 30.w,
// height: 30.w,
// ),
// Padding(
// padding: EdgeInsets.only(left: 10.w),
// child: Text(
// '个人邮件',
// style: TextStyle(
// fontSize: 22.sp, fontWeight: FontWeight.bold),
// ),
// ),
// ],
// ),
// ),
// Padding(
// padding: EdgeInsets.only(top: 6.h, left: 10.w),
// child: Align(
// alignment: Alignment.centerLeft,
// child: Text(
// '邮件将从你的个人邮箱发给用户',
// style: TextStyle(fontSize: 18.sp),
// ),
// ),
// ),
// ],
// ),
// actions: <Widget>[
// CupertinoDialogAction(
// onPressed: Get.back,
// child: Text(
// '确定'.tr,
// style: TextStyle(color: AppColors.mainColor),
// ),
// ),
// ],
// );
// },
// );
// }
} }

View File

@ -68,8 +68,10 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
# 1.0.58+2024060702xhj 线上环境,对外发布,提交测试 # 1.0.58+2024060702xhj 线上环境,对外发布,提交测试
# 1.0.59+2024060703xhj 线上环境,对外发布,提交测试 # 1.0.59+2024060703xhj 线上环境,对外发布,提交测试
# 1.0.60+2024061101xhj 线上环境,对外发布,提交测试 # 1.0.60+2024061101xhj 线上环境,对外发布,提交测试
# 1.0.60+2024061102xhj 线上环境,对外发布,提交测试
# 1.0.61+2024061103xhj 线上环境,对外发布,提交测试:处理华为拒审
version: 1.0.60+2024061101 version: 1.0.61+2024061103
environment: environment:
sdk: '>=2.12.0 <3.0.0' sdk: '>=2.12.0 <3.0.0'