Files
CloudHome-Ops/lib/models/marquee_message.dart

212 lines
7.0 KiB
Dart
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/// 滚动字幕消息模型。
///
/// 对应 Web 后台「滚动字幕」表(tv_scrolling_text / theme_scrolling_text)
/// 以及管理模块「滚动字幕管理」中的单条字幕记录。
///
/// 字段映射:
/// - Web 端返回 `orgId` / `orgName`,本模型内部使用 `storeId` / `storeName`。
/// - Web 端返回 `scrollSpeed`,本模型内部使用 `speed`。
/// - Web 端返回 `bgColor`,本模型内部使用 `backgroundColor`。
/// - `status` 沿用 Web 端语义:`1=启用`,`0=禁用`。
class MarqueeMessage {
const MarqueeMessage({
required this.id,
required this.storeId,
required this.storeName,
required this.content,
required this.status,
required this.speed,
required this.createTime,
required this.updateTime,
this.fontColor,
this.backgroundColor,
this.fontSize,
this.level,
this.startTime,
this.endTime,
});
/// 字幕 ID。
final String id;
/// 所属门店 ID(对应 Web 端 orgId)。
final String storeId;
/// 所属门店名称(对应 Web 端 orgName)。
final String storeName;
/// 字幕内容。
final String content;
/// 状态:`1=启用`,`0=禁用`。
final int status;
/// 滚动速度(对应 Web 端 scrollSpeed,单位 ms/像素,越小越快)。
///
/// 档位映射:慢=200 / 较慢=100 / 中=50 / 较快=30 / 快=10。
final int speed;
/// 字体颜色(Hex,如 `#FFFFFF`)。
final String? fontColor;
/// 背景颜色(Hex,如 `#3B82F6`,对应 Web 端 bgColor)。
final String? backgroundColor;
/// 字体大小(px,如 32)。
final int? fontSize;
/// 字幕级别/优先级。
final int? level;
/// 开始生效时间(Web 端为 `HH:mm:ss` 字符串,本地存为时间)。
final DateTime? startTime;
/// 结束生效时间(Web 端为 `HH:mm:ss` 字符串,本地存为时间)。
final DateTime? endTime;
/// 创建时间。
final DateTime? createTime;
/// 更新时间。
final DateTime? updateTime;
bool get isEnabled => status == 1;
bool get isDisabled => status == 0;
factory MarqueeMessage.fromJson(Map<String, dynamic> json) {
return MarqueeMessage(
id: (json['id'] ?? json['marqueeId'])?.toString() ?? '',
storeId: json['storeId']?.toString() ??
json['orgId']?.toString() ??
json['org_id']?.toString() ??
'',
storeName: json['storeName']?.toString() ??
json['orgName']?.toString() ??
json['org_name']?.toString() ??
'',
content: json['content']?.toString() ?? '',
status: _parseInt(json['status'], fallback: 0) ?? 0,
speed: _parseInt(json['speed'], fallback: 50) ??
_parseInt(json['scrollSpeed'], fallback: 50) ??
_parseInt(json['scroll_speed'], fallback: 50) ??
50,
fontColor: json['fontColor']?.toString() ?? json['font_color']?.toString(),
backgroundColor: json['backgroundColor']?.toString() ??
json['bgColor']?.toString() ??
json['bg_color']?.toString(),
fontSize: _parseInt(json['fontSize'] ?? json['font_size']),
level: _parseInt(json['level']),
startTime: _parseDateTime(json['startTime'] ?? json['start_time']),
endTime: _parseDateTime(json['endTime'] ?? json['end_time']),
createTime: _parseDateTime(json['createTime'] ?? json['create_time']),
updateTime: _parseDateTime(json['updateTime'] ?? json['update_time']),
);
}
/// 转换为本地缓存使用的 JSON。
Map<String, dynamic> toJson() {
return {
'id': id,
'storeId': storeId,
'storeName': storeName,
'content': content,
'status': status,
'speed': speed,
if (fontColor != null) 'fontColor': fontColor,
if (backgroundColor != null) 'backgroundColor': backgroundColor,
if (fontSize != null) 'fontSize': fontSize,
if (level != null) 'level': level,
if (startTime != null) 'startTime': _formatTime(startTime!),
if (endTime != null) 'endTime': _formatTime(endTime!),
'createTime': createTime?.toIso8601String(),
'updateTime': updateTime?.toIso8601String(),
};
}
/// 转换为 Web 后台可接收的字段名(用于新增/编辑请求)。
Map<String, dynamic> toWebJson() {
return {
if (id.isNotEmpty) 'id': int.tryParse(id),
'orgId': int.tryParse(storeId) ?? storeId,
'orgName': storeName,
'content': content,
'scrollSpeed': speed,
if (fontColor != null) 'fontColor': fontColor,
if (backgroundColor != null) 'bgColor': backgroundColor,
if (fontSize != null) 'fontSize': fontSize,
if (level != null) 'level': level,
'status': status,
if (startTime != null) 'startTime': _formatTime(startTime!),
if (endTime != null) 'endTime': _formatTime(endTime!),
};
}
MarqueeMessage copyWith({
String? id,
String? storeId,
String? storeName,
String? content,
int? status,
int? speed,
String? fontColor,
String? backgroundColor,
int? fontSize,
int? level,
DateTime? startTime,
DateTime? endTime,
DateTime? createTime,
DateTime? updateTime,
}) {
return MarqueeMessage(
id: id ?? this.id,
storeId: storeId ?? this.storeId,
storeName: storeName ?? this.storeName,
content: content ?? this.content,
status: status ?? this.status,
speed: speed ?? this.speed,
fontColor: fontColor ?? this.fontColor,
backgroundColor: backgroundColor ?? this.backgroundColor,
fontSize: fontSize ?? this.fontSize,
level: level ?? this.level,
startTime: startTime ?? this.startTime,
endTime: endTime ?? this.endTime,
createTime: createTime ?? this.createTime,
updateTime: updateTime ?? this.updateTime,
);
}
/// 颜色字段兜底:当 Web 端未返回颜色时返回默认半透明色。
static const String defaultFontColor = '#FFFFFF';
static const String defaultBackgroundColor = '#3B82F6';
/// 兼容 `yyyy-MM-dd HH:mm:ss`、ISO 8601 以及纯 `HH:mm:ss` 时间字符串。
static DateTime? _parseDateTime(dynamic value) {
if (value == null) return null;
final text = value.toString().trim();
if (text.isEmpty) return null;
// 纯时间:补齐一个固定日期用于本地 DateTime 存储。
if (RegExp(r'^\d{2}:\d{2}:\d{2}$').hasMatch(text)) {
return DateTime.tryParse('2000-01-01 $text');
}
return DateTime.tryParse(text) ??
DateTime.tryParse(text.replaceFirst(' ', 'T'));
}
/// 时间字段序列化为 `HH:mm:ss`,与 Web 后台保持一致。
static String _formatTime(DateTime value) {
return '${value.hour.toString().padLeft(2, '0')}:'
'${value.minute.toString().padLeft(2, '0')}:'
'${value.second.toString().padLeft(2, '0')}';
}
/// 解析整数字段,兼容 int / String / null。
static int? _parseInt(dynamic value, {int? fallback}) {
if (value == null) return fallback;
if (value is int) return value;
if (value is String) return int.tryParse(value.trim()) ?? fallback;
return fallback;
}
}