feat: 新增设备绑定、扫码与联系人管理功能
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:ttstd_family_care/core/network/error_message.dart';
|
||||
import 'package:ttstd_family_care/features/device/data/device_providers.dart';
|
||||
|
||||
/// 设备管理(绑定 / 解绑)操作状态。
|
||||
///
|
||||
/// [submitting] 表示正在请求中,用于禁用按钮并展示 loading;
|
||||
/// [alert] 为一次性提示文案,UI 展示后必须调用 [DeviceManageController.consumeAlert] 消费;
|
||||
/// [lastSuccess] 标记最近一次操作是否成功,供 UI 决定是否关闭页面。
|
||||
class DeviceManageState {
|
||||
const DeviceManageState({
|
||||
this.submitting = false,
|
||||
this.alert,
|
||||
this.lastSuccess = false,
|
||||
});
|
||||
|
||||
final bool submitting;
|
||||
final String? alert;
|
||||
final bool lastSuccess;
|
||||
|
||||
DeviceManageState copyWith({
|
||||
bool? submitting,
|
||||
String? alert,
|
||||
bool? lastSuccess,
|
||||
}) =>
|
||||
DeviceManageState(
|
||||
submitting: submitting ?? this.submitting,
|
||||
alert: alert,
|
||||
lastSuccess: lastSuccess ?? this.lastSuccess,
|
||||
);
|
||||
}
|
||||
|
||||
/// 设备绑定 / 解绑控制器。
|
||||
///
|
||||
/// 页面级控制器,**不使用** keepAlive,随页面销毁自动释放(见 AGENTS.md §4)。
|
||||
/// 操作成功后主动 `ref.invalidate(myDevicesProvider)` 刷新绑定列表。
|
||||
class DeviceManageController extends Notifier<DeviceManageState> {
|
||||
@override
|
||||
DeviceManageState build() => const DeviceManageState();
|
||||
|
||||
/// 绑定设备。[sn] 为设备序列号,[remark] 为可选备注名。
|
||||
///
|
||||
/// SN 为空等输入校验由 UI 层负责(便于使用本地化文案),此处只做兜底裁剪。
|
||||
/// 返回是否绑定成功。
|
||||
Future<bool> bind(String sn, {String? remark}) =>
|
||||
_run(() => ref.read(deviceRepositoryProvider).bindDevice(
|
||||
sn.trim(),
|
||||
remark: remark?.trim(),
|
||||
));
|
||||
|
||||
/// 解绑设备。返回是否解绑成功。
|
||||
Future<bool> unbind(String sn) =>
|
||||
_run(() => ref.read(deviceRepositoryProvider).unbindDevice(sn));
|
||||
|
||||
/// 消费一次性提示,避免重复弹窗。
|
||||
void consumeAlert() {
|
||||
if (state.alert != null) {
|
||||
state = state.copyWith(alert: null, lastSuccess: state.lastSuccess);
|
||||
}
|
||||
}
|
||||
|
||||
/// 统一执行绑定/解绑请求:处理 submitting 开关、错误文案与列表刷新。
|
||||
Future<bool> _run(Future<String?> Function() action) async {
|
||||
if (state.submitting) return false;
|
||||
state = state.copyWith(submitting: true, alert: null, lastSuccess: false);
|
||||
try {
|
||||
final error = await action();
|
||||
if (error != null) {
|
||||
state = state.copyWith(
|
||||
submitting: false,
|
||||
alert: error,
|
||||
lastSuccess: false,
|
||||
);
|
||||
return false;
|
||||
}
|
||||
// 绑定关系变化,刷新已绑定设备列表。
|
||||
ref.invalidate(myDevicesProvider);
|
||||
state = state.copyWith(submitting: false, lastSuccess: true);
|
||||
return true;
|
||||
} catch (e) {
|
||||
// 统一文案映射,禁止直接 toString()(见 AGENTS.md §12)。
|
||||
state = state.copyWith(
|
||||
submitting: false,
|
||||
alert: userMessageOf(e),
|
||||
lastSuccess: false,
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 设备管理控制器 Provider(页面级,不 keepAlive)。
|
||||
final deviceManageControllerProvider =
|
||||
NotifierProvider<DeviceManageController, DeviceManageState>(
|
||||
DeviceManageController.new,
|
||||
);
|
||||
Reference in New Issue
Block a user