机器列表和远程喊话等ui
This commit is contained in:
@@ -1,3 +1,7 @@
|
||||
import 'package:maibu_satabot_v2/core/localization/app_localizations.dart';
|
||||
|
||||
import '../../domain/entities/device_model_info.dart';
|
||||
|
||||
/// 机器人数据模型
|
||||
class RobotDataModel {
|
||||
final String name;
|
||||
@@ -11,6 +15,28 @@ class RobotDataModel {
|
||||
final String task;
|
||||
final bool hasHost;
|
||||
|
||||
/// 产品型号(getSiteList 返回,如「割草机产品MC700」)
|
||||
final String? productName;
|
||||
|
||||
/// 机型编码(getSiteList 返回,如 MC700PRO)—— 列表机型展示以此为准
|
||||
final String? productModel;
|
||||
|
||||
/// 设备类型(getSiteList 返回的 deviceType)
|
||||
///
|
||||
/// 展示位置在版本号(PRO / PLUS / STD)之前:`MC700 · PRO 旗舰版`。
|
||||
final String? deviceType;
|
||||
|
||||
/// 归属信息:当前挂在哪个组织 / 场站 / 负责人下。
|
||||
///
|
||||
/// 后端 getSiteList 不一定回传这些字段,因此全部可空:
|
||||
/// 拿不到时页面显示「未知」,不编造。
|
||||
final int? orgId;
|
||||
final String? orgName;
|
||||
final int? siteId;
|
||||
final String? siteName;
|
||||
final int? userId;
|
||||
final String? userName;
|
||||
|
||||
const RobotDataModel({
|
||||
required this.name,
|
||||
required this.id,
|
||||
@@ -22,6 +48,15 @@ class RobotDataModel {
|
||||
required this.battery,
|
||||
required this.task,
|
||||
this.hasHost = false,
|
||||
this.productName,
|
||||
this.productModel,
|
||||
this.deviceType,
|
||||
this.orgId,
|
||||
this.orgName,
|
||||
this.siteId,
|
||||
this.siteName,
|
||||
this.userId,
|
||||
this.userName,
|
||||
});
|
||||
|
||||
/// 从 JSON 创建数据模型
|
||||
@@ -49,9 +84,60 @@ class RobotDataModel {
|
||||
battery: batteryValue,
|
||||
task: json['task'] ?? json['currentTask'] ?? '待机中',
|
||||
hasHost: json['hasHost'] as bool? ?? false,
|
||||
productName: _pickStr(json['productName']),
|
||||
productModel: _pickStr(json['productModel']),
|
||||
deviceType: _pickStr(json['deviceType'] ?? json['device_type']),
|
||||
orgId: _pickInt(json, const ['orgId', 'org_id', 'organizationId']),
|
||||
orgName: _pickStr(
|
||||
json['orgName'] ?? json['org_name'] ?? json['organizationName'],
|
||||
),
|
||||
siteId: _pickInt(json, const ['siteId', 'site_id']),
|
||||
siteName: _pickStr(json['siteName'] ?? json['site_name']),
|
||||
userId: _pickInt(json, const [
|
||||
'userId',
|
||||
'user_id',
|
||||
'ownerId',
|
||||
'owner_id',
|
||||
'managerId',
|
||||
]),
|
||||
userName: _pickStr(
|
||||
json['userName'] ??
|
||||
json['user_name'] ??
|
||||
json['ownerName'] ??
|
||||
json['nickName'] ??
|
||||
json['managerName'],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// 多候选 key 里取第一个能转成整数的值
|
||||
static int? _pickInt(Map<String, dynamic> json, List<String> keys) {
|
||||
for (final key in keys) {
|
||||
final value = json[key];
|
||||
if (value is int) return value;
|
||||
if (value is num) return value.toInt();
|
||||
if (value is String) {
|
||||
final parsed = int.tryParse(value.trim());
|
||||
if (parsed != null) return parsed;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// 机型信息(系列 + 版本),由 productModel 解析
|
||||
DeviceModelInfo get modelInfo => DeviceModelInfo.parse(productModel);
|
||||
|
||||
/// 列表卡「型号 · 版本」文案:`MC700 · PRO 旗舰版`
|
||||
/// productModel 为 null / 空串时统一显示未知;
|
||||
/// deviceType 排在版本号之前。
|
||||
String modelLabelOf(AppLocalizations l10n) =>
|
||||
modelInfo.labelOf(l10n, deviceType: deviceType);
|
||||
|
||||
static String? _pickStr(dynamic value) {
|
||||
final s = value?.toString().trim() ?? '';
|
||||
return s.isEmpty ? null : s;
|
||||
}
|
||||
|
||||
/// 转换为 JSON
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
@@ -64,6 +150,15 @@ class RobotDataModel {
|
||||
'statusCode': statusCode,
|
||||
'battery': battery,
|
||||
'task': task,
|
||||
'productName': productName,
|
||||
'productModel': productModel,
|
||||
'deviceType': deviceType,
|
||||
'orgId': orgId,
|
||||
'orgName': orgName,
|
||||
'siteId': siteId,
|
||||
'siteName': siteName,
|
||||
'userId': userId,
|
||||
'userName': userName,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -52,7 +52,12 @@ class VoicePresetStore {
|
||||
VoicePreset(id: 'default_polite', name: '礼貌提示', text: '请注意避让,感谢配合。'),
|
||||
];
|
||||
|
||||
static Future<List<VoicePreset>> loadPresets(String deviceName) async {
|
||||
/// 首次进入时落盘一份出厂默认;[fallback] 允许调用方传入已本地化的默认值
|
||||
static Future<List<VoicePreset>> loadPresets(
|
||||
String deviceName, {
|
||||
List<VoicePreset>? fallback,
|
||||
}) async {
|
||||
final defaults = fallback ?? VoicePresetStore.defaults;
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final raw = prefs.getString(_keyOf(deviceName));
|
||||
if (raw == null || raw.isEmpty) {
|
||||
|
||||
Reference in New Issue
Block a user