feat: 蓝牙血压计BLE数据同步 + 设备管理页重构 + 健康记录滑动删除 + 医生端合并设计文档
- BLE: 修复Omron设备Indication模式连接(先订阅后配CCCD + forceIndications) + 直连重连
- BLE: 设备断连实时检测(connectionState流→Provider→UI)
- 修复: 血压数据上报后端枚举不匹配(Device→DeviceSync)导致500
- 新增: DELETE /api/health-records/{id} 后端接口
- 设备管理页: 白色主题重设计 + 直连重连 + 实时状态 + Toast通知
- 设备扫描页: 白色主题 + 扫描动画居中 + 已连接等待页面
- 健康记录: 左滑删除(Dismissible) + 同时清理_allRecords和_filtered
- 导航: 修复自定义路由栈下Navigator.pop黑屏bug
- 文档: 医生端合并App完整设计文档(已确认版)
This commit is contained in:
@@ -864,9 +864,9 @@ class StaticTextPage extends ConsumerWidget {
|
||||
}
|
||||
}
|
||||
|
||||
/// 血压计设备管理(已绑定/未绑定)
|
||||
class DeviceManagementPage extends ConsumerWidget {
|
||||
const DeviceManagementPage({super.key});
|
||||
/// 旧版设备管理页,已移至 device/device_management_page.dart
|
||||
class _DeviceManagementPageLegacy extends ConsumerWidget {
|
||||
const _DeviceManagementPageLegacy({super.key});
|
||||
|
||||
@override Widget build(BuildContext context, WidgetRef ref) {
|
||||
final device = ref.watch(omronDeviceProvider);
|
||||
@@ -930,12 +930,28 @@ class DeviceManagementPage extends ConsumerWidget {
|
||||
Container(
|
||||
width: 72, height: 72,
|
||||
decoration: BoxDecoration(
|
||||
gradient: AppColors.primaryGradient,
|
||||
gradient: device.isConnected ? AppColors.primaryGradient : const LinearGradient(colors: [Color(0xFF9CA3AF), Color(0xFF6B7280)]),
|
||||
borderRadius: BorderRadius.circular(AppTheme.rMd),
|
||||
),
|
||||
child: const Icon(Icons.bluetooth_connected, size: 36, color: Colors.white),
|
||||
child: Icon(
|
||||
device.isConnected ? Icons.bluetooth_connected : Icons.bluetooth_disabled,
|
||||
size: 36, color: Colors.white,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
const SizedBox(height: 8),
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4),
|
||||
decoration: BoxDecoration(
|
||||
color: device.isConnected ? const Color(0xFFD1FAE5) : const Color(0xFFFEE2E2),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: Text(
|
||||
device.isConnected ? '已连接' : '未连接',
|
||||
style: TextStyle(fontSize: 13, fontWeight: FontWeight.w600,
|
||||
color: device.isConnected ? const Color(0xFF059669) : const Color(0xFFDC2626)),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
Text(device.name ?? '血压计', style: const TextStyle(fontSize: 22, fontWeight: FontWeight.w700, color: AppColors.textPrimary)),
|
||||
const SizedBox(height: 6),
|
||||
Text('MAC: ${device.mac ?? '—'}', style: const TextStyle(fontSize: 14, color: AppColors.textHint)),
|
||||
@@ -944,12 +960,45 @@ class DeviceManagementPage extends ConsumerWidget {
|
||||
Text('上次同步: ${device.lastSync}', style: const TextStyle(fontSize: 13, color: AppColors.textHint)),
|
||||
],
|
||||
const SizedBox(height: 24),
|
||||
Row(children: [
|
||||
Expanded(
|
||||
if (device.isConnected) ...[
|
||||
// 已连接:显示断开和解绑
|
||||
Row(children: [
|
||||
Expanded(
|
||||
child: OutlinedButton.icon(
|
||||
onPressed: () => _unbind(context, ref),
|
||||
icon: const Icon(Icons.delete_outline, size: 18, color: AppColors.error),
|
||||
label: const Text('解绑', style: TextStyle(color: AppColors.error)),
|
||||
style: OutlinedButton.styleFrom(
|
||||
side: const BorderSide(color: AppColors.error),
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(AppTheme.rMd)),
|
||||
padding: const EdgeInsets.symmetric(vertical: 14),
|
||||
),
|
||||
),
|
||||
),
|
||||
]),
|
||||
] else ...[
|
||||
// 未连接:显示重新连接和解绑
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
height: 52,
|
||||
child: ElevatedButton.icon(
|
||||
onPressed: () => pushRoute(ref, 'deviceScan'),
|
||||
icon: const Icon(Icons.bluetooth_searching, size: 20),
|
||||
label: const Text('重新连接设备', style: TextStyle(fontSize: 17, fontWeight: FontWeight.w600)),
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: AppColors.primary,
|
||||
foregroundColor: Colors.white,
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(AppTheme.rMd)),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
child: OutlinedButton.icon(
|
||||
onPressed: () => _unbind(context, ref),
|
||||
icon: const Icon(Icons.delete_outline, size: 18, color: AppColors.error),
|
||||
label: const Text('解绑', style: TextStyle(color: AppColors.error)),
|
||||
label: const Text('解绑设备', style: TextStyle(color: AppColors.error)),
|
||||
style: OutlinedButton.styleFrom(
|
||||
side: const BorderSide(color: AppColors.error),
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(AppTheme.rMd)),
|
||||
@@ -957,21 +1006,7 @@ class DeviceManagementPage extends ConsumerWidget {
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: ElevatedButton.icon(
|
||||
onPressed: () => pushRoute(ref, 'deviceScan'),
|
||||
icon: const Icon(Icons.swap_horiz, size: 18),
|
||||
label: const Text('更换设备'),
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: AppColors.primary,
|
||||
foregroundColor: Colors.white,
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(AppTheme.rMd)),
|
||||
padding: const EdgeInsets.symmetric(vertical: 14),
|
||||
),
|
||||
),
|
||||
),
|
||||
]),
|
||||
],
|
||||
]),
|
||||
),
|
||||
|
||||
|
||||
Reference in New Issue
Block a user