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:
MingNian
2026-06-11 22:11:02 +08:00
parent 66168e3261
commit d102205b18
11 changed files with 1083 additions and 248 deletions

View File

@@ -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),
),
),
),
]),
],
]),
),