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

282 lines
7.5 KiB
Dart
Raw Permalink Normal View History

/// 介绍页分类模型。
///
/// 对应后端 /company/introCategory/* 接口。
///
/// 后端实际字段:
/// - id, orgId, orgName, categoryType, name, subCategories,
/// createTime, updateTime
/// 注:后端分类列表不返回 sort/status,兼容处理为默认值。
class IntroCategory {
const IntroCategory({
required this.id,
required this.orgId,
required this.orgName,
required this.categoryType,
required this.name,
required this.sort,
required this.status,
required this.createTime,
this.subCategories,
});
/// 分类 ID。
final String id;
/// 所属门店/组织 ID。
final String orgId;
/// 所属门店/组织名称(用于门店筛选展示)。
final String orgName;
/// 分类类型编码(如 gongsi/gsjs/hotel 等)。
final String categoryType;
/// 分类名称。
final String name;
/// 排序号(后端可能缺失,缺省 0)。
final int sort;
/// 状态(1=启用/正常,0=禁用),与 Web 后端保持一致。
final int status;
/// 创建时间。
final DateTime? createTime;
/// 后端可能嵌入的子分类原始数据(暂不直接解析,用于后续扩展)。
final List<dynamic>? subCategories;
factory IntroCategory.fromJson(Map<String, dynamic> json) {
return IntroCategory(
id: json['id']?.toString() ?? '',
orgId: json['orgId']?.toString() ?? '',
orgName: json['orgName']?.toString() ?? '',
categoryType: json['categoryType']?.toString() ?? '',
name: json['name']?.toString() ?? '',
sort: int.tryParse(json['sortOrder']?.toString() ??
json['sort']?.toString() ??
'0') ??
0,
status: _parseStatus(json['status']),
createTime: _parseDateTime(json['createTime']),
subCategories: json['subCategories'] is List
? List<dynamic>.from(json['subCategories'] as List)
: null,
);
}
/// 与 Web 后端保持一致:1=启用/正常,0=禁用;缺失/null 视为启用。
static int _parseStatus(dynamic value) {
if (value == null) return 1;
if (value is bool) return value ? 1 : 0;
final text = value.toString().trim().toLowerCase();
if (text == '1' || text == 'active' || text == '正常' || text == '启用' ||
text == 'enabled' || text == 'true') {
return 1;
}
if (text == '0' ||
text == 'inactive' ||
text == '禁用' ||
text == '停用' ||
text == 'disabled' ||
text == 'false') {
return 0;
}
return 1;
}
/// 兼容 `yyyy-MM-dd HH:mm:ss` 与 ISO 8601 两种时间格式。
static DateTime? _parseDateTime(dynamic value) {
if (value == null) return null;
final text = value.toString().trim();
if (text.isEmpty) return null;
return DateTime.tryParse(text) ??
DateTime.tryParse(text.replaceFirst(' ', 'T'));
}
Map<String, dynamic> toJson() {
return {
'id': id,
'orgId': orgId,
'orgName': orgName,
'categoryType': categoryType,
'name': name,
'sort': sort,
'status': status,
'createTime': createTime?.toIso8601String(),
'subCategories': subCategories,
};
}
}
/// 介绍页子分类模型。
///
/// 对应后端 /company/introSubcategory/* 接口。
///
/// 后端实际字段:
/// - id, categoryId, categoryType, mediaType, mediaUrl,
/// title, description, status, sortOrder, contents, createTime, updateTime
class IntroSubcategory {
const IntroSubcategory({
required this.id,
required this.categoryId,
required this.categoryType,
required this.title,
required this.description,
required this.mediaType,
required this.mediaUrl,
required this.sort,
required this.status,
this.contents,
});
/// 子分类 ID。
final String id;
/// 所属分类 ID。
final String categoryId;
/// 分类类型编码。
final String categoryType;
/// 子分类标题(后端用 title 而非 name)。
final String title;
/// 描述/简介。
final String description;
/// 媒体类型:image / video。
final String mediaType;
/// 媒体地址。
final String mediaUrl;
/// 排序号(后端字段 sortOrder)。
final int sort;
/// 状态(0=正常 1=禁用)。
final int status;
/// 后端可能嵌入的内容原始数据。
final List<dynamic>? contents;
factory IntroSubcategory.fromJson(Map<String, dynamic> json) {
return IntroSubcategory(
id: json['id']?.toString() ?? '',
categoryId: json['categoryId']?.toString() ?? '',
categoryType: json['categoryType']?.toString() ?? '',
title: json['title']?.toString() ??
json['name']?.toString() ??
json['subcategoryTitle']?.toString() ??
'',
description: json['description']?.toString() ?? '',
mediaType: json['mediaType']?.toString() ?? '',
mediaUrl: json['mediaUrl']?.toString() ?? '',
sort: int.tryParse(json['sortOrder']?.toString() ??
json['sort']?.toString() ??
'0') ??
0,
status: IntroCategory._parseStatus(json['status']),
contents: json['contents'] is List
? List<dynamic>.from(json['contents'] as List)
: null,
);
}
Map<String, dynamic> toJson() {
return {
'id': id,
'categoryId': categoryId,
'categoryType': categoryType,
'title': title,
'description': description,
'mediaType': mediaType,
'mediaUrl': mediaUrl,
'sortOrder': sort,
'status': status,
'contents': contents,
};
}
}
/// 介绍页详情模型。
///
/// 对应后端 /company/introDetail/* 接口。
///
/// 后端实际字段:
/// - id, subcategoryId, subcategoryTitle, mediaType, mediaUrl,
/// title, description, status, sortOrder, createTime, updateTime
class IntroDetail {
const IntroDetail({
required this.id,
required this.subcategoryId,
required this.title,
required this.description,
required this.mediaType,
required this.mediaUrl,
required this.sort,
required this.status,
});
/// 详情 ID。
final String id;
/// 所属子分类 ID。
final String subcategoryId;
/// 标题。
final String title;
/// 描述/内容。
final String description;
/// 媒体类型:image / video。
final String mediaType;
/// 媒体地址。
final String mediaUrl;
/// 排序号(后端字段 sortOrder)。
final int sort;
/// 状态(0=正常 1=禁用)。
final int status;
factory IntroDetail.fromJson(Map<String, dynamic> json) {
return IntroDetail(
id: json['id']?.toString() ?? '',
subcategoryId: json['subcategoryId']?.toString() ?? '',
title: json['title']?.toString() ??
json['name']?.toString() ??
json['subcategoryTitle']?.toString() ??
'',
description: json['description']?.toString() ??
json['content']?.toString() ??
'',
mediaType: json['mediaType']?.toString() ?? '',
mediaUrl: json['mediaUrl']?.toString() ??
json['imageUrl']?.toString() ??
json['videoUrl']?.toString() ??
'',
sort: int.tryParse(json['sortOrder']?.toString() ??
json['sort']?.toString() ??
'0') ??
0,
status: IntroCategory._parseStatus(json['status']),
);
}
Map<String, dynamic> toJson() {
return {
'id': id,
'subcategoryId': subcategoryId,
'title': title,
'description': description,
'mediaType': mediaType,
'mediaUrl': mediaUrl,
'sortOrder': sort,
'status': status,
};
}
}