Merge branch 'release' of https://gitee.com/starlock-cn/app-starlock into release
# Conflicts: # images/lan/lan_en.json # images/lan/lan_keys.json # images/lan/lan_zh.json
This commit is contained in:
commit
8f63629e4a
@ -52,14 +52,14 @@ android {
|
||||
// 这里“debug”不是一个自定义变量,而是一个特定的关键词,凡是使用--debug模式,都会引用到这里
|
||||
// 目前看来,debug模式没办法在buildTypes里面按flavors指定编译签名,所有口味的debug模式只能用同一个签名
|
||||
debug {
|
||||
// storeFile file("starlock.keystore")
|
||||
// storePassword '123456'
|
||||
// keyAlias = 'starlock'
|
||||
// keyPassword '123456'
|
||||
storeFile file("xhj.jks")
|
||||
storePassword 'xhj8872'
|
||||
keyAlias = 'upload'
|
||||
keyPassword 'xhj8872'
|
||||
storeFile file("starlock.keystore")
|
||||
storePassword '123456'
|
||||
keyAlias = 'starlock'
|
||||
keyPassword '123456'
|
||||
// storeFile file("xhj.jks")
|
||||
// storePassword 'xhj8872'
|
||||
// keyAlias = 'upload'
|
||||
// keyPassword 'xhj8872'
|
||||
}
|
||||
sky {
|
||||
// CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown
|
||||
|
||||
@ -862,6 +862,7 @@
|
||||
"五": "Fri",
|
||||
"六": "Sat",
|
||||
"日": "Sun",
|
||||
|
||||
"新建短信模版":"New SMS template",
|
||||
"新建邮件模版":"New email template",
|
||||
"自定义短信模版":"Custom SMS template",
|
||||
@ -874,4 +875,12 @@
|
||||
"国家地区的选择将影响数据安全,你当前选择的是阿尔巴尼亚,请确认后再继续": "The selection of the country or region will affect data security. You have currently selected Albania. Please confirm before continuing",
|
||||
"确认国家或地区": "Confirm country or region",
|
||||
"我知道了": "I know",
|
||||
|
||||
"为了让您及时收到重要通知和更新,我们需要获取通知权限。请点击“确定”按钮,然后在设置页面中启用通知权限。": "To receive important updates, please click 'OK' and enable notifications in the settings.",
|
||||
"开启后,可通过长按锁上的设置键重新上电,用APP重新添加": "After turning on, you can re-power on by long pressing the setting key on the lock, and re-add it with the APP",
|
||||
"已有": "Already has",
|
||||
"新增": "New",
|
||||
"账号格式错误": "The account format is incorrect",
|
||||
"接收者信息为空": "The recipient information is empty"
|
||||
|
||||
}
|
||||
|
||||
@ -900,10 +900,19 @@
|
||||
"自定义邮件模版":"自定义邮件模版",
|
||||
"名称":"名称",
|
||||
"星星锁": "星星锁",
|
||||
|
||||
"无考勤记录": "无考勤记录",
|
||||
"大家干劲十足": "大家干劲十足",
|
||||
"工作时长未出炉": "工作时长未出炉",
|
||||
"国家地区的选择将影响数据安全,你当前选择的是阿尔巴尼亚,请确认后再继续": "国家地区的选择将影响数据安全,你当前选择的是阿尔巴尼亚,请确认后再继续",
|
||||
"确认国家或地区": "确认国家或地区",
|
||||
"我知道了": "我知道了"
|
||||
"我知道了": "我知道了",
|
||||
|
||||
"为了让您及时收到重要通知和更新,我们需要获取通知权限。请点击“确定”按钮,然后在设置页面中启用通知权限。": "为了让您及时收到重要通知和更新,我们需要获取通知权限。请点击“确定”按钮,然后在设置页面中启用通知权限。",
|
||||
"开启后,可通过长按锁上的设置键重新上电,用APP重新添加":"开启后,可通过长按锁上的设置键重新上电,用APP重新添加",
|
||||
"已有": "已有",
|
||||
"新增": "新增",
|
||||
"账号格式错误": "账号格式错误",
|
||||
"接收者信息为空": "接收者信息为空"
|
||||
|
||||
}
|
||||
|
||||
@ -862,17 +862,25 @@
|
||||
"五": "五",
|
||||
"六": "六",
|
||||
"日": "日",
|
||||
"新建短信模版":"新建短信模版",
|
||||
"新建邮件模版":"新建邮件模版",
|
||||
"自定义短信模版":"自定义短信模版",
|
||||
"自定义邮件模版":"自定义邮件模版",
|
||||
"名称":"名称",
|
||||
"星星锁": "星星锁",
|
||||
|
||||
"无考勤记录": "无考勤记录",
|
||||
"大家干劲十足": "大家干劲十足",
|
||||
"工作时长未出炉": "工作时长未出炉",
|
||||
"国家地区的选择将影响数据安全,你当前选择的是阿尔巴尼亚,请确认后再继续": "国家地区的选择将影响数据安全,你当前选择的是阿尔巴尼亚,请确认后再继续",
|
||||
"确认国家或地区": "确认国家或地区",
|
||||
"我知道了": "我知道了"
|
||||
"我知道了": "我知道了",
|
||||
|
||||
"新建短信模版": "新建短信模版",
|
||||
"新建邮件模版": "新建邮件模版",
|
||||
"自定义短信模版": "自定义短信模版",
|
||||
"自定义邮件模版": "自定义邮件模版",
|
||||
"名称": "名称",
|
||||
"星星锁": "星星锁",
|
||||
"为了让您及时收到重要通知和更新,我们需要获取通知权限。请点击“确定”按钮,然后在设置页面中启用通知权限。": "为了让您及时收到重要通知和更新,我们需要获取通知权限。请点击“确定”按钮,然后在设置页面中启用通知权限。",
|
||||
"开启后,可通过长按锁上的设置键重新上电,用APP重新添加":"开启后,可通过长按锁上的设置键重新上电,用APP重新添加",
|
||||
"已有": "已有",
|
||||
"新增": "新增",
|
||||
"账号格式错误": "账号格式错误",
|
||||
"接收者信息为空": "接收者信息为空"
|
||||
|
||||
}
|
||||
|
||||
@ -71,14 +71,14 @@
|
||||
// iOS 8 Notifications
|
||||
[application registerUserNotificationSettings:
|
||||
[UIUserNotificationSettings settingsForTypes:
|
||||
(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge)
|
||||
(UIUserNotificationTypeSound | UIUserNotificationTypeAlert)
|
||||
categories:nil]];
|
||||
[application registerForRemoteNotifications];
|
||||
}
|
||||
else {
|
||||
// iOS < 8 Notifications
|
||||
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:
|
||||
(UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound)];
|
||||
(UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound)];
|
||||
}
|
||||
}
|
||||
/*
|
||||
|
||||
@ -325,7 +325,8 @@ class BlueManage {
|
||||
mac != null) {
|
||||
scanSingleTimer?.cancel();
|
||||
//兼容android 的低配手机
|
||||
await doNotSearchBLE(mac, connectStateCallBack);
|
||||
await doNotSearchBLE(mac, connectStateCallBack,
|
||||
isAddEquipment: isAddEquipment);
|
||||
scanSingleTimer = Timer(3.seconds, () {
|
||||
scanSingleTimer?.cancel();
|
||||
startScanSingle(deviceName, 15, (List<ScanResult> scanDevices) => null);
|
||||
@ -384,6 +385,7 @@ class BlueManage {
|
||||
isAddEquipment == false) {
|
||||
connectStateCallBack(BluetoothConnectionState.disconnected);
|
||||
EasyLoading.showToast('该锁已被重置'.tr, duration: 2000.milliseconds);
|
||||
scanDevices.clear();
|
||||
return;
|
||||
}
|
||||
//尝试连接设备
|
||||
@ -392,7 +394,8 @@ class BlueManage {
|
||||
|
||||
//直接给蓝牙设备写入
|
||||
Future<void> doNotSearchBLE(
|
||||
String masAdds, ConnectStateCallBack connectStateCallBack) async {
|
||||
String masAdds, ConnectStateCallBack connectStateCallBack,
|
||||
{bool isAddEquipment = false}) async {
|
||||
await FlutterBluePlus.stopScan();
|
||||
if (bluetoothConnectDevice == null ||
|
||||
bluetoothConnectDevice?.remoteId.str != masAdds) {
|
||||
@ -401,12 +404,14 @@ class BlueManage {
|
||||
_initListenConnectionState();
|
||||
}
|
||||
//尝试连接设备
|
||||
await bluetoothDeviceConnect(bluetoothConnectDevice!, connectStateCallBack);
|
||||
await bluetoothDeviceConnect(bluetoothConnectDevice!, connectStateCallBack,
|
||||
isAddEquipment: isAddEquipment);
|
||||
}
|
||||
|
||||
//设备连接
|
||||
Future<void> bluetoothDeviceConnect(BluetoothDevice bluetoothConnectDevice,
|
||||
ConnectStateCallBack connectStateCallBack) async {
|
||||
ConnectStateCallBack connectStateCallBack,
|
||||
{bool isAddEquipment = false}) async {
|
||||
// 重连三次
|
||||
const int maxAttempts = 3;
|
||||
int attempt = 0;
|
||||
@ -430,23 +435,22 @@ class BlueManage {
|
||||
|
||||
if (bluetoothConnectionState == BluetoothConnectionState.connected) {
|
||||
try {
|
||||
bluetoothConnectDevice!
|
||||
.discoverServices()
|
||||
.then((List<BluetoothService> services) {
|
||||
for (final BluetoothService service in services) {
|
||||
if (service.uuid == _serviceIdConnect) {
|
||||
for (final BluetoothCharacteristic characteristic
|
||||
in service.characteristics) {
|
||||
if (characteristic.characteristicUuid ==
|
||||
_characteristicIdSubscription) {
|
||||
_subScribeToCharacteristic(characteristic);
|
||||
bluetoothConnectionState = BluetoothConnectionState.connected;
|
||||
connectStateCallBack(bluetoothConnectionState!);
|
||||
}
|
||||
final List<BluetoothService> services =
|
||||
await bluetoothConnectDevice.discoverServices();
|
||||
//循环判断服务
|
||||
for (final BluetoothService service in services) {
|
||||
if (service.uuid == _serviceIdConnect) {
|
||||
for (final BluetoothCharacteristic characteristic
|
||||
in service.characteristics) {
|
||||
if (characteristic.characteristicUuid ==
|
||||
_characteristicIdSubscription) {
|
||||
_subScribeToCharacteristic(characteristic);
|
||||
bluetoothConnectionState = BluetoothConnectionState.connected;
|
||||
connectStateCallBack(bluetoothConnectionState!);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
} on Exception catch (e) {
|
||||
bluetoothConnectionState = BluetoothConnectionState.disconnected;
|
||||
connectStateCallBack(bluetoothConnectionState!);
|
||||
|
||||
@ -170,7 +170,6 @@ class _MassSendElectronicKeyPageState extends State<MassSendElectronicKeyPage> {
|
||||
if (value != null) {
|
||||
value as Map<String, dynamic>;
|
||||
state.receiverList = value['lockUserList'];
|
||||
|
||||
setState(() {});
|
||||
}
|
||||
});
|
||||
|
||||
@ -3,6 +3,7 @@ import 'package:flutter_native_contact_picker/flutter_native_contact_picker.dart
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:star_lock/main/lockDetail/electronicKey/massSendElectronicKey/massSendLockGroupList/lockUserList/lockUserList_entity.dart';
|
||||
import 'package:star_lock/tools/regexp_tool.dart';
|
||||
import 'package:star_lock/translations/trans_lib.dart';
|
||||
import '../../../../../../app_settings/app_colors.dart';
|
||||
|
||||
@ -13,6 +14,7 @@ class MassSendReceiverCell extends StatefulWidget {
|
||||
required this.onDeleteUser,
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
|
||||
final int currentIndex;
|
||||
final LockUserItemData userData;
|
||||
final VoidCallback onDeleteUser;
|
||||
@ -25,6 +27,7 @@ class _MassSendReceiverCellState extends State<MassSendReceiverCell> {
|
||||
final FlutterContactPicker contactPicker = FlutterContactPicker();
|
||||
late TextEditingController _receiverController;
|
||||
late TextEditingController _nickNameController;
|
||||
RxString errorTxt = ''.obs;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@ -50,50 +53,95 @@ class _MassSendReceiverCellState extends State<MassSendReceiverCell> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
color: Colors.white,
|
||||
child: Row(
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: widget.onDeleteUser,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 20.w),
|
||||
child: Image.asset(
|
||||
'images/icon_massSend_delete.png',
|
||||
width: 26.w,
|
||||
height: 26.w,
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Container(
|
||||
color: Colors.white,
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
GestureDetector(
|
||||
onTap: widget.onDeleteUser,
|
||||
child: Container(
|
||||
color: Colors.transparent,
|
||||
padding: EdgeInsets.all(20.r),
|
||||
child: Image.asset(
|
||||
'images/icon_massSend_delete.png',
|
||||
width: 26.w,
|
||||
height: 26.w,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
_buildCellWidget(
|
||||
leftTitle: TranslationLoader.lanKeys!.receiver!.tr,
|
||||
isInputField: true,
|
||||
inputHint: TranslationLoader
|
||||
.lanKeys!.pleaseEnterNumberOrEmail!.tr,
|
||||
controller: _receiverController,
|
||||
isContactPickerEnabled: true,
|
||||
onSubmitted: (String text) {
|
||||
final bool isEmail = RegexpTool.isEmail(text);
|
||||
final bool isPhoneNumber =
|
||||
RegexpTool.isPhoneNumber(text);
|
||||
if (text.trim() == '' || isEmail || isPhoneNumber) {
|
||||
errorTxt.value = '';
|
||||
} else {
|
||||
errorTxt.value = '账号格式错误'.tr;
|
||||
}
|
||||
}),
|
||||
Divider(
|
||||
color: AppColors.greyLineColor,
|
||||
indent: 20.w,
|
||||
endIndent: 20.w,
|
||||
height: 1,
|
||||
),
|
||||
_buildCellWidget(
|
||||
leftTitle: TranslationLoader.lanKeys!.name!.tr,
|
||||
isInputField: true,
|
||||
inputHint: TranslationLoader.lanKeys!.enterYourName!.tr,
|
||||
controller: _nickNameController,
|
||||
isContactPickerEnabled: false,
|
||||
onSubmitted: (String text) {
|
||||
final bool isEmail = RegexpTool.isEmail(text);
|
||||
final bool isPhoneNumber =
|
||||
RegexpTool.isPhoneNumber(text);
|
||||
if (text.trim() == '' || isEmail || isPhoneNumber) {
|
||||
errorTxt.value = '';
|
||||
} else {
|
||||
errorTxt.value = '账号格式错误'.tr;
|
||||
}
|
||||
}),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Expanded(
|
||||
child: Column(
|
||||
children: [
|
||||
_buildCellWidget(
|
||||
leftTitle: TranslationLoader.lanKeys!.receiver!.tr,
|
||||
isInputField: true,
|
||||
inputHint:
|
||||
TranslationLoader.lanKeys!.pleaseEnterNumberOrEmail!.tr,
|
||||
controller: _receiverController,
|
||||
isContactPickerEnabled: true,
|
||||
),
|
||||
Divider(
|
||||
color: AppColors.greyLineColor,
|
||||
indent: 20.w,
|
||||
endIndent: 20.w,
|
||||
height: 1,
|
||||
),
|
||||
_buildCellWidget(
|
||||
leftTitle: TranslationLoader.lanKeys!.name!.tr,
|
||||
isInputField: true,
|
||||
inputHint: TranslationLoader.lanKeys!.enterYourName!.tr,
|
||||
controller: _nickNameController,
|
||||
isContactPickerEnabled: false,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Obx(() {
|
||||
return errorTxt.value.trim() != ''
|
||||
? Padding(
|
||||
padding: EdgeInsets.only(
|
||||
left: 80.w,
|
||||
top: 10.h,
|
||||
bottom: 10.h,
|
||||
),
|
||||
child: Text(
|
||||
errorTxt.value,
|
||||
style: TextStyle(
|
||||
color: Colors.red,
|
||||
fontSize: 18.sp,
|
||||
),
|
||||
),
|
||||
)
|
||||
: SizedBox(
|
||||
height: 10.w,
|
||||
);
|
||||
}),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@ -103,20 +151,22 @@ class _MassSendReceiverCellState extends State<MassSendReceiverCell> {
|
||||
required String inputHint,
|
||||
required TextEditingController controller,
|
||||
required bool isContactPickerEnabled,
|
||||
ValueChanged<String>? onSubmitted,
|
||||
}) {
|
||||
return Container(
|
||||
height: 60.h,
|
||||
padding: EdgeInsets.only(right: 20.w),
|
||||
child: Row(
|
||||
children: [
|
||||
children: <Widget>[
|
||||
SizedBox(width: 20.w),
|
||||
Text(leftTitle, style: TextStyle(fontSize: 22.sp)),
|
||||
Expanded(child: SizedBox(width: 10.w)),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
children: <Widget>[
|
||||
if (isInputField)
|
||||
_buildTextField(controller, inputHint, isContactPickerEnabled)
|
||||
_buildTextField(controller, inputHint, isContactPickerEnabled,
|
||||
onSubmitted: onSubmitted)
|
||||
else
|
||||
Text(
|
||||
controller.text,
|
||||
@ -132,11 +182,12 @@ class _MassSendReceiverCellState extends State<MassSendReceiverCell> {
|
||||
}
|
||||
|
||||
Widget _buildTextField(TextEditingController controller, String hintText,
|
||||
bool isContactPickerEnabled) {
|
||||
bool isContactPickerEnabled,
|
||||
{ValueChanged<String>? onSubmitted}) {
|
||||
return SizedBox(
|
||||
width: 380.w,
|
||||
child: Row(
|
||||
children: [
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: TextField(
|
||||
controller: controller,
|
||||
@ -148,6 +199,7 @@ class _MassSendReceiverCellState extends State<MassSendReceiverCell> {
|
||||
hintStyle: TextStyle(fontSize: 22.sp),
|
||||
border: InputBorder.none,
|
||||
),
|
||||
onSubmitted: onSubmitted,
|
||||
),
|
||||
),
|
||||
if (isContactPickerEnabled)
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import 'package:get/get.dart';
|
||||
import 'package:star_lock/main/lockDetail/electronicKey/massSendElectronicKey/massSendLockGroupList/lockUserList/lockUserList_entity.dart';
|
||||
import 'package:star_lock/main/lockDetail/electronicKey/massSendElectronicKey/massSendLockGroupList/massSendReceiver/massSendReceiver_state.dart';
|
||||
import 'package:star_lock/tools/baseGetXController.dart';
|
||||
@ -6,14 +7,25 @@ import 'package:star_lock/tools/storage.dart';
|
||||
class MassSendReceiverLogic extends BaseGetXController {
|
||||
MassSendReceiverState state = MassSendReceiverState();
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
final dynamic data = Get.arguments;
|
||||
if (data is Map && data['lockUserList'] is List) {
|
||||
data['lockUserList'].forEach((dynamic lockUser) {
|
||||
state.lockUserList.add(lockUser);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> onReady() async {
|
||||
super.onReady();
|
||||
|
||||
LockUserItemData data = LockUserItemData();
|
||||
final LockUserItemData data = LockUserItemData();
|
||||
state.lockUserList.add(data);
|
||||
|
||||
var isVip = await Storage.getBool(saveIsVip);
|
||||
final bool? isVip = await Storage.getBool(saveIsVip);
|
||||
state.isVip.value = isVip ?? false;
|
||||
state.isVip.refresh();
|
||||
}
|
||||
|
||||
@ -1,13 +1,17 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:star_lock/appRouters.dart';
|
||||
import 'package:star_lock/app_settings/app_colors.dart';
|
||||
import 'package:star_lock/app_settings/app_settings.dart';
|
||||
import 'package:star_lock/main/lockDetail/electronicKey/massSendElectronicKey/massSendLockGroupList/lockUserList/lockUserList_entity.dart';
|
||||
import 'package:star_lock/main/lockDetail/electronicKey/massSendElectronicKey/massSendLockGroupList/massSendReceiver/massSendReceiverCell.dart';
|
||||
import 'package:star_lock/main/lockDetail/electronicKey/massSendElectronicKey/massSendLockGroupList/massSendReceiver/massSendReceiver_logic.dart';
|
||||
import 'package:star_lock/tools/showCupertinoAlertView.dart';
|
||||
import 'package:star_lock/main/lockDetail/electronicKey/massSendElectronicKey/massSendLockGroupList/massSendReceiver/massSendReceiver_state.dart';
|
||||
import 'package:star_lock/tools/commonItem.dart';
|
||||
import 'package:star_lock/tools/regexp_tool.dart';
|
||||
import 'package:star_lock/tools/showCupertinoAlertView.dart';
|
||||
import 'package:star_lock/translations/trans_lib.dart';
|
||||
|
||||
class MassSendReceiverPage extends StatefulWidget {
|
||||
@ -20,8 +24,8 @@ class MassSendReceiverPage extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _MassSendReceiverPageState extends State<MassSendReceiverPage> {
|
||||
final logic = Get.put(MassSendReceiverLogic());
|
||||
final state = Get.find<MassSendReceiverLogic>().state;
|
||||
final MassSendReceiverLogic logic = Get.put(MassSendReceiverLogic());
|
||||
final MassSendReceiverState state = Get.find<MassSendReceiverLogic>().state;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@ -40,7 +44,7 @@ class _MassSendReceiverPageState extends State<MassSendReceiverPage> {
|
||||
icon: const Icon(Icons.arrow_back_ios, color: Colors.white),
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
),
|
||||
actions: [
|
||||
actions: <Widget>[
|
||||
TextButton(
|
||||
child: Text(
|
||||
TranslationLoader.lanKeys!.save!.tr,
|
||||
@ -50,24 +54,37 @@ class _MassSendReceiverPageState extends State<MassSendReceiverPage> {
|
||||
if (!state.isVip.value) {
|
||||
return;
|
||||
}
|
||||
Map<String, dynamic> resultMap = {};
|
||||
resultMap['lockUserList'] = state.lockUserList.value;
|
||||
if (state.lockUserList.isEmpty) {
|
||||
EasyLoading.showToast('接收者信息为空'.tr);
|
||||
return;
|
||||
}
|
||||
for (final LockUserItemData userItem in state.lockUserList) {
|
||||
final bool isEmail = RegexpTool.isEmail(userItem.userid ?? '');
|
||||
final bool isPhoneNumber =
|
||||
RegexpTool.isPhoneNumber(userItem.userid ?? '');
|
||||
if (!isEmail && !isPhoneNumber) {
|
||||
EasyLoading.showToast('账号格式错误'.tr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
final Map<String, dynamic> resultMap = <String, dynamic>{};
|
||||
resultMap['lockUserList'] = state.lockUserList;
|
||||
Navigator.pop(context, resultMap);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
body: Column(
|
||||
children: [
|
||||
children: <Widget>[
|
||||
Obx(() => Visibility(
|
||||
visible: state.isVip.value ? false : true,
|
||||
visible: !state.isVip.value,
|
||||
child: ShowCupertinoAlertView()
|
||||
.topTipsAdvancedFeatures('开通高级功能后才可以选择和添加接收者'.tr))),
|
||||
Obx(() => Visibility(
|
||||
visible: state.isVip.value ? true : false,
|
||||
visible: state.isVip.value,
|
||||
child: CommonItem(
|
||||
leftTitel: TranslationLoader.lanKeys!.countryAndRegion!.tr,
|
||||
rightTitle: "",
|
||||
rightTitle: '',
|
||||
isHaveLine: true,
|
||||
isHaveRightWidget: true,
|
||||
isHaveDirection: true,
|
||||
@ -78,7 +95,7 @@ class _MassSendReceiverPageState extends State<MassSendReceiverPage> {
|
||||
fontSize: 22.sp, color: AppColors.darkGrayTextColor),
|
||||
),
|
||||
action: () async {
|
||||
var result = await Navigator.pushNamed(
|
||||
final Object? result = await Navigator.pushNamed(
|
||||
context, Routers.selectCountryRegionPage);
|
||||
if (result != null) {
|
||||
result as Map<String, dynamic>;
|
||||
@ -88,24 +105,26 @@ class _MassSendReceiverPageState extends State<MassSendReceiverPage> {
|
||||
}
|
||||
},
|
||||
))),
|
||||
Obx(() => Row(
|
||||
children: [controlViewTitle(0), controlViewTitle(1)],
|
||||
Obx(() => Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 20.h),
|
||||
child: Row(
|
||||
children: <Widget>[controlViewTitle(0), controlViewTitle(1)],
|
||||
),
|
||||
)),
|
||||
SizedBox(
|
||||
height: 2.h,
|
||||
),
|
||||
Obx(() => Visibility(
|
||||
visible: state.isVip.value ? true : false,
|
||||
visible: state.isVip.value,
|
||||
child: Expanded(
|
||||
child: ListView.separated(
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
LockUserItemData data = state.lockUserList.value[index];
|
||||
final LockUserItemData data = state.lockUserList[index];
|
||||
state.emailOrPhoneController.text = data.userid ?? '';
|
||||
state.keyNameController.text = data.nickname ?? '';
|
||||
|
||||
return _itemBuilder(index, data);
|
||||
},
|
||||
itemCount: state.lockUserList.value.length,
|
||||
itemCount: state.lockUserList.length,
|
||||
separatorBuilder: (BuildContext context, int index) {
|
||||
return Divider(
|
||||
height: 20.h,
|
||||
@ -129,7 +148,7 @@ class _MassSendReceiverPageState extends State<MassSendReceiverPage> {
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
children: <Widget>[
|
||||
Image.asset(
|
||||
state.isVip.value
|
||||
? 'images/icon_btn_add.png'
|
||||
@ -141,7 +160,7 @@ class _MassSendReceiverPageState extends State<MassSendReceiverPage> {
|
||||
width: 6.w,
|
||||
),
|
||||
Text(
|
||||
btnIndex == 0 ? '已有' : '新增',
|
||||
btnIndex == 0 ? '已有'.tr : '新增'.tr,
|
||||
style: TextStyle(
|
||||
color: state.isVip.value
|
||||
? AppColors.mainColor
|
||||
@ -158,17 +177,27 @@ class _MassSendReceiverPageState extends State<MassSendReceiverPage> {
|
||||
}
|
||||
if (btnIndex == 0) {
|
||||
//已有
|
||||
Navigator.pushNamed(context, Routers.lockUserListPage).then((val) {
|
||||
Navigator.pushNamed(context, Routers.lockUserListPage)
|
||||
.then((Object? val) {
|
||||
if (val != null) {
|
||||
val as Map<String, dynamic>;
|
||||
state.lockUserList.value = val['lockUserList'];
|
||||
|
||||
if (val['lockUserList'] is List) {
|
||||
final List<int?> uid = state.lockUserList
|
||||
.where((LockUserItemData e) => e.isCheck ?? false)
|
||||
.map((LockUserItemData e) => e.uid)
|
||||
.toList();
|
||||
val['lockUserList'].forEach((LockUserItemData itemData) {
|
||||
if (!uid.contains(itemData.uid)) {
|
||||
state.lockUserList.add(itemData);
|
||||
}
|
||||
});
|
||||
}
|
||||
setState(() {});
|
||||
}
|
||||
});
|
||||
} else if (btnIndex == 1) {
|
||||
//新增
|
||||
state.lockUserList.value.add(LockUserItemData());
|
||||
state.lockUserList.add(LockUserItemData());
|
||||
setState(() {});
|
||||
}
|
||||
},
|
||||
@ -177,12 +206,11 @@ class _MassSendReceiverPageState extends State<MassSendReceiverPage> {
|
||||
|
||||
Widget _itemBuilder(int index, LockUserItemData userData) {
|
||||
return MassSendReceiverCell(
|
||||
currentIndex: index,
|
||||
userData: userData,
|
||||
onDeleteUser: () {
|
||||
state.lockUserList.removeAt(index - 1);
|
||||
setState(() {});
|
||||
},
|
||||
);
|
||||
currentIndex: index,
|
||||
userData: userData,
|
||||
onDeleteUser: () {
|
||||
state.lockUserList.removeAt(index);
|
||||
setState(() {});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,11 +10,11 @@ class MassSendReceiverState {
|
||||
// }
|
||||
// }
|
||||
|
||||
var isVip = false.obs;
|
||||
var lockUserList = <LockUserItemData>[].obs;
|
||||
RxBool isVip = false.obs;
|
||||
RxList<LockUserItemData> lockUserList = <LockUserItemData>[].obs;
|
||||
TextEditingController emailOrPhoneController = TextEditingController();
|
||||
TextEditingController keyNameController = TextEditingController();
|
||||
|
||||
var countryCode = '86'.obs;
|
||||
var countryName = '中国'.obs;
|
||||
RxString countryCode = '86'.obs;
|
||||
RxString countryName = '中国'.obs;
|
||||
}
|
||||
|
||||
@ -1,11 +1,10 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_easyloading/flutter_easyloading.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:get/get.dart';
|
||||
import '../../../../flavors.dart';
|
||||
|
||||
import '../../../../app_settings/app_colors.dart';
|
||||
import '../../../../blue/blue_manage.dart';
|
||||
import '../../../../tools/appRouteObserver.dart';
|
||||
import '../../../../tools/showTipView.dart';
|
||||
import '../../../../tools/submitBtn.dart';
|
||||
@ -23,7 +22,7 @@ class ResetButtonPage extends StatefulWidget {
|
||||
class _ResetButtonPageState extends State<ResetButtonPage> with RouteAware {
|
||||
final logic = Get.put(ResetButtonLogic());
|
||||
final state = Get.find<ResetButtonLogic>().state;
|
||||
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
@ -44,10 +43,16 @@ class _ResetButtonPageState extends State<ResetButtonPage> with RouteAware {
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
TranslationLoader.lanKeys!.resetButtonTip1!.tr,
|
||||
style: TextStyle(fontSize: 20.sp),
|
||||
),
|
||||
if (F.isSKY)
|
||||
Text(
|
||||
TranslationLoader.lanKeys!.resetButtonTip1!.tr,
|
||||
style: TextStyle(fontSize: 20.sp),
|
||||
)
|
||||
else
|
||||
Text(
|
||||
'开启后,可通过长按锁上的设置键重新上电,用APP重新添加'.tr,
|
||||
style: TextStyle(fontSize: 20.sp),
|
||||
),
|
||||
SizedBox(
|
||||
height: 10.h,
|
||||
),
|
||||
@ -63,35 +68,38 @@ class _ResetButtonPageState extends State<ResetButtonPage> with RouteAware {
|
||||
height: 30.h,
|
||||
),
|
||||
Obx(() => Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
"${TranslationLoader.lanKeys!.currentMode!.tr} : ${state.resetButtonEnable.value == 1 ? TranslationLoader.lanKeys!.opened!.tr : TranslationLoader.lanKeys!.closed!.tr}",
|
||||
style:
|
||||
TextStyle(fontWeight: FontWeight.w600, fontSize: 20.sp),
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
"${TranslationLoader.lanKeys!.currentMode!.tr} : ${state.resetButtonEnable.value == 1 ? TranslationLoader.lanKeys!.opened!.tr : TranslationLoader.lanKeys!.closed!.tr}",
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.w600, fontSize: 20.sp),
|
||||
)),
|
||||
],
|
||||
)),
|
||||
],
|
||||
)),
|
||||
SizedBox(
|
||||
height: 30.h,
|
||||
),
|
||||
Obx(() => SubmitBtn(
|
||||
btnName: state.resetButtonEnable.value == 1 ? TranslationLoader.lanKeys!.close!.tr : TranslationLoader.lanKeys!.open!.tr,
|
||||
btnName: state.resetButtonEnable.value == 1
|
||||
? TranslationLoader.lanKeys!.close!.tr
|
||||
: TranslationLoader.lanKeys!.open!.tr,
|
||||
borderRadius: 20.w,
|
||||
fontSize: 32.sp,
|
||||
// margin: EdgeInsets.only(left: 03.w, right: 30.w, top: 20.w),
|
||||
padding: EdgeInsets.only(top: 20.w, bottom: 20.w),
|
||||
onClick: () {
|
||||
// showDeletAlertTipDialog(context);
|
||||
ShowTipView().showIosTipWithContentDialog('确定要${state.resetButtonEnable.value == 1 ? TranslationLoader.lanKeys!.close!.tr : TranslationLoader.lanKeys!.open!.tr}重置键?', () {
|
||||
ShowTipView().showIosTipWithContentDialog(
|
||||
'确定要${state.resetButtonEnable.value == 1 ? TranslationLoader.lanKeys!.close!.tr : TranslationLoader.lanKeys!.open!.tr}重置键?',
|
||||
() {
|
||||
logic.sendBurglarAlarm();
|
||||
});
|
||||
})),
|
||||
],
|
||||
),
|
||||
)
|
||||
);
|
||||
));
|
||||
}
|
||||
|
||||
@override
|
||||
@ -144,5 +152,4 @@ class _ResetButtonPageState extends State<ResetButtonPage> with RouteAware {
|
||||
state.ifCurrentScreen.value = false;
|
||||
state.sureBtnState.value = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,7 +1,11 @@
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
import 'package:connectivity_plus/connectivity_plus.dart';
|
||||
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
import 'package:star_lock/main/lockMian/lockList/lockList_logic.dart';
|
||||
import 'package:star_lock/tools/showTipView.dart';
|
||||
|
||||
import '../../../app_settings/app_settings.dart';
|
||||
import '../../../blue/blue_manage.dart';
|
||||
@ -17,7 +21,8 @@ class LockMainLogic extends BaseGetXController {
|
||||
|
||||
Future<LockListInfoEntity> getStarLockInfo(
|
||||
{bool isUnShowLoading = false}) async {
|
||||
LockListInfoEntity entity = await ApiRepository.to.getStarLockListInfo(
|
||||
final LockListInfoEntity entity =
|
||||
await ApiRepository.to.getStarLockListInfo(
|
||||
pageNo: pageNo,
|
||||
pageSize: 50,
|
||||
isUnShowLoading: isUnShowLoading,
|
||||
@ -59,33 +64,35 @@ class LockMainLogic extends BaseGetXController {
|
||||
|
||||
/// 获取联网类型
|
||||
void getConnectType() async {
|
||||
var connectResult = await (Connectivity().checkConnectivity());
|
||||
final ConnectivityResult connectResult =
|
||||
await (Connectivity().checkConnectivity());
|
||||
if (connectResult == ConnectivityResult.mobile) {
|
||||
// _netType = "4G";
|
||||
state.networkConnectionStatus.value = 1;
|
||||
AppLog.log("网络连接: 4G 4G 4G 4G 4G");
|
||||
AppLog.log('网络连接: 4G 4G 4G 4G 4G');
|
||||
} else if (connectResult == ConnectivityResult.wifi) {
|
||||
// _netType = "wifi";
|
||||
state.networkConnectionStatus.value = 1;
|
||||
AppLog.log("网络连接: wifi wifi wifi wifi wifi");
|
||||
AppLog.log('网络连接: wifi wifi wifi wifi wifi');
|
||||
} else {
|
||||
// _netType = "未连接";
|
||||
state.networkConnectionStatus.value = 0;
|
||||
AppLog.log("网络连接: 未连接 未连接 未连接 未连接 未连接");
|
||||
AppLog.log('网络连接: 未连接 未连接 未连接 未连接 未连接');
|
||||
// showToast("网络访问失败,请检查网络是否正常");
|
||||
}
|
||||
}
|
||||
|
||||
/// 判断网络是否连接
|
||||
Future<bool> isConnected() async {
|
||||
var connectResult = await (Connectivity().checkConnectivity());
|
||||
final ConnectivityResult connectResult =
|
||||
await Connectivity().checkConnectivity();
|
||||
return connectResult != ConnectivityResult.none;
|
||||
}
|
||||
|
||||
/// 设置网络切换监听
|
||||
connectListener() async {
|
||||
Future<void> connectListener() async {
|
||||
Connectivity().onConnectivityChanged.listen((ConnectivityResult result) {
|
||||
AppLog.log("设置网络切换监听:$result");
|
||||
AppLog.log('设置网络切换监听:$result');
|
||||
if (state.networkConnectionStatus.value == 0 &&
|
||||
result != ConnectivityResult.none) {
|
||||
// 从无网络到有网络
|
||||
@ -95,36 +102,52 @@ class LockMainLogic extends BaseGetXController {
|
||||
});
|
||||
}
|
||||
|
||||
/// 检测推送是否开启
|
||||
Future<void> checkWhetherPushIsEnabled() async {
|
||||
bool notificationEnabled = false;
|
||||
|
||||
if (Platform.isAndroid) {
|
||||
notificationEnabled = await FlutterLocalNotificationsPlugin()
|
||||
.resolvePlatformSpecificImplementation<
|
||||
AndroidFlutterLocalNotificationsPlugin>()
|
||||
?.areNotificationsEnabled() ??
|
||||
false;
|
||||
} else if (Platform.isIOS) {
|
||||
notificationEnabled = await FlutterLocalNotificationsPlugin()
|
||||
.resolvePlatformSpecificImplementation<
|
||||
IOSFlutterLocalNotificationsPlugin>()
|
||||
?.requestPermissions(
|
||||
alert: true,
|
||||
badge: false,
|
||||
sound: true,
|
||||
) ??
|
||||
false;
|
||||
}
|
||||
if (!notificationEnabled) {
|
||||
//推送未开启
|
||||
ShowTipView().showIosTipWithContentDialog(
|
||||
'为了让您及时收到重要通知和更新,我们需要获取通知权限。请点击“确定”按钮,然后在设置页面中启用通知权限。'.tr, () async {
|
||||
openAppSettings();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void onReady() {
|
||||
// TODO: implement onReady
|
||||
super.onReady();
|
||||
|
||||
// 开启UDP
|
||||
UdpHelp().openUDP();
|
||||
|
||||
BlueManage();
|
||||
}
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
// TODO: implement onInit
|
||||
super.onInit();
|
||||
|
||||
// getLockInfo();
|
||||
// 设置网络变化监听
|
||||
// connectListener();
|
||||
// 获取网络连接状态
|
||||
// getConnectType();
|
||||
checkWhetherPushIsEnabled();
|
||||
}
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
// TODO: implement onClose
|
||||
super.onClose();
|
||||
|
||||
// refreshController.dispose();
|
||||
// _teamEvent.cancel();
|
||||
// state.timer.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@ -54,9 +54,6 @@ class _StarLockMainPageState extends State<StarLockMainPage> with BaseWidget {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
||||
setState(() {});
|
||||
});
|
||||
// if (mounted) {
|
||||
// setSŒe(() {});
|
||||
// }
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@ -5,7 +5,10 @@ import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:star_lock/main/lockMian/lockMain/lockMain_page.dart';
|
||||
import 'package:star_lock/main/lockMian/lockMain/xhj/lockMain_xhj_state.dart';
|
||||
import 'package:star_lock/mine/minePersonInfo/minePersonInfoPage/minePersonInfo_entity.dart';
|
||||
import 'package:star_lock/network/api_repository.dart';
|
||||
import 'package:star_lock/tools/baseGetXController.dart';
|
||||
import 'package:star_lock/tools/storage.dart';
|
||||
|
||||
class LockMainXHJLogic extends BaseGetXController {
|
||||
final LockMainXHJState state = LockMainXHJState();
|
||||
@ -17,6 +20,14 @@ class LockMainXHJLogic extends BaseGetXController {
|
||||
|
||||
bool get isMall => state.index ==1;
|
||||
|
||||
//用户信息
|
||||
Future<void> getUserInfoRequest() async {
|
||||
final MinePersonInfoEntity entity = await ApiRepository.to.getUserInfo();
|
||||
if (entity.errorCode!.codeIsSuccessful) {
|
||||
Storage.setBool(saveIsVip, entity.data!.isVip==1);
|
||||
}
|
||||
}
|
||||
|
||||
//打开设备弹窗
|
||||
void openEquipment() {
|
||||
showModalBottomSheet(
|
||||
@ -48,6 +59,7 @@ class LockMainXHJLogic extends BaseGetXController {
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
getUserInfoRequest();
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@ -39,7 +39,7 @@ class StarLockMineLogic extends BaseGetXController {
|
||||
});
|
||||
}
|
||||
|
||||
getMineInfoData() async {
|
||||
Future<void> getMineInfoData() async {
|
||||
final String? data = await Storage.getString(saveUserLoginData);
|
||||
if (data != null && data.isNotEmpty) {
|
||||
state.userNickName.value = (await Storage.getNickname())!;
|
||||
@ -59,7 +59,6 @@ class StarLockMineLogic extends BaseGetXController {
|
||||
@override
|
||||
Future<void> onInit() async {
|
||||
super.onInit();
|
||||
|
||||
getMineInfoData();
|
||||
}
|
||||
|
||||
|
||||
@ -28,7 +28,7 @@ class StarLockMinePageState extends State<StarLockMinePage> with BaseWidget {
|
||||
final StarLockMineState state = Get.find<StarLockMineLogic>().state;
|
||||
|
||||
@override
|
||||
initState() {
|
||||
void initState() {
|
||||
super.initState();
|
||||
logic.getUserInfoRequest();
|
||||
}
|
||||
|
||||
@ -12,10 +12,11 @@ import 'lockUserManageList_state.dart';
|
||||
|
||||
class LockUserManageListLogic extends BaseGetXController {
|
||||
final LockUserManageListState state = LockUserManageListState();
|
||||
StreamSubscription? _getElectronicKeyListRefreshUIEvent;
|
||||
|
||||
//请求锁用户列表
|
||||
Future<LockUserListEntity> lockUserListRequest() async {
|
||||
LockUserListEntity entity =
|
||||
final LockUserListEntity entity =
|
||||
await ApiRepository.to.lockUserList(pageNo.toString(), pageSize, state.searchController.text);
|
||||
if(entity.errorCode!.codeIsSuccessful){
|
||||
if (pageNo == 1) {
|
||||
@ -23,7 +24,7 @@ class LockUserManageListLogic extends BaseGetXController {
|
||||
pageNo++;
|
||||
} else {
|
||||
if (entity.data!.isNotEmpty) {
|
||||
state.dataList.value.addAll(entity.data!);
|
||||
state.dataList.addAll(entity.data!);
|
||||
pageNo++;
|
||||
}
|
||||
}
|
||||
@ -33,7 +34,7 @@ class LockUserManageListLogic extends BaseGetXController {
|
||||
|
||||
//删除锁用户管理
|
||||
Future<void> deletelockUserRequest(int uid) async {
|
||||
var entity = await ApiRepository.to.deletLockUser(uid);
|
||||
final entity = await ApiRepository.to.deletLockUser(uid);
|
||||
if (entity.errorCode!.codeIsSuccessful) {
|
||||
EasyLoading.showToast('删除成功',duration: 2000.milliseconds);
|
||||
showToast('删除成功', something: (){
|
||||
@ -44,7 +45,6 @@ class LockUserManageListLogic extends BaseGetXController {
|
||||
}
|
||||
|
||||
/// 刷新电子钥匙列表
|
||||
StreamSubscription? _getElectronicKeyListRefreshUIEvent;
|
||||
void _getElectronicKeyListRefreshUIAction() {
|
||||
// 蓝牙协议通知传输跟蓝牙之外的数据传输类不一样 eventBus
|
||||
_getElectronicKeyListRefreshUIEvent = eventBus.on<LockUserManageListRefreshUI>().listen((event) {
|
||||
@ -55,23 +55,18 @@ class LockUserManageListLogic extends BaseGetXController {
|
||||
|
||||
@override
|
||||
void onReady() {
|
||||
// TODO: implement onReady
|
||||
super.onReady();
|
||||
|
||||
_getElectronicKeyListRefreshUIAction();
|
||||
}
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
// TODO: implement onInit
|
||||
super.onInit();
|
||||
}
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
// TODO: implement onClose
|
||||
super.onClose();
|
||||
|
||||
_getElectronicKeyListRefreshUIEvent?.cancel();
|
||||
}
|
||||
}
|
||||
@ -38,7 +38,6 @@ class _LockUserManageListPageState extends State<LockUserManageListPage> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
getHttpData();
|
||||
}
|
||||
|
||||
|
||||
@ -15,7 +15,7 @@ class NewSMSTemplateLogic extends BaseGetXController {
|
||||
//获取默认模板-- 1:电子钥匙 2:密码
|
||||
Future<void> getDefaultTemplate() async {
|
||||
final NewSMSTemplateEntity entity = await ApiRepository.to
|
||||
.getDefaultTemplate(type: state.currentTemplate.value.type ?? 0);
|
||||
.getDefaultTemplate(type: state.templateType.value);
|
||||
if (entity.errorCode!.codeIsSuccessful) {
|
||||
state.templateList.value = entity.dataList ?? <SMSTemplateData>[];
|
||||
if (state.templateList.isNotEmpty) {
|
||||
@ -59,9 +59,32 @@ class NewSMSTemplateLogic extends BaseGetXController {
|
||||
}
|
||||
}
|
||||
|
||||
List<TextSpan> buildElectronicKeySpan({required bool isPreview}) {
|
||||
final List<TextSpan> textSpans = <TextSpan>[];
|
||||
// 更新短信条数的函数
|
||||
void updateSmsCost(String template) {
|
||||
state.smsCost.value = calculateSmsCost(template);
|
||||
}
|
||||
|
||||
int calculateSmsCost(String template) {
|
||||
final int smsCount = template.length;
|
||||
if (smsCount <= 70) {
|
||||
return 1;
|
||||
} else {
|
||||
return (smsCount / 67).ceil();
|
||||
}
|
||||
}
|
||||
|
||||
//构建电子钥匙模板
|
||||
List<TextSpan> buildElectronicKeySpan({required bool isPreview}) {
|
||||
//短信模版
|
||||
if (state.templateType.value == 1) {
|
||||
return _buildSMSElectronicKey(isPreview);
|
||||
} else {
|
||||
return _buildEmailElectronicKey(isPreview);
|
||||
}
|
||||
}
|
||||
|
||||
List<TextSpan> _buildSMSElectronicKey(bool isPreview) {
|
||||
final List<TextSpan> textSpans = <TextSpan>[];
|
||||
// 如果是预览模式,添加预览模板的文本
|
||||
if (isPreview) {
|
||||
textSpans.add(
|
||||
@ -74,7 +97,7 @@ class NewSMSTemplateLogic extends BaseGetXController {
|
||||
// 将模板分割为文本片段
|
||||
final List<String> textFragments = state.currentTemplate.value.template
|
||||
?.split(RegularExpression.urlRegExp) ??
|
||||
[];
|
||||
<String>[];
|
||||
|
||||
// 添加链接文本和普通文本到文本片段列表
|
||||
for (int i = 0; i < textFragments.length; i++) {
|
||||
@ -115,7 +138,62 @@ class NewSMSTemplateLogic extends BaseGetXController {
|
||||
),
|
||||
);
|
||||
}
|
||||
return textSpans;
|
||||
}
|
||||
|
||||
List<TextSpan> _buildEmailElectronicKey(bool isPreview) {
|
||||
final List<TextSpan> textSpans = <TextSpan>[];
|
||||
|
||||
//邮件模版
|
||||
// 如果是预览模式,添加预览模板的文本
|
||||
if (isPreview) {
|
||||
textSpans.add(
|
||||
TextSpan(
|
||||
text: '${state.templateOneTf.text}\n',
|
||||
style: state.defaultStyle,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
String template = state.currentTemplate.value.template ?? '';
|
||||
template = template.replaceAll(',', ',\n');
|
||||
|
||||
// 定义匹配 ${} 包围的变量的正则表达式
|
||||
final RegExp variableRegExp = RegExp(r'\{([^}]+)\}');
|
||||
final Iterable<Match> matches = variableRegExp.allMatches(template);
|
||||
|
||||
int start = 0;
|
||||
for (final Match match in matches) {
|
||||
// 添加非变量文本
|
||||
if (match.start > start) {
|
||||
textSpans.add(
|
||||
TextSpan(
|
||||
text: template.substring(start, match.start),
|
||||
style: state.defaultStyle,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// 添加变量文本
|
||||
textSpans.add(
|
||||
TextSpan(
|
||||
text: match.group(0),
|
||||
style: state.highStyle,
|
||||
),
|
||||
);
|
||||
|
||||
start = match.end;
|
||||
}
|
||||
|
||||
// 添加剩余的非变量文本
|
||||
if (start < template.length) {
|
||||
textSpans.add(
|
||||
TextSpan(
|
||||
text: template.substring(start),
|
||||
style: state.defaultStyle,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
return textSpans;
|
||||
}
|
||||
|
||||
@ -132,64 +210,68 @@ class NewSMSTemplateLogic extends BaseGetXController {
|
||||
);
|
||||
}
|
||||
|
||||
// 定义匹配 ${} 包围的变量的正则表达式
|
||||
final RegExp variableRegExp = RegExp(r'\$\{([^}]+)\}');
|
||||
//短信模版才需要加默认模版
|
||||
if (state.templateType == 1 ||
|
||||
(state.templateType == 2 && isPreview == false)) {
|
||||
// 定义匹配 ${} 包围的变量的正则表达式
|
||||
final RegExp variableRegExp = RegExp(r'\$\{([^}]+)\}');
|
||||
|
||||
final String template = state.currentTemplate.value.template ?? '';
|
||||
final String template = state.currentTemplate.value.template ?? '';
|
||||
|
||||
// 对模板进行处理
|
||||
int startIndex = 0;
|
||||
for (final Match match in variableRegExp.allMatches(template)) {
|
||||
// 处理变量之前的文本
|
||||
final String nonVariableText =
|
||||
template.substring(startIndex, match.start);
|
||||
// 对模板进行处理
|
||||
int startIndex = 0;
|
||||
for (final Match match in variableRegExp.allMatches(template)) {
|
||||
// 处理变量之前的文本
|
||||
final String nonVariableText =
|
||||
template.substring(startIndex, match.start);
|
||||
// 替换非变量文本中的字符
|
||||
final String replacedNonVariableText =
|
||||
nonVariableText.replaceAllMapped(RegExp(r',|。'), (Match match) {
|
||||
return '${match.group(0)}\n';
|
||||
});
|
||||
textSpans.add(
|
||||
TextSpan(
|
||||
text: replacedNonVariableText,
|
||||
style: state.defaultStyle,
|
||||
),
|
||||
);
|
||||
|
||||
// 处理变量
|
||||
final String variableText = match.group(0) ?? '';
|
||||
textSpans.add(
|
||||
TextSpan(
|
||||
text: variableText,
|
||||
style: state.highStyle,
|
||||
),
|
||||
);
|
||||
|
||||
// 更新起始索引
|
||||
startIndex = match.end;
|
||||
}
|
||||
|
||||
// 添加最后一个变量之后的文本
|
||||
final String remainingText = template.substring(startIndex);
|
||||
// 替换非变量文本中的字符
|
||||
final String replacedNonVariableText =
|
||||
nonVariableText.replaceAllMapped(RegExp(r',|。'), (Match match) {
|
||||
final String replacedRemainingText =
|
||||
remainingText.replaceAllMapped(RegExp(r',|。'), (Match match) {
|
||||
return '${match.group(0)}\n';
|
||||
});
|
||||
textSpans.add(
|
||||
TextSpan(
|
||||
text: replacedNonVariableText,
|
||||
text: replacedRemainingText,
|
||||
style: state.defaultStyle,
|
||||
),
|
||||
);
|
||||
|
||||
// 处理变量
|
||||
final String variableText = match.group(0) ?? '';
|
||||
textSpans.add(
|
||||
TextSpan(
|
||||
text: variableText,
|
||||
style: state.highStyle,
|
||||
),
|
||||
);
|
||||
|
||||
// 更新起始索引
|
||||
startIndex = match.end;
|
||||
}
|
||||
|
||||
// 添加最后一个变量之后的文本
|
||||
final String remainingText = template.substring(startIndex);
|
||||
// 替换非变量文本中的字符
|
||||
final String replacedRemainingText =
|
||||
remainingText.replaceAllMapped(RegExp(r',|。'), (Match match) {
|
||||
return '${match.group(0)}\n';
|
||||
});
|
||||
textSpans.add(
|
||||
TextSpan(
|
||||
text: replacedRemainingText,
|
||||
style: state.defaultStyle,
|
||||
),
|
||||
);
|
||||
|
||||
// 在预览模式下,添加预览模板的文本
|
||||
if (isPreview) {
|
||||
textSpans.add(
|
||||
TextSpan(
|
||||
text: '\n${state.templateTwoTf.text}',
|
||||
style: state.defaultStyle,
|
||||
),
|
||||
);
|
||||
// 在预览模式下,添加预览模板的文本
|
||||
if (isPreview) {
|
||||
textSpans.add(
|
||||
TextSpan(
|
||||
text: '\n${state.templateTwoTf.text}',
|
||||
style: state.defaultStyle,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return textSpans;
|
||||
|
||||
@ -28,7 +28,7 @@ class _NewSMSTemplatePageState extends State<NewSMSTemplatePage> {
|
||||
return Scaffold(
|
||||
backgroundColor: AppColors.mainBackgroundColor,
|
||||
appBar: TitleAppBar(
|
||||
barTitle: state.templateType.value == 1 ? '新建短信模版'.tr : '新建邮件模版'.tr,
|
||||
barTitle: state.templateType == 1 ? '新建短信模版'.tr : '新建邮件模版'.tr,
|
||||
haveBack: true,
|
||||
backgroundColor: AppColors.mainColor,
|
||||
),
|
||||
@ -109,18 +109,24 @@ class _NewSMSTemplatePageState extends State<NewSMSTemplatePage> {
|
||||
height: 100,
|
||||
child: _buildTextField(state.templateOneTf),
|
||||
),
|
||||
Obx(() => _buildTemplateWithType(isPreview: false)),
|
||||
Obx(() => Container(
|
||||
width: 1.sw - 50.w,
|
||||
margin: EdgeInsets.only(left: 25.w, right: 25.w),
|
||||
child: _buildTemplateWithType(isPreview: false),
|
||||
)),
|
||||
SizedBox(height: 10.h),
|
||||
Container(
|
||||
margin: EdgeInsets.symmetric(horizontal: 25.w, vertical: 25.h),
|
||||
height: 100,
|
||||
child: Stack(
|
||||
alignment: Alignment.bottomRight,
|
||||
children: <Widget>[
|
||||
_buildTextField(state.templateTwoTf),
|
||||
],
|
||||
),
|
||||
),
|
||||
Obx(() => Visibility(
|
||||
visible: state.templateType.value == 1,
|
||||
child: Container(
|
||||
margin: EdgeInsets.symmetric(horizontal: 25.w, vertical: 25.h),
|
||||
height: 100,
|
||||
child: Stack(
|
||||
alignment: Alignment.bottomRight,
|
||||
children: <Widget>[
|
||||
_buildTextField(state.templateTwoTf),
|
||||
],
|
||||
),
|
||||
))),
|
||||
],
|
||||
),
|
||||
);
|
||||
@ -144,7 +150,9 @@ class _NewSMSTemplatePageState extends State<NewSMSTemplatePage> {
|
||||
),
|
||||
),
|
||||
Obx(() => Container(
|
||||
width: 1.sw - 50.w,
|
||||
margin: EdgeInsets.only(left: 25.w, right: 25.w),
|
||||
padding: EdgeInsets.only(left: 20.w, right: 20.w, top: 10.h),
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xFFF5F5F5),
|
||||
borderRadius: BorderRadius.circular(10.h),
|
||||
@ -158,7 +166,7 @@ class _NewSMSTemplatePageState extends State<NewSMSTemplatePage> {
|
||||
bottom: 25.h,
|
||||
),
|
||||
child: Text(
|
||||
'预计产生短信条数:2',
|
||||
'预计产生短信条数:${state.smsCost.value}',
|
||||
style: TextStyle(
|
||||
color: Colors.grey,
|
||||
fontSize: 20.sp,
|
||||
@ -176,19 +184,12 @@ class _NewSMSTemplatePageState extends State<NewSMSTemplatePage> {
|
||||
state.currentTemplate.value.template!.isEmpty) {
|
||||
return const SizedBox.shrink(); // 如果为空,返回一个空的 SizedBox
|
||||
} else {
|
||||
return Row(
|
||||
children: <Widget>[
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 25.w, vertical: 10.h),
|
||||
child: Obx(() => RichText(
|
||||
text: TextSpan(
|
||||
children: state.currentTemplate.value.typeName == '电子钥匙'
|
||||
? logic.buildElectronicKeySpan(isPreview: isPreview)
|
||||
: logic.buildPasswordSpan(isPreview: isPreview),
|
||||
),
|
||||
)),
|
||||
),
|
||||
],
|
||||
return RichText(
|
||||
text: TextSpan(
|
||||
children: state.currentTemplate.value.typeName == '电子钥匙'
|
||||
? logic.buildElectronicKeySpan(isPreview: isPreview)
|
||||
: logic.buildPasswordSpan(isPreview: isPreview),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -213,6 +214,7 @@ class _NewSMSTemplatePageState extends State<NewSMSTemplatePage> {
|
||||
onChanged: (String value) {
|
||||
setState(() {
|
||||
controller.text = value;
|
||||
logic.updateSmsCost(value); // 更新短信条数
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
@ -30,7 +30,8 @@ class NewSMSTemplateState {
|
||||
|
||||
RxBool isVip = false.obs;
|
||||
RxList<SMSTemplateData> templateList = <SMSTemplateData>[].obs;
|
||||
Rx<SMSTemplateData> currentTemplate = SMSTemplateData().obs;
|
||||
RxBool isShowDate = false.obs;
|
||||
RxInt templateType = 0.obs;
|
||||
Rx<SMSTemplateData> currentTemplate = SMSTemplateData().obs; //当前模板信息
|
||||
RxBool isShowDate = false.obs; //是否显示日期
|
||||
RxInt templateType = 0.obs; //1:短信 2:邮件
|
||||
RxInt smsCost = 0.obs; //短信条数
|
||||
}
|
||||
|
||||
@ -12,9 +12,8 @@ import '../../../../tools/baseGetXController.dart';
|
||||
class CustomSMSTemplateListLogic extends BaseGetXController {
|
||||
CustomSMSTemplateListState state = CustomSMSTemplateListState();
|
||||
|
||||
//获取短信模板列表
|
||||
// 获取短信模板列表
|
||||
Future<void> getSMSTemplateListRequest({required bool isRefresh}) async {
|
||||
// 如果是下拉刷新,清空已有数据
|
||||
if (isRefresh) {
|
||||
state.smsTemplateList.clear();
|
||||
pageNo = 1;
|
||||
@ -31,7 +30,7 @@ class CustomSMSTemplateListLogic extends BaseGetXController {
|
||||
}
|
||||
}
|
||||
|
||||
//删除短信模版
|
||||
// 删除短信模板
|
||||
Future<void> deleteSMSTemplateRequest({required int id}) async {
|
||||
final LoginEntity entity =
|
||||
await ApiRepository.to.deleteTemplateInfo(id: id);
|
||||
@ -42,131 +41,75 @@ class CustomSMSTemplateListLogic extends BaseGetXController {
|
||||
|
||||
List<TextSpan> buildElectronicKeySpan(
|
||||
{required CustomSMSTemplateItem templateData}) {
|
||||
final List<TextSpan> textSpans = <TextSpan>[];
|
||||
|
||||
textSpans.add(
|
||||
TextSpan(
|
||||
text: '${templateData.regards}\n',
|
||||
style: state.defaultStyle,
|
||||
),
|
||||
);
|
||||
// 将模板分割为文本片段
|
||||
final List<String> textFragments =
|
||||
templateData.template?.split(RegularExpression.urlRegExp) ?? [];
|
||||
|
||||
// 添加链接文本和普通文本到文本片段列表
|
||||
for (int i = 0; i < textFragments.length; i++) {
|
||||
final String textFragment = textFragments[i];
|
||||
// 添加普通文本
|
||||
textSpans.add(
|
||||
TextSpan(
|
||||
text: textFragment,
|
||||
style: state.defaultStyle,
|
||||
),
|
||||
);
|
||||
// 如果不是最后一个文本片段,则添加换行符
|
||||
if (i < textFragments.length - 1) {
|
||||
textSpans.add(
|
||||
TextSpan(
|
||||
text: '\n',
|
||||
style: state.defaultStyle,
|
||||
),
|
||||
);
|
||||
// 添加链接文本
|
||||
textSpans.add(
|
||||
TextSpan(
|
||||
text: RegularExpression.urlRegExp
|
||||
.stringMatch(templateData.template!) ??
|
||||
'',
|
||||
style: state.highStyle,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
textSpans.add(
|
||||
TextSpan(
|
||||
text: '\n${templateData.tips}',
|
||||
style: state.defaultStyle,
|
||||
),
|
||||
);
|
||||
|
||||
final List<TextSpan> textSpans = [];
|
||||
_addTextSpan(textSpans, '${templateData.regards}\n', state.defaultStyle);
|
||||
_buildTextSpansFromTemplate(
|
||||
textSpans, templateData.template, state.defaultStyle, state.highStyle);
|
||||
_addTextSpan(textSpans, '\n${templateData.tips}', state.defaultStyle);
|
||||
return textSpans;
|
||||
}
|
||||
|
||||
List<TextSpan> buildPasswordSpan(
|
||||
{required CustomSMSTemplateItem templateData}) {
|
||||
final List<TextSpan> textSpans = <TextSpan>[];
|
||||
|
||||
textSpans.add(
|
||||
TextSpan(
|
||||
text: '${templateData.regards}\n',
|
||||
style: state.defaultStyle,
|
||||
),
|
||||
);
|
||||
|
||||
// 定义匹配 ${} 包围的变量的正则表达式
|
||||
final RegExp variableRegExp = RegExp(r'\$\{([^}]+)\}');
|
||||
|
||||
final String template = templateData.template ?? '';
|
||||
|
||||
// 对模板进行处理
|
||||
int startIndex = 0;
|
||||
for (final Match match in variableRegExp.allMatches(template)) {
|
||||
// 处理变量之前的文本
|
||||
final String nonVariableText =
|
||||
template.substring(startIndex, match.start);
|
||||
// 替换非变量文本中的字符
|
||||
final String replacedNonVariableText =
|
||||
nonVariableText.replaceAllMapped(RegExp(r',|。'), (Match match) {
|
||||
return '${match.group(0)}\n';
|
||||
});
|
||||
textSpans.add(
|
||||
TextSpan(
|
||||
text: replacedNonVariableText,
|
||||
style: state.defaultStyle,
|
||||
),
|
||||
);
|
||||
|
||||
// 处理变量
|
||||
final String variableText = match.group(0) ?? '';
|
||||
textSpans.add(
|
||||
TextSpan(
|
||||
text: variableText,
|
||||
style: state.highStyle,
|
||||
),
|
||||
);
|
||||
|
||||
// 更新起始索引
|
||||
startIndex = match.end;
|
||||
}
|
||||
|
||||
// 添加最后一个变量之后的文本
|
||||
final String remainingText = template.substring(startIndex);
|
||||
// 替换非变量文本中的字符
|
||||
final String replacedRemainingText =
|
||||
remainingText.replaceAllMapped(RegExp(r',|。'), (Match match) {
|
||||
return '${match.group(0)}\n';
|
||||
});
|
||||
textSpans.add(
|
||||
TextSpan(
|
||||
text: replacedRemainingText,
|
||||
style: state.defaultStyle,
|
||||
),
|
||||
);
|
||||
|
||||
textSpans.add(
|
||||
TextSpan(
|
||||
text: '\n${templateData.tips}',
|
||||
style: state.defaultStyle,
|
||||
),
|
||||
);
|
||||
|
||||
final List<TextSpan> textSpans = [];
|
||||
_addTextSpan(textSpans, '${templateData.regards}\n', state.defaultStyle);
|
||||
_buildPasswordTextSpans(
|
||||
textSpans, templateData.template, state.defaultStyle, state.highStyle);
|
||||
_addTextSpan(textSpans, '\n${templateData.tips}', state.defaultStyle);
|
||||
return textSpans;
|
||||
}
|
||||
|
||||
void _buildTextSpansFromTemplate(List<TextSpan> textSpans, String? template,
|
||||
TextStyle defaultStyle, TextStyle highStyle) {
|
||||
final List<String> textFragments =
|
||||
template?.split(RegularExpression.urlRegExp) ?? [];
|
||||
for (int i = 0; i < textFragments.length; i++) {
|
||||
_addTextSpan(textSpans, textFragments[i], defaultStyle);
|
||||
if (i < textFragments.length - 1) {
|
||||
_addTextSpan(textSpans, '\n', defaultStyle);
|
||||
_addTextSpan(
|
||||
textSpans,
|
||||
RegularExpression.urlRegExp.stringMatch(template!) ?? '',
|
||||
highStyle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _buildPasswordTextSpans(List<TextSpan> textSpans, String? template,
|
||||
TextStyle defaultStyle, TextStyle highStyle) {
|
||||
final RegExp variableRegExp = RegExp(r'\$\{([^}]+)\}');
|
||||
final String text = template ?? '';
|
||||
int startIndex = 0;
|
||||
|
||||
for (final Match match in variableRegExp.allMatches(text)) {
|
||||
_addTextSpan(
|
||||
textSpans,
|
||||
text
|
||||
.substring(startIndex, match.start)
|
||||
.replaceAllMapped(RegExp(r',|。'), (Match match) {
|
||||
return '${match.group(0)}\n';
|
||||
}),
|
||||
defaultStyle);
|
||||
_addTextSpan(textSpans, match.group(0) ?? '', highStyle);
|
||||
startIndex = match.end;
|
||||
}
|
||||
|
||||
_addTextSpan(
|
||||
textSpans,
|
||||
text.substring(startIndex).replaceAllMapped(RegExp(r',|。'),
|
||||
(Match match) {
|
||||
return '${match.group(0)}\n';
|
||||
}),
|
||||
defaultStyle);
|
||||
}
|
||||
|
||||
void _addTextSpan(List<TextSpan> textSpans, String text, TextStyle style) {
|
||||
textSpans.add(TextSpan(text: text, style: style));
|
||||
}
|
||||
|
||||
@override
|
||||
onReady() async {
|
||||
Future<void> onReady() async {
|
||||
super.onReady();
|
||||
var isVip = await Storage.getBool(saveIsVip);
|
||||
state.isVip.value = isVip ?? false;
|
||||
}
|
||||
|
||||
18
lib/tools/regexp_tool.dart
Normal file
18
lib/tools/regexp_tool.dart
Normal file
@ -0,0 +1,18 @@
|
||||
///
|
||||
/// 正则判断工具
|
||||
///
|
||||
class RegexpTool {
|
||||
//判断手机号
|
||||
static bool isPhoneNumber(String input) {
|
||||
// 手机号正则表达式
|
||||
final RegExp phoneNumberRegExp = RegExp(r'^1[0-9]{10}$');
|
||||
return phoneNumberRegExp.hasMatch(input);
|
||||
}
|
||||
|
||||
//判断邮箱
|
||||
static bool isEmail(String input) {
|
||||
// 邮箱正则表达式
|
||||
final RegExp emailRegExp = RegExp(r'^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$');
|
||||
return emailRegExp.hasMatch(input);
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user