/// 介绍页分类模型。 /// /// 对应后端 /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? subCategories; factory IntroCategory.fromJson(Map 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.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 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? contents; factory IntroSubcategory.fromJson(Map 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.from(json['contents'] as List) : null, ); } Map 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 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 toJson() { return { 'id': id, 'subcategoryId': subcategoryId, 'title': title, 'description': description, 'mediaType': mediaType, 'mediaUrl': mediaUrl, 'sortOrder': sort, 'status': status, }; } }