ops-console v1.0.2 (versionCode 8) 源码入库
This commit is contained in:
106
lib/providers/dashboard_provider.dart
Normal file
106
lib/providers/dashboard_provider.dart
Normal file
@@ -0,0 +1,106 @@
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
import '../models/device.dart';
|
||||
import '../services/device_service.dart';
|
||||
import '../services/org_service.dart';
|
||||
import '../utils/session_org_scope.dart';
|
||||
import 'devices_provider.dart';
|
||||
|
||||
/// 仪表盘统计数据。
|
||||
class DashboardStats {
|
||||
const DashboardStats({
|
||||
this.deviceTotal = 0,
|
||||
this.storeTotal = 0,
|
||||
this.onlineCount = 0,
|
||||
this.offlineCount = 0,
|
||||
});
|
||||
|
||||
final int deviceTotal;
|
||||
final int storeTotal;
|
||||
final int onlineCount;
|
||||
final int offlineCount;
|
||||
|
||||
DashboardStats copyWith({
|
||||
int? deviceTotal,
|
||||
int? storeTotal,
|
||||
int? onlineCount,
|
||||
int? offlineCount,
|
||||
}) {
|
||||
return DashboardStats(
|
||||
deviceTotal: deviceTotal ?? this.deviceTotal,
|
||||
storeTotal: storeTotal ?? this.storeTotal,
|
||||
onlineCount: onlineCount ?? this.onlineCount,
|
||||
offlineCount: offlineCount ?? this.offlineCount,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 仪表盘统计状态。
|
||||
class DashboardStatsNotifier extends StateNotifier<DashboardStats> {
|
||||
DashboardStatsNotifier(this._deviceService, this._orgService)
|
||||
: super(const DashboardStats());
|
||||
|
||||
final DeviceService _deviceService;
|
||||
final OrgService _orgService;
|
||||
|
||||
Future<void> load() async {
|
||||
try {
|
||||
int deviceTotal = 0;
|
||||
int onlineCount = 0;
|
||||
int offlineCount = 0;
|
||||
|
||||
if (SessionOrgScope.instance.enabled) {
|
||||
// 受限账号:仅统计其组织子树内的设备。
|
||||
// 设备接口可能忽略 orgId,故改为「拉取列表 + 按 storeId 在范围内收敛」,
|
||||
// 杜绝跨组织设备越权统计(只会少计、不会多计或泄露其他组织数据)。
|
||||
final ids = await _orgService.scopedOrgIdSet();
|
||||
if (ids.isNotEmpty) {
|
||||
final devices = await _deviceService.fetchDevices(limit: 1000);
|
||||
final scoped =
|
||||
devices.where((d) => ids.contains(d.storeId)).toList();
|
||||
deviceTotal = scoped.length;
|
||||
onlineCount =
|
||||
scoped.where((d) => d.status == DeviceStatus.online).length;
|
||||
offlineCount =
|
||||
scoped.where((d) => d.status == DeviceStatus.offline).length;
|
||||
}
|
||||
} else {
|
||||
deviceTotal = await _deviceService.fetchDeviceTotalCount();
|
||||
// 若后端未返回 totalCount,则拉取一页列表用其长度兜底。
|
||||
if (deviceTotal <= 0) {
|
||||
final devices = await _deviceService.fetchDevices(limit: 100);
|
||||
deviceTotal = devices.length;
|
||||
}
|
||||
// 在线/离线:分别按 status 拉 totalCount(O(1),无需遍历全量设备)。
|
||||
final results = await Future.wait<int>([
|
||||
_deviceService.fetchDeviceCountByStatus(status: 'online'),
|
||||
_deviceService.fetchDeviceCountByStatus(status: 'offline'),
|
||||
]);
|
||||
onlineCount = results[0];
|
||||
offlineCount = results[1];
|
||||
}
|
||||
|
||||
// 门店总数:优先组织树,失败回退门店接口(fetchStoreCount 内部已含回退链)。
|
||||
final storeTotal = await _orgService.fetchStoreCount();
|
||||
|
||||
state = state.copyWith(
|
||||
deviceTotal: deviceTotal,
|
||||
storeTotal: storeTotal,
|
||||
onlineCount: onlineCount,
|
||||
offlineCount: offlineCount,
|
||||
);
|
||||
} catch (_) {
|
||||
// 统计失败不阻断页面,保持旧值或 0。
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final orgServiceProvider = Provider<OrgService>((ref) => OrgService());
|
||||
|
||||
final dashboardStatsProvider =
|
||||
StateNotifierProvider<DashboardStatsNotifier, DashboardStats>(
|
||||
(ref) => DashboardStatsNotifier(
|
||||
ref.watch(deviceServiceProvider),
|
||||
ref.watch(orgServiceProvider),
|
||||
),
|
||||
);
|
||||
Reference in New Issue
Block a user