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

282 lines
7.5 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.

/// 介绍页分类模型。
///
/// 对应后端 /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,
};
}
}