Commit 862904c4 authored by akari's avatar akari

feat: 软件设置页面更新

parent 34e710d5
...@@ -118,6 +118,9 @@ class DeviceControlBloc ...@@ -118,6 +118,9 @@ class DeviceControlBloc
final BleBluetoothManager _bluetoothManager; final BleBluetoothManager _bluetoothManager;
final StorageService _storageService; final StorageService _storageService;
final McuReportFrameDecoder _mcuReportDecoder; final McuReportFrameDecoder _mcuReportDecoder;
static const Duration _careLevelPendingTimeout = Duration(seconds: 5);
int? _pendingCareLevelProtocolValue;
DateTime? _pendingCareLevelSince;
late final StreamSubscription<McuReportChangedEvent> _mcuReportSub; late final StreamSubscription<McuReportChangedEvent> _mcuReportSub;
late final StreamSubscription<BluetoothDataPacket> _bluetoothDataSub; late final StreamSubscription<BluetoothDataPacket> _bluetoothDataSub;
...@@ -212,6 +215,7 @@ class DeviceControlBloc ...@@ -212,6 +215,7 @@ class DeviceControlBloc
'co2Set=${report.co2Setting} ' 'co2Set=${report.co2Setting} '
'sn=${report.sn.isEmpty ? '<EMPTY>' : report.sn}', 'sn=${report.sn.isEmpty ? '<EMPTY>' : report.sn}',
); );
final reportCareLevel = _careLevelFromReportValue(report.levelLight);
final newData = state.data.copyWith( final newData = state.data.copyWith(
sn: report.sn.isEmpty ? state.data.sn : report.sn, sn: report.sn.isEmpty ? state.data.sn : report.sn,
cabinTemp: state.data.cabinTemp.copyWith( cabinTemp: state.data.cabinTemp.copyWith(
...@@ -242,6 +246,11 @@ class DeviceControlBloc ...@@ -242,6 +246,11 @@ class DeviceControlBloc
state.data.co2Concentration.alarmThreshold, state.data.co2Concentration.alarmThreshold,
), ),
), ),
careLevel: reportCareLevel == null
? state.data.careLevel
: state.data.careLevel.copyWith(
currentLevel: reportCareLevel,
),
); );
emit(state.copyWith(data: newData, clearError: true)); emit(state.copyWith(data: newData, clearError: true));
} }
...@@ -592,6 +601,8 @@ class DeviceControlBloc ...@@ -592,6 +601,8 @@ class DeviceControlBloc
DeviceControlCareLevelChanged event, DeviceControlCareLevelChanged event,
Emitter<DeviceControlState> emit, Emitter<DeviceControlState> emit,
) async { ) async {
final protocolValue = _careLevelProtocolValue(event.level);
_markCareLevelPending(protocolValue);
final newData = state.data.copyWith( final newData = state.data.copyWith(
careLevel: state.data.careLevel.copyWith( careLevel: state.data.careLevel.copyWith(
currentLevel: event.level, currentLevel: event.level,
...@@ -604,10 +615,11 @@ class DeviceControlBloc ...@@ -604,10 +615,11 @@ class DeviceControlBloc
)); ));
await _writeControlValueToBluetooth( await _writeControlValueToBluetooth(
identifier: 0xA8, identifier: 0xA8,
setValue: '${_careLevelProtocolValue(event.level)}', setValue: '$protocolValue',
errorPrefix: '护理等级', errorPrefix: '护理等级',
emit: emit, emit: emit,
); );
eventBus.emit(CareLevelChangedEvent(protocolValue));
} }
// ==================== 新风进化控制事件处理 ==================== // ==================== 新风进化控制事件处理 ====================
...@@ -1019,6 +1031,52 @@ class DeviceControlBloc ...@@ -1019,6 +1031,52 @@ class DeviceControlBloc
} }
} }
CareLevel? _careLevelFromProtocolValue(int value) {
switch (value) {
case 0:
return CareLevel.off;
case 1:
return CareLevel.level3;
case 2:
return CareLevel.level2;
case 3:
return CareLevel.level1;
case 4:
return CareLevel.special;
}
return null;
}
CareLevel? _careLevelFromReportValue(int value) {
final pendingValue = _pendingCareLevelProtocolValue;
final pendingSince = _pendingCareLevelSince;
if (pendingValue != null && pendingSince != null) {
final isPendingFresh =
DateTime.now().difference(pendingSince) < _careLevelPendingTimeout;
if (isPendingFresh && value != pendingValue) {
Log.warn(
'🔥🔥🔥 BLE_READ_DEBUG care_level_report_ignored '
'pending=$pendingValue report=$value',
);
return null;
}
if (value == pendingValue || !isPendingFresh) {
_clearPendingCareLevel();
}
}
return _careLevelFromProtocolValue(value);
}
void _markCareLevelPending(int protocolValue) {
_pendingCareLevelProtocolValue = protocolValue;
_pendingCareLevelSince = DateTime.now();
}
void _clearPendingCareLevel() {
_pendingCareLevelProtocolValue = null;
_pendingCareLevelSince = null;
}
List<int>? _buildControlValueCommand({ List<int>? _buildControlValueCommand({
required int identifier, required int identifier,
required String setValue, required String setValue,
......
...@@ -102,9 +102,42 @@ class PatientInfoBO extends Equatable { ...@@ -102,9 +102,42 @@ class PatientInfoBO extends Equatable {
); );
} }
PatientInfoBO copyWith({
String? name,
String? type,
String? phone,
String? breed,
String? doctor,
String? disease,
String? checkInDate,
String? careLevel,
String? avatarUrl,
}) {
return PatientInfoBO(
name: name ?? this.name,
type: type ?? this.type,
phone: phone ?? this.phone,
breed: breed ?? this.breed,
doctor: doctor ?? this.doctor,
disease: disease ?? this.disease,
checkInDate: checkInDate ?? this.checkInDate,
careLevel: careLevel ?? this.careLevel,
avatarUrl: avatarUrl ?? this.avatarUrl,
);
}
@override @override
List<Object?> get props => List<Object?> get props => [
[name, type, phone, breed, doctor, disease, checkInDate, careLevel, avatarUrl]; name,
type,
phone,
breed,
doctor,
disease,
checkInDate,
careLevel,
avatarUrl
];
} }
/// 用途:首页监护舱告警信息展示数据 /// 用途:首页监护舱告警信息展示数据
......
...@@ -49,3 +49,10 @@ class McuReportChangedEvent { ...@@ -49,3 +49,10 @@ class McuReportChangedEvent {
const McuReportChangedEvent(this.report); const McuReportChangedEvent(this.report);
} }
// 护理等级更新事件
class CareLevelChangedEvent {
final int protocolValue;
const CareLevelChangedEvent(this.protocolValue);
}
...@@ -37,6 +37,7 @@ class MonitoringIndexCubit extends Cubit<MonitoringIndexState> { ...@@ -37,6 +37,7 @@ class MonitoringIndexCubit extends Cubit<MonitoringIndexState> {
StreamSubscription<BluetoothDataPacket>? _bluetoothDataSub; StreamSubscription<BluetoothDataPacket>? _bluetoothDataSub;
StreamSubscription<BluetoothReadInfoChangedEvent>? _bluetoothReadInfoSub; StreamSubscription<BluetoothReadInfoChangedEvent>? _bluetoothReadInfoSub;
StreamSubscription<McuReportChangedEvent>? _mcuReportChangedSub; StreamSubscription<McuReportChangedEvent>? _mcuReportChangedSub;
StreamSubscription<CareLevelChangedEvent>? _careLevelChangedSub;
StreamSubscription<LakiMqttConnectionState>? _mqttStateSub; StreamSubscription<LakiMqttConnectionState>? _mqttStateSub;
StreamSubscription<LakiMqttMessage>? _mqttMessageSub; StreamSubscription<LakiMqttMessage>? _mqttMessageSub;
StreamSubscription<String>? _mqttErrorSub; StreamSubscription<String>? _mqttErrorSub;
...@@ -60,6 +61,9 @@ class MonitoringIndexCubit extends Cubit<MonitoringIndexState> { ...@@ -60,6 +61,9 @@ class MonitoringIndexCubit extends Cubit<MonitoringIndexState> {
/// 连接代际计数器 —— 每次切换模式时 +1, /// 连接代际计数器 —— 每次切换模式时 +1,
/// 防止旧连接的异步结果污染当前模式的状态。 /// 防止旧连接的异步结果污染当前模式的状态。
int _switchGen = 0; int _switchGen = 0;
static const Duration _careLevelPendingTimeout = Duration(seconds: 5);
int? _pendingCareLevelProtocolValue;
DateTime? _pendingCareLevelSince;
MonitoringIndexCubit() MonitoringIndexCubit()
: _cabinService = CabinService(), : _cabinService = CabinService(),
...@@ -74,6 +78,7 @@ class MonitoringIndexCubit extends Cubit<MonitoringIndexState> { ...@@ -74,6 +78,7 @@ class MonitoringIndexCubit extends Cubit<MonitoringIndexState> {
_listenBluetoothState(); _listenBluetoothState();
_listenBluetoothReadInfo(); _listenBluetoothReadInfo();
_listenMcuReportChanged(); _listenMcuReportChanged();
_listenCareLevelChanged();
_loadBoundBluetoothDevice(); _loadBoundBluetoothDevice();
} }
...@@ -158,9 +163,13 @@ class MonitoringIndexCubit extends Cubit<MonitoringIndexState> { ...@@ -158,9 +163,13 @@ class MonitoringIndexCubit extends Cubit<MonitoringIndexState> {
_publishMqttMonitorReport(latestReport); _publishMqttMonitorReport(latestReport);
if (isClosed) return; if (isClosed) return;
} }
final patientInfo = latestReport == null
? state.patientInfo
: _patientInfoWithCareLevel(latestReport);
emit(state.copyWith( emit(state.copyWith(
latestBluetoothRawHex: packet.rawHex, latestBluetoothRawHex: packet.rawHex,
latestMcuReport: latestReport, latestMcuReport: latestReport,
patientInfo: patientInfo,
metrics: latestReport == null metrics: latestReport == null
? state.metrics ? state.metrics
: _metricsFromBluetoothReport(latestReport), : _metricsFromBluetoothReport(latestReport),
...@@ -188,10 +197,24 @@ class MonitoringIndexCubit extends Cubit<MonitoringIndexState> { ...@@ -188,10 +197,24 @@ class MonitoringIndexCubit extends Cubit<MonitoringIndexState> {
emit(state.copyWith( emit(state.copyWith(
latestMcuReport: event.report, latestMcuReport: event.report,
metrics: metrics, metrics: metrics,
patientInfo: _patientInfoWithCareLevel(event.report),
)); ));
}); });
} }
void _listenCareLevelChanged() {
_careLevelChangedSub = eventBus.on<CareLevelChangedEvent>().listen((event) {
if (isClosed) return;
_markCareLevelPending(event.protocolValue);
final patientInfo = _patientInfoWithCareLevelValue(
event.protocolValue,
fromReport: false,
);
if (patientInfo == null) return;
emit(state.copyWith(patientInfo: patientInfo));
});
}
void _listenBluetoothReadInfo() { void _listenBluetoothReadInfo() {
_bluetoothReadInfoSub = _bluetoothReadInfoSub =
eventBus.on<BluetoothReadInfoChangedEvent>().listen((event) { eventBus.on<BluetoothReadInfoChangedEvent>().listen((event) {
...@@ -351,7 +374,10 @@ class MonitoringIndexCubit extends Cubit<MonitoringIndexState> { ...@@ -351,7 +374,10 @@ class MonitoringIndexCubit extends Cubit<MonitoringIndexState> {
cabinCameraSn: detail.cameraSn, cabinCameraSn: detail.cameraSn,
cabinWifiPwd: detail.wifiPwd, cabinWifiPwd: detail.wifiPwd,
patientInfo: detail.petInfo != null patientInfo: detail.petInfo != null
? _mapPetInfoToPatientInfo(detail.petInfo!) ? _mapPetInfoToPatientInfo(
detail.petInfo!,
careLevel: _careLevelFromCabinDetail(detail),
)
: state.patientInfo, : state.patientInfo,
)); ));
...@@ -366,7 +392,10 @@ class MonitoringIndexCubit extends Cubit<MonitoringIndexState> { ...@@ -366,7 +392,10 @@ class MonitoringIndexCubit extends Cubit<MonitoringIndexState> {
} }
/// 将 [PetInfoResponse] 映射为 [PatientInfoBO] /// 将 [PetInfoResponse] 映射为 [PatientInfoBO]
PatientInfoBO _mapPetInfoToPatientInfo(PetInfoResponse pet) { PatientInfoBO _mapPetInfoToPatientInfo(
PetInfoResponse pet, {
String? careLevel,
}) {
return PatientInfoBO( return PatientInfoBO(
name: (pet.petName ?? pet.name) ?? '', name: (pet.petName ?? pet.name) ?? '',
type: (pet.petType ?? pet.type) ?? '', type: (pet.petType ?? pet.type) ?? '',
...@@ -376,10 +405,86 @@ class MonitoringIndexCubit extends Cubit<MonitoringIndexState> { ...@@ -376,10 +405,86 @@ class MonitoringIndexCubit extends Cubit<MonitoringIndexState> {
avatarUrl: pet.avatar ?? '', avatarUrl: pet.avatar ?? '',
disease: pet.disease ?? '', disease: pet.disease ?? '',
checkInDate: '缺失字段', checkInDate: '缺失字段',
careLevel: '缺失字段', careLevel: careLevel ?? '缺失字段',
); );
} }
String? _careLevelFromCabinDetail(CabinDetailResponse detail) {
final careLevel = detail.monitoringData?.careLevel?.trim();
if (careLevel != null && careLevel.isNotEmpty) {
return careLevel;
}
return _careLevelTextFromProtocolValue(detail.monitoringData?.levelLight);
}
PatientInfoBO? _patientInfoWithCareLevel(McuReport report) {
return _patientInfoWithCareLevelValue(report.levelLight);
}
PatientInfoBO? _patientInfoWithCareLevelValue(
int value, {
bool fromReport = true,
}) {
final current = state.patientInfo;
if (current == null) return null;
final resolvedValue =
fromReport ? _resolveCareLevelReportValue(value) : value;
if (resolvedValue == null) return current;
final careLevel = _careLevelTextFromProtocolValue(resolvedValue);
if (careLevel == null || careLevel == current.careLevel) {
return current;
}
return current.copyWith(careLevel: careLevel);
}
int? _resolveCareLevelReportValue(int value) {
final pendingValue = _pendingCareLevelProtocolValue;
final pendingSince = _pendingCareLevelSince;
if (pendingValue != null && pendingSince != null) {
final isPendingFresh =
DateTime.now().difference(pendingSince) < _careLevelPendingTimeout;
if (isPendingFresh && value != pendingValue) {
Log.warn(
'🔥🔥🔥 BLE_READ_DEBUG index_care_level_report_ignored '
'pending=$pendingValue report=$value',
);
return null;
}
if (value == pendingValue || !isPendingFresh) {
_clearPendingCareLevel();
}
}
return value;
}
void _markCareLevelPending(int protocolValue) {
_pendingCareLevelProtocolValue = protocolValue;
_pendingCareLevelSince = DateTime.now();
}
void _clearPendingCareLevel() {
_pendingCareLevelProtocolValue = null;
_pendingCareLevelSince = null;
}
String? _careLevelTextFromProtocolValue(int? value) {
switch (value) {
case 0:
return '关闭';
case 1:
return '三级';
case 2:
return '二级';
case 3:
return '一级';
case 4:
return '特级';
}
return null;
}
// ==================== 模式切换 ==================== // ==================== 模式切换 ====================
/// 切换视频传输模式 /// 切换视频传输模式
...@@ -1055,6 +1160,7 @@ class MonitoringIndexCubit extends Cubit<MonitoringIndexState> { ...@@ -1055,6 +1160,7 @@ class MonitoringIndexCubit extends Cubit<MonitoringIndexState> {
_bluetoothDataSub?.cancel(); _bluetoothDataSub?.cancel();
_bluetoothReadInfoSub?.cancel(); _bluetoothReadInfoSub?.cancel();
_mcuReportChangedSub?.cancel(); _mcuReportChangedSub?.cancel();
_careLevelChangedSub?.cancel();
_webrtcService.dispose(); _webrtcService.dispose();
_p2pVideoService.dispose(); _p2pVideoService.dispose();
return _disposeMqttClient().then((_) => super.close()); return _disposeMqttClient().then((_) => super.close());
......
...@@ -18,6 +18,7 @@ class MonitoringIndexState extends Equatable { ...@@ -18,6 +18,7 @@ class MonitoringIndexState extends Equatable {
final String? error; final String? error;
final List<MonitoringMetricBO> metrics; final List<MonitoringMetricBO> metrics;
final PatientInfoBO? patientInfo; final PatientInfoBO? patientInfo;
final String? currentCareLevel;
final List<AlertInfoBO> alerts; final List<AlertInfoBO> alerts;
/// WebRTC 视频连接状态 /// WebRTC 视频连接状态
...@@ -89,6 +90,7 @@ class MonitoringIndexState extends Equatable { ...@@ -89,6 +90,7 @@ class MonitoringIndexState extends Equatable {
this.error, this.error,
this.metrics = const [], this.metrics = const [],
this.patientInfo, this.patientInfo,
this.currentCareLevel,
this.alerts = const [], this.alerts = const [],
this.cameraAlerts = const [], this.cameraAlerts = const [],
this.videoConnectionState = WebrtcConnectionState.disconnected, this.videoConnectionState = WebrtcConnectionState.disconnected,
...@@ -119,6 +121,7 @@ class MonitoringIndexState extends Equatable { ...@@ -119,6 +121,7 @@ class MonitoringIndexState extends Equatable {
String? error, String? error,
List<MonitoringMetricBO>? metrics, List<MonitoringMetricBO>? metrics,
PatientInfoBO? patientInfo, PatientInfoBO? patientInfo,
String? currentCareLevel,
List<AlertInfoBO>? alerts, List<AlertInfoBO>? alerts,
List<AlertInfoBO>? cameraAlerts, List<AlertInfoBO>? cameraAlerts,
WebrtcConnectionState? videoConnectionState, WebrtcConnectionState? videoConnectionState,
...@@ -144,6 +147,7 @@ class MonitoringIndexState extends Equatable { ...@@ -144,6 +147,7 @@ class MonitoringIndexState extends Equatable {
bool clearBoundBluetoothDevice = false, bool clearBoundBluetoothDevice = false,
bool clearLatestMcuReport = false, bool clearLatestMcuReport = false,
bool clearPatientInfo = false, bool clearPatientInfo = false,
bool clearCurrentCareLevel = false,
bool clearMqttDeviceSn = false, bool clearMqttDeviceSn = false,
bool clearSelectedAlert = false, bool clearSelectedAlert = false,
}) { }) {
...@@ -153,6 +157,9 @@ class MonitoringIndexState extends Equatable { ...@@ -153,6 +157,9 @@ class MonitoringIndexState extends Equatable {
error: error ?? this.error, error: error ?? this.error,
metrics: metrics ?? this.metrics, metrics: metrics ?? this.metrics,
patientInfo: clearPatientInfo ? null : patientInfo ?? this.patientInfo, patientInfo: clearPatientInfo ? null : patientInfo ?? this.patientInfo,
currentCareLevel: clearCurrentCareLevel
? null
: currentCareLevel ?? this.currentCareLevel,
alerts: alerts ?? this.alerts, alerts: alerts ?? this.alerts,
cameraAlerts: cameraAlerts ?? this.cameraAlerts, cameraAlerts: cameraAlerts ?? this.cameraAlerts,
videoConnectionState: videoConnectionState ?? this.videoConnectionState, videoConnectionState: videoConnectionState ?? this.videoConnectionState,
...@@ -196,6 +203,7 @@ class MonitoringIndexState extends Equatable { ...@@ -196,6 +203,7 @@ class MonitoringIndexState extends Equatable {
error, error,
metrics, metrics,
patientInfo, patientInfo,
currentCareLevel,
alerts, alerts,
cameraAlerts, cameraAlerts,
videoConnectionState, videoConnectionState,
......
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:laki_icu_app/models/bo/monitoring_bo.dart'; import 'package:laki_icu_app/models/bo/monitoring_bo.dart';
class MonitoringPetInfoCard extends StatelessWidget { class MonitoringPetInfoCard extends StatelessWidget {
final PatientInfoBO? patientInfo; final PatientInfoBO? patientInfo;
final String? currentCareLevel;
final VoidCallback? onExit; final VoidCallback? onExit;
final VoidCallback? onBindPet; final VoidCallback? onBindPet;
const MonitoringPetInfoCard({ const MonitoringPetInfoCard({
super.key, super.key,
required this.patientInfo, required this.patientInfo,
this.currentCareLevel,
this.onExit, this.onExit,
this.onBindPet, this.onBindPet,
}); });
...@@ -19,15 +20,21 @@ class MonitoringPetInfoCard extends StatelessWidget { ...@@ -19,15 +20,21 @@ class MonitoringPetInfoCard extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Container( return Container(
decoration: BoxDecoration( decoration: BoxDecoration(
image: DecorationImage(image: AssetImage('lib/assets/monitoring/box_bg_460x905.png'),fit: BoxFit.fill), image: DecorationImage(
image: AssetImage('lib/assets/monitoring/box_bg_460x905.png'),
fit: BoxFit.fill),
// border: Border.all(color: Colors.red,width: 1.w) // border: Border.all(color: Colors.red,width: 1.w)
), ),
padding: EdgeInsets.only(left: 40.w,right: 40.w, top: 32.h), padding: EdgeInsets.only(left: 40.w, right: 40.w, top: 32.h),
child: patientInfo == null ? _buildEmpty() : _buildContent(patientInfo!), child: patientInfo == null
? _buildEmpty(currentCareLevel)
: _buildContent(patientInfo!),
); );
} }
Widget _buildEmpty() { Widget _buildEmpty(String? careLevel) {
final displayCareLevel =
careLevel == null || careLevel.isEmpty ? '暂无' : careLevel;
return Column( return Column(
children: [ children: [
SizedBox(height: 10.h), SizedBox(height: 10.h),
...@@ -100,7 +107,7 @@ class MonitoringPetInfoCard extends StatelessWidget { ...@@ -100,7 +107,7 @@ class MonitoringPetInfoCard extends StatelessWidget {
), ),
SizedBox(height: 41.h), SizedBox(height: 41.h),
Text( Text(
'暂无', displayCareLevel,
style: TextStyle( style: TextStyle(
color: Colors.white, color: Colors.white,
fontSize: 64.sp, fontSize: 64.sp,
...@@ -109,74 +116,7 @@ class MonitoringPetInfoCard extends StatelessWidget { ...@@ -109,74 +116,7 @@ class MonitoringPetInfoCard extends StatelessWidget {
), ),
), ),
SizedBox(height: 55.h), SizedBox(height: 55.h),
// 进度条 _buildLevelBar(displayCareLevel),
Container(
padding: EdgeInsets.symmetric(horizontal: 4.w),
decoration: BoxDecoration(
color: const Color(0xFF0A1A2E),
borderRadius: BorderRadius.circular(6.r),
),
child: Row(
children: [
Expanded(
child: Container(
margin: EdgeInsets.symmetric(horizontal: 2.w),
height: 10.h,
decoration: BoxDecoration(
color: const Color(0xFFFFFFFF),
borderRadius: BorderRadius.circular(2.r),
boxShadow: const [
BoxShadow(
color: Color(0x99FFFFFF),
blurRadius: 6,
),
],
),
),
),
Expanded(
child: Container(
margin: EdgeInsets.symmetric(horizontal: 2.w),
height: 10.h,
decoration: BoxDecoration(
color: const Color(0xFF25E5B0).withOpacity(0.3),
borderRadius: BorderRadius.circular(2.r),
),
),
),
Expanded(
child: Container(
margin: EdgeInsets.symmetric(horizontal: 2.w),
height: 10.h,
decoration: BoxDecoration(
color: const Color(0xFFFFB347).withOpacity(0.3),
borderRadius: BorderRadius.circular(2.r),
),
),
),
Expanded(
child: Container(
margin: EdgeInsets.symmetric(horizontal: 2.w),
height: 10.h,
decoration: BoxDecoration(
color: const Color(0xFFFF7A4D).withOpacity(0.3),
borderRadius: BorderRadius.circular(2.r),
),
),
),
Expanded(
child: Container(
margin: EdgeInsets.symmetric(horizontal: 2.w),
height: 10.h,
decoration: BoxDecoration(
color: const Color(0xFFFF4E4E).withOpacity(0.3),
borderRadius: BorderRadius.circular(2.r),
),
),
),
],
),
),
], ],
), ),
SizedBox(height: 26.h), SizedBox(height: 26.h),
...@@ -188,7 +128,8 @@ class MonitoringPetInfoCard extends StatelessWidget { ...@@ -188,7 +128,8 @@ class MonitoringPetInfoCard extends StatelessWidget {
height: 140.h, height: 140.h,
decoration: const BoxDecoration( decoration: const BoxDecoration(
image: DecorationImage( image: DecorationImage(
image: AssetImage('lib/assets/monitoring/title_bg_spacewalk.png'), image:
AssetImage('lib/assets/monitoring/title_bg_spacewalk.png'),
fit: BoxFit.fill, fit: BoxFit.fill,
), ),
), ),
...@@ -196,7 +137,6 @@ class MonitoringPetInfoCard extends StatelessWidget { ...@@ -196,7 +137,6 @@ class MonitoringPetInfoCard extends StatelessWidget {
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
SizedBox(width: 24.w), SizedBox(width: 24.w),
Text( Text(
'绑定宠物', '绑定宠物',
...@@ -208,7 +148,6 @@ class MonitoringPetInfoCard extends StatelessWidget { ...@@ -208,7 +148,6 @@ class MonitoringPetInfoCard extends StatelessWidget {
), ),
), ),
SizedBox(width: 24.w), SizedBox(width: 24.w),
], ],
), ),
), ),
...@@ -233,7 +172,6 @@ class MonitoringPetInfoCard extends StatelessWidget { ...@@ -233,7 +172,6 @@ class MonitoringPetInfoCard extends StatelessWidget {
SizedBox(height: 30.h), SizedBox(height: 30.h),
_buildCareLevelBlock(info), _buildCareLevelBlock(info),
SizedBox(height: 25.h), SizedBox(height: 25.h),
_buildExitButton(), _buildExitButton(),
], ],
); );
...@@ -245,7 +183,7 @@ class MonitoringPetInfoCard extends StatelessWidget { ...@@ -245,7 +183,7 @@ class MonitoringPetInfoCard extends StatelessWidget {
children: [ children: [
Container( Container(
width: 150.w, width: 150.w,
height: 160.w, height: 160.w,
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20.r), borderRadius: BorderRadius.circular(20.r),
color: const Color(0xFF1F4E79), color: const Color(0xFF1F4E79),
...@@ -427,12 +365,12 @@ class MonitoringPetInfoCard extends StatelessWidget { ...@@ -427,12 +365,12 @@ class MonitoringPetInfoCard extends StatelessWidget {
], ],
), ),
SizedBox(height: 49.h), SizedBox(height: 49.h),
_buildLevelBar(), _buildLevelBar(info.careLevel),
], ],
); );
} }
Widget _buildLevelBar() { Widget _buildLevelBar(String careLevel) {
const segments = [ const segments = [
Color(0xFFFFFFFF), Color(0xFFFFFFFF),
Color(0xFF25E5B0), Color(0xFF25E5B0),
...@@ -447,6 +385,7 @@ class MonitoringPetInfoCard extends StatelessWidget { ...@@ -447,6 +385,7 @@ class MonitoringPetInfoCard extends StatelessWidget {
Color(0x99FF7A4D), Color(0x99FF7A4D),
Color(0x99FF4E4E), Color(0x99FF4E4E),
]; ];
final activeIndex = _careLevelIndex(careLevel);
return Container( return Container(
padding: EdgeInsets.symmetric(horizontal: 4.w), padding: EdgeInsets.symmetric(horizontal: 4.w),
decoration: BoxDecoration( decoration: BoxDecoration(
...@@ -462,14 +401,18 @@ class MonitoringPetInfoCard extends StatelessWidget { ...@@ -462,14 +401,18 @@ class MonitoringPetInfoCard extends StatelessWidget {
margin: EdgeInsets.symmetric(horizontal: 2.w), margin: EdgeInsets.symmetric(horizontal: 2.w),
height: 10.h, height: 10.h,
decoration: BoxDecoration( decoration: BoxDecoration(
color: entry.value, color: entry.key <= activeIndex
? entry.value
: const Color(0xFF6A7481),
borderRadius: BorderRadius.circular(2.r), borderRadius: BorderRadius.circular(2.r),
boxShadow: [ boxShadow: entry.key <= activeIndex
BoxShadow( ? [
color: shadowColors[entry.key], BoxShadow(
blurRadius: 6, color: shadowColors[entry.key],
), blurRadius: 6,
], ),
]
: null,
), ),
), ),
)) ))
...@@ -478,6 +421,22 @@ class MonitoringPetInfoCard extends StatelessWidget { ...@@ -478,6 +421,22 @@ class MonitoringPetInfoCard extends StatelessWidget {
); );
} }
int _careLevelIndex(String careLevel) {
switch (careLevel) {
case '关闭':
return 0;
case '三级':
return 1;
case '二级':
return 2;
case '一级':
return 3;
case '特级':
return 4;
}
return 0;
}
Widget _buildExitButton() { Widget _buildExitButton() {
return GestureDetector( return GestureDetector(
onTap: onExit, onTap: onExit,
......
...@@ -15,14 +15,14 @@ class SettingsAboutPanel extends StatelessWidget { ...@@ -15,14 +15,14 @@ class SettingsAboutPanel extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return SettingsPanelFrame( return SettingsPanelFrame(
backgroundAsset: settingsAssetPanelMain, backgroundAsset: settingsAssetPanelMain,
padding: EdgeInsets.fromLTRB(42.w, 54.h, 42.w, 48.h), padding: EdgeInsets.fromLTRB(100.w, 80.h, 100.w, 100.h),
child: BlocBuilder<SettingsIndexCubit, SettingsIndexState>( child: BlocBuilder<SettingsIndexCubit, SettingsIndexState>(
builder: (context, state) { builder: (context, state) {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.stretch, crossAxisAlignment: CrossAxisAlignment.stretch,
children: [ children: [
const _LogoPlaceholder(), const _LogoPlaceholder(),
SizedBox(height: 62.h), SizedBox(height: 20.h),
Row( Row(
crossAxisAlignment: CrossAxisAlignment.end, crossAxisAlignment: CrossAxisAlignment.end,
children: [ children: [
...@@ -71,8 +71,8 @@ class _LogoPlaceholder extends StatelessWidget { ...@@ -71,8 +71,8 @@ class _LogoPlaceholder extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Center( return Center(
child: Container( child: Container(
width: 855.w, width: 863.w,
height: 184.h, height: 185.h,
color: const Color(0xFFD7D7D7), color: const Color(0xFFD7D7D7),
alignment: Alignment.center, alignment: Alignment.center,
child: Text( child: Text(
......
...@@ -3,6 +3,10 @@ import 'package:flutter_screenutil/flutter_screenutil.dart'; ...@@ -3,6 +3,10 @@ import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'settings_panel_frame.dart'; import 'settings_panel_frame.dart';
const String _settingsMenuButtonAsset = 'lib/assets/settings/btn_setmenu.png';
const String _settingsMenuButtonActiveAsset =
'lib/assets/settings/btn_setmenu_active.png';
class SettingsSideMenu extends StatelessWidget { class SettingsSideMenu extends StatelessWidget {
const SettingsSideMenu({ const SettingsSideMenu({
super.key, super.key,
...@@ -25,7 +29,7 @@ class SettingsSideMenu extends StatelessWidget { ...@@ -25,7 +29,7 @@ class SettingsSideMenu extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return SettingsPanelFrame( return SettingsPanelFrame(
backgroundAsset: settingsAssetPanelLeft, backgroundAsset: settingsAssetPanelLeft,
padding: EdgeInsets.fromLTRB(42.w, 48.h, 42.w, 48.h), padding: EdgeInsets.fromLTRB(36.w, 48.h, 36.w, 48.h),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
...@@ -37,7 +41,7 @@ class SettingsSideMenu extends StatelessWidget { ...@@ -37,7 +41,7 @@ class SettingsSideMenu extends StatelessWidget {
fontWeight: FontWeight.w700, fontWeight: FontWeight.w700,
), ),
), ),
SizedBox(height: 34.h), SizedBox(height: 30.h),
Divider(color: const Color(0xFF4CA7D2).withValues(alpha: 0.42)), Divider(color: const Color(0xFF4CA7D2).withValues(alpha: 0.42)),
SizedBox(height: 30.h), SizedBox(height: 30.h),
for (final menu in menus) ...[ for (final menu in menus) ...[
...@@ -46,7 +50,7 @@ class SettingsSideMenu extends StatelessWidget { ...@@ -46,7 +50,7 @@ class SettingsSideMenu extends StatelessWidget {
active: menu == selectedMenu, active: menu == selectedMenu,
onTap: () => onSelected(menu), onTap: () => onSelected(menu),
), ),
SizedBox(height: 22.h), // SizedBox(height: 6.h),
], ],
], ],
), ),
...@@ -71,9 +75,10 @@ class _SettingsMenuButton extends StatelessWidget { ...@@ -71,9 +75,10 @@ class _SettingsMenuButton extends StatelessWidget {
behavior: HitTestBehavior.opaque, behavior: HitTestBehavior.opaque,
onTap: onTap, onTap: onTap,
child: Container( child: Container(
height: 64.h, width: 388,
padding: EdgeInsets.symmetric(horizontal: 28.w), height: 62,
decoration: settingsButtonDecoration(active: active), // padding: EdgeInsets.symmetric(horizontal: 10.w),
decoration: _settingsMenuButtonDecoration(active: active),
child: Row( child: Row(
children: [ children: [
Expanded( Expanded(
...@@ -82,23 +87,35 @@ class _SettingsMenuButton extends StatelessWidget { ...@@ -82,23 +87,35 @@ class _SettingsMenuButton extends StatelessWidget {
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle( style: TextStyle(
color: active ? const Color(0xFFC9F8FF) : Colors.white, color: active ? const Color(0xFFC9F8FF) : Colors.white,
fontSize: 30.sp, fontSize: 20,
// height: 0.9,
fontWeight: FontWeight.w700, fontWeight: FontWeight.w700,
), ),
), ),
), ),
Text(
'》》',
style: TextStyle(
color: const Color(0xFF67C9F5)
.withValues(alpha: active ? 0.72 : 0.36),
fontSize: 28.sp,
fontWeight: FontWeight.w700,
),
),
], ],
), ),
), ),
); );
} }
} }
BoxDecoration _settingsMenuButtonDecoration({required bool active}) {
return BoxDecoration(
image: DecorationImage(
image: AssetImage(
active ? _settingsMenuButtonActiveAsset : _settingsMenuButtonAsset,
),
fit: BoxFit.fill,
),
boxShadow: active
? [
BoxShadow(
color: const Color(0xFF45CFFF).withValues(alpha: 0.10),
blurRadius: 18.r,
spreadRadius: 10.r,
),
]
: null,
);
}
...@@ -101,6 +101,7 @@ flutter: ...@@ -101,6 +101,7 @@ flutter:
- lib/assets/tab/ - lib/assets/tab/
- lib/assets/icon/ - lib/assets/icon/
- lib/assets/monitoring/ - lib/assets/monitoring/
- lib/assets/settings/
# - images/a_dot_ham.jpeg # - images/a_dot_ham.jpeg
# An image asset can refer to one or more resolution-specific "variants", see # An image asset can refer to one or more resolution-specific "variants", see
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment