MappingProfile.cs 24.8 KB
using AutoMapper;
using Rcs.Application.Dtos;
using Rcs.Application.DTOs;
using Rcs.Domain.Entities;
using Rcs.Domain.Enums;
using Rcs.Shared.Utils;
using TaskStatus = Rcs.Domain.Entities.TaskStatus;

namespace Rcs.Application.Common.Mapping
{
    /// <summary>
    /// AutoMapper 配置文件
    /// </summary>
    public class MappingProfile : Profile
    {
        public MappingProfile()
        {
            // 机器人映射 - 包含枚举到字符串的转换
            // @author zzy - 修改为使用导航属性
            CreateMap<Robot, RobotDto>()
                .ForMember(dest => dest.RobotId, opt => opt.MapFrom(src => src.RobotId.ToString()))
                .ForMember(dest => dest.RobotManufacturer, opt => opt.MapFrom(src => src.RobotManufacturer))
                .ForMember(dest => dest.RobotType, opt => opt.MapFrom(src => src.RobotType))
                .ForMember(dest => dest.Status, opt => opt.MapFrom(src => src.Status))
                .ForMember(dest => dest.Online, opt => opt.MapFrom(src => src.Online))
                .ForMember(dest => dest.OperatingMode, opt => opt.MapFrom(src => src.OperatingMode))
                .ForMember(dest => dest.CurrentMapCode, opt => opt.MapFrom(src => src.Map != null ? src.Map.MapCode : null))
                .ForMember(dest => dest.ForkAngleOffset, opt => opt.MapFrom(src => src.ForkRadOffset != null ? src.ForkRadOffset.Select(r => AngleConverter.ToCycleDegrees(r)).ToList() : null))
                .ForMember(dest => dest.CacheLocations, opt => opt.MapFrom(src => src.CacheLocations));

            CreateMap<Robot, RobotListItemDto>()
                .ForMember(dest => dest.RobotId, opt => opt.MapFrom(src => src.RobotId.ToString()))
                .ForMember(dest => dest.RobotManufacturer, opt => opt.MapFrom(src => src.RobotManufacturer))
                .ForMember(dest => dest.RobotType, opt => opt.MapFrom(src => src.RobotType))
                .ForMember(dest => dest.CacheLocations, opt => opt.MapFrom(src => src.CacheLocations));


            CreateMap<Map, MapDto>()
                .ForMember(dest => dest.MapId, opt => opt.MapFrom(src => src.MapId.ToString()))
                .ForMember(dest => dest.MapType, opt => opt.MapFrom(src => src.MapType));

            CreateMap<MapDto, Map>()
                .ForMember(dest => dest.MapId, opt => opt.MapFrom(src => Guid.Parse(src.MapId)))
                .ForMember(dest => dest.MapType, opt => opt.MapFrom(src => (MapTYPE)src.MapType));

            CreateMap<Map, MapListItemDto>()
                .ForMember(dest => dest.MapId, opt => opt.MapFrom(src => src.MapId.ToString()))
                .ForMember(dest => dest.MapType, opt => opt.MapFrom(src => src.MapType));

            CreateMap<MapListItemDto, Map>()
                .ForMember(dest => dest.MapId, opt => opt.MapFrom(src => Guid.Parse(src.MapId)))
                .ForMember(dest => dest.MapType, opt => opt.MapFrom(src => (MapTYPE)src.MapType));

            // MapResource 映射 - 枚举到字符串的转换,Guid到string的转换
            // @author zzy - 添加 MaxSpeed, CanRotate, EntryAction, ExitAction 映射,LocationCoordinates Polygon转List<PointDto>
            CreateMap<MapResource, MapResourceDto>()
                .ForMember(dest => dest.ResourceId, opt => opt.MapFrom(src => src.ResourceId.ToString()))
                .ForMember(dest => dest.MapId, opt => opt.MapFrom(src => src.MapId.ToString()))
                .ForMember(dest => dest.Type, opt => opt.MapFrom(src => src.Type))
                .ForMember(dest => dest.LocationCoordinates,
                    opt => opt.MapFrom(src =>
                        PolygonConverter.ToPointList(src.LocationCoordinates) != null
                            ? PolygonConverter.ToPointList(src.LocationCoordinates)!
                                .Select(p => new Point { X = p.X, Y = p.Y }).ToList()
                            : null))
                .ForMember(dest => dest.PreAction1Type, opt => opt.MapFrom(src => src.PreAction1Type.HasValue ? (int?)src.PreAction1Type.Value : null))
                .ForMember(dest => dest.PreNetActions1, opt => opt.MapFrom(src => src.PreNetActions1 != null ? src.PreNetActions1.Select(n => n.ToString()).ToList() : null))
                .ForMember(dest => dest.PostAction1Type, opt => opt.MapFrom(src => src.PostAction1Type.HasValue ? (int?)src.PostAction1Type.Value : null))
                .ForMember(dest => dest.PostNetActions1, opt => opt.MapFrom(src => src.PostNetActions1 != null ? src.PostNetActions1.Select(n => n.ToString()).ToList() : null))
                .ForMember(dest => dest.PreAction2Type, opt => opt.MapFrom(src => src.PreAction2Type.HasValue ? (int?)src.PreAction2Type.Value : null))
                .ForMember(dest => dest.PreNetActions2, opt => opt.MapFrom(src => src.PreNetActions2 != null ? src.PreNetActions2.Select(n => n.ToString()).ToList() : null))
                .ForMember(dest => dest.PostAction2Type, opt => opt.MapFrom(src => src.PostAction2Type.HasValue ? (int?)src.PostAction2Type.Value : null))
                .ForMember(dest => dest.PostNetActions2, opt => opt.MapFrom(src => src.PostNetActions2 != null ? src.PostNetActions2.Select(n => n.ToString()).ToList() : null));

            CreateMap<MapResourceDto, MapResource>()
                .ForMember(dest => dest.ResourceId, opt => opt.MapFrom(src => string.IsNullOrEmpty(src.ResourceId) ? Guid.Empty : Guid.Parse(src.ResourceId)))
                .ForMember(dest => dest.MapId, opt => opt.MapFrom(src => string.IsNullOrEmpty(src.MapId) ? Guid.Empty : Guid.Parse(src.MapId)))
                .ForMember(dest => dest.Type, opt => opt.MapFrom(src => (MapResourcesTYPE)src.Type))
                .ForMember(dest => dest.LocationCoordinates, opt => opt.MapFrom<LocationCoordinatesResolver>())

                .ForMember(dest => dest.Maps, opt => opt.Ignore());

            // MapNode 映射 - 枚举到字符串的转换,Guid到string的转换
            // @author zzy - 添加 StorageLocations 映射, StorageLocationTypeId 映射, Theta弧度转角度
            CreateMap<MapNode, MapNodeDto>()
                .ForMember(dest => dest.NodeId, opt => opt.MapFrom(src => src.NodeId.ToString()))
                .ForMember(dest => dest.MapId, opt => opt.MapFrom(src => src.MapId.ToString()))
                .ForMember(dest => dest.StorageLocationTypeId, opt => opt.MapFrom(src => src.StorageLocationTypeId.HasValue ? src.StorageLocationTypeId.Value.ToString() : null))
                .ForMember(dest => dest.Theta, opt => opt.MapFrom(src => src.Theta.HasValue ? AngleConverter.ToCycleDegrees(src.Theta.Value) : (double?)null));  // 弧度转角度,保留6位小数

            // StorageArea 映射
            // @author zzy
            CreateMap<StorageArea, StorageAreaDto>()
                .ForMember(dest => dest.AreaId, opt => opt.MapFrom(src => src.AreaId.ToString()));

            // StorageLocation 映射
            // @author zzy
            CreateMap<StorageLocation, StorageLocationDto>()
                .ForMember(dest => dest.LocationId, opt => opt.MapFrom(src => src.LocationId.ToString()))
                .ForMember(dest => dest.AreaId, opt => opt.MapFrom(src => src.AreaId.ToString()))
                .ForMember(dest => dest.LocationTypeId, opt => opt.MapFrom(src => src.LocationTypeId.HasValue ? src.LocationTypeId.Value.ToString() : null))
                .ForMember(dest => dest.Status, opt => opt.MapFrom(src => (int)src.Status));

            // StorageLocationType 映射
            // @author zzy
            CreateMap<StorageLocationType, StorageLocationTypeDto>()
                .ForMember(dest => dest.TypeId, opt => opt.MapFrom(src => src.TypeId.ToString()));

            CreateMap<StorageLocationType, StorageLocationTypeListItemDto>()
                .ForMember(dest => dest.TypeId, opt => opt.MapFrom(src => src.TypeId.ToString()));

            // RobotCacheLocation 映射
            CreateMap<RobotCacheLocation, RobotCacheLocationListItemDto>()
                .ForMember(dest => dest.CacheLocationId, opt => opt.MapFrom(src => src.CacheLocationId.ToString()))
                .ForMember(dest => dest.RobotId, opt => opt.MapFrom(src => src.RobotId.ToString()))
                .ForMember(dest => dest.RobotCode, opt => opt.MapFrom(src => src.Robot != null ? src.Robot.RobotCode : null))
                .ForMember(dest => dest.RobotName, opt => opt.MapFrom(src => src.Robot != null ? src.Robot.RobotName : null));

            CreateMap<RobotCacheLocation, RobotCacheLocationDto>()
                .ForMember(dest => dest.CacheLocationId, opt => opt.MapFrom(src => src.CacheLocationId.ToString()))
                .ForMember(dest => dest.RobotId, opt => opt.MapFrom(src => src.RobotId.ToString()));

            CreateMap<CreateRobotCacheLocationDto, RobotCacheLocation>()
                .ForMember(dest => dest.CacheLocationId, opt => opt.Ignore()) // 由工厂方法生成
                .ForMember(dest => dest.RobotId, opt => opt.MapFrom(src => Guid.Parse(src.RobotId)))
                .ForMember(dest => dest.CreatedAt, opt => opt.Ignore()) // 由工厂方法设置
                .ForMember(dest => dest.UpdatedAt, opt => opt.Ignore()) // 由工厂方法设置
                .ForMember(dest => dest.Robot, opt => opt.Ignore()); // 导航属性忽略

            CreateMap<UpdateRobotCacheLocationDto, RobotCacheLocation>()
                .ForMember(dest => dest.CacheLocationId, opt => opt.Ignore())
                .ForMember(dest => dest.RobotId, opt => opt.Ignore())
                .ForMember(dest => dest.CreatedAt, opt => opt.Ignore())
                .ForMember(dest => dest.UpdatedAt, opt => opt.Ignore())
                .ForMember(dest => dest.Robot, opt => opt.Ignore());

            // @author zzy - Theta角度转弧度
            CreateMap<MapNodeDto, MapNode>()
                .ForMember(dest => dest.NodeId,
                    opt => opt.MapFrom(src => string.IsNullOrEmpty(src.NodeId) ? Guid.Empty : Guid.Parse(src.NodeId)))
                .ForMember(dest => dest.MapId,
                    opt => opt.MapFrom(src => string.IsNullOrEmpty(src.MapId) ? Guid.Empty : Guid.Parse(src.MapId)))
                .ForMember(dest => dest.Type,
                    opt => opt.MapFrom(src =>
                        (MapNodeTYPE)src.Type))
                .ForMember(dest => dest.StorageLocationTypeId,
                    opt => opt.MapFrom(src => string.IsNullOrEmpty(src.StorageLocationTypeId) ? (Guid?)null : Guid.Parse(src.StorageLocationTypeId)))
                .ForMember(dest => dest.Theta, opt => opt.MapFrom(src => src.Theta.HasValue ? AngleConverter.ToCycleRadians(src.Theta.Value) : (double?)null))  // 角度转弧度
                .ForMember(dest => dest.Map, opt => opt.Ignore())
                .ForMember(dest => dest.StorageLocationType, opt => opt.Ignore())
                .ForMember(dest => dest.MapEdgesFromNodes, opt => opt.Ignore())
                .ForMember(dest => dest.MapEdgesToNodes, opt => opt.Ignore())
                .ForMember(dest => dest.MapResourcess, opt => opt.Ignore());

            // MapEdge 映射 - Guid到string的转换,弧度与角度互转
            // @author zzy - OrientationRads/MaxRadDeviation(弧度) 与 OrientationAngles/MaxAngleDeviation(角度) 互转
            CreateMap<MapEdge, MapEdgeDto>()
                .ForMember(dest => dest.EdgeId, opt => opt.MapFrom(src => src.EdgeId.ToString()))
                .ForMember(dest => dest.MapId, opt => opt.MapFrom(src => src.MapId.ToString()))
                .ForMember(dest => dest.FromNode, opt => opt.MapFrom(src => src.FromNode.ToString()))
                .ForMember(dest => dest.ToNode, opt => opt.MapFrom(src => src.ToNode.ToString()))
                .ForMember(dest => dest.OrientationAngles, opt => opt.MapFrom(src => src.OrientationRads != null ? src.OrientationRads.Select(r => AngleConverter.ToCycleDegrees(r)).ToList() : null))  // 弧度列表转角度列表,保留6位小数
                .ForMember(dest => dest.MaxAngleDeviation, opt => opt.MapFrom(src => src.MaxRadDeviation.HasValue ? AngleConverter.ToCycleDegrees(src.MaxRadDeviation.Value): (double?)null));  // 弧度转角度,保留6位小数

            // @author zzy - OrientationAngles/MaxAngleDeviation(角度) 转 OrientationRads/MaxRadDeviation(弧度)
            CreateMap<MapEdgeDto, MapEdge>()
                .ForMember(dest => dest.EdgeId, opt => opt.MapFrom(src => string.IsNullOrEmpty(src.EdgeId) ? Guid.Empty : Guid.Parse(src.EdgeId)))
                .ForMember(dest => dest.MapId, opt => opt.MapFrom(src => string.IsNullOrEmpty(src.MapId) ? Guid.Empty : Guid.Parse(src.MapId)))
                .ForMember(dest => dest.FromNode, opt => opt.MapFrom(src => Guid.Parse(src.FromNode)))
                .ForMember(dest => dest.ToNode, opt => opt.MapFrom(src => Guid.Parse(src.ToNode)))
                .ForMember(dest => dest.OrientationRads, opt => opt.MapFrom(src => src.OrientationAngles != null ? src.OrientationAngles.Select(a => AngleConverter.ToCycleRadians(a)).ToList() : null))  // 角度列表转弧度列表
                .ForMember(dest => dest.MaxRadDeviation, opt => opt.MapFrom(src => src.MaxAngleDeviation.HasValue ? AngleConverter.ToCycleRadians(src.MaxAngleDeviation.Value) : (double?)null))  // 角度转弧度
                .ForMember(dest => dest.Maps, opt => opt.Ignore())
                .ForMember(dest => dest.MapNodesFromNode, opt => opt.Ignore())
                .ForMember(dest => dest.MapNodesToNode, opt => opt.Ignore());

            // TaskTemplate 映射
            CreateMap<TaskTemplate, TaskTemplateDto>()
                .ForMember(dest => dest.TemplateId, opt => opt.MapFrom(src => src.TemplateId.ToString()))
                .ForMember(dest => dest.RobotType, opt => opt.MapFrom(src => src.RobotType));

            CreateMap<TaskTemplate, TaskTemplateListItemDto>()
                .ForMember(dest => dest.TemplateId, opt => opt.MapFrom(src => src.TemplateId.ToString()))
                .ForMember(dest => dest.RobotType, opt => opt.MapFrom(src => src.RobotType));

            CreateMap<TaskStep, TaskStepDto>()
                .ForMember(dest => dest.StepId, opt => opt.MapFrom(src => src.StepId.ToString()))
                .ForMember(dest => dest.TemplateId, opt => opt.MapFrom(src => src.TemplateId.ToString()))
                .ForMember(dest => dest.Type, opt => opt.MapFrom(src => src.Type));

            // @author zzy - 修复 NodeValue 映射类型错误,添加四对动作属性映射
            CreateMap<StepProperty, StepPropertyDto>()
                .ForMember(dest => dest.PropertyId, opt => opt.MapFrom(src => src.PropertyId.ToString()))
                .ForMember(dest => dest.StepId, opt => opt.MapFrom(src => src.StepId.ToString()))
                .ForMember(dest => dest.PropertyType, opt => opt.MapFrom(src => src.PropertyType))
                .ForMember(dest => dest.NodeValue,
                    opt => opt.MapFrom(src => src.NodeValue.HasValue ? (int)src.NodeValue.Value : 0))
                .ForMember(dest => dest.PreAction1Type, opt => opt.MapFrom(src => src.PreAction1Type.HasValue ? (int?)src.PreAction1Type.Value : null))
                .ForMember(dest => dest.PreNetActions1, opt => opt.MapFrom(src => src.PreNetActions1 != null ? src.PreNetActions1.Select(n => n.ToString()).ToList() : null))
                .ForMember(dest => dest.PostAction1Type, opt => opt.MapFrom(src => src.PostAction1Type.HasValue ? (int?)src.PostAction1Type.Value : null))
                .ForMember(dest => dest.PostNetActions1, opt => opt.MapFrom(src => src.PostNetActions1 != null ? src.PostNetActions1.Select(n => n.ToString()).ToList() : null))
                .ForMember(dest => dest.PreAction2Type, opt => opt.MapFrom(src => src.PreAction2Type.HasValue ? (int?)src.PreAction2Type.Value : null))
                .ForMember(dest => dest.PreNetActions2, opt => opt.MapFrom(src => src.PreNetActions2 != null ? src.PreNetActions2.Select(n => n.ToString()).ToList() : null))
                .ForMember(dest => dest.PostAction2Type, opt => opt.MapFrom(src => src.PostAction2Type.HasValue ? (int?)src.PostAction2Type.Value : null))
                .ForMember(dest => dest.PostNetActions2, opt => opt.MapFrom(src => src.PostNetActions2 != null ? src.PostNetActions2.Select(n => n.ToString()).ToList() : null));

            // @author zzy - StepPropertyAction 映射
            CreateMap<NetActionPropertys, NetActionPropertyDto>()
                .ForMember(dest => dest.ActionConfigId, opt => opt.MapFrom(src => src.NetActionId.ToString()));

            CreateMap<StepAction, ActionDto>()
                .ForMember(dest => dest.ActionId, opt => opt.MapFrom(src => src.ActionId.ToString()))
                .ForMember(dest => dest.PropertyId, opt => opt.MapFrom(src => src.PropertyId.ToString()))
                .ForMember(dest => dest.BlockingType, opt => opt.MapFrom(src => src.BlockingType));

            // ActionConfiguration 映射
            CreateMap<ActionConfiguration, ActionConfigurationDto>()
                .ForMember(dest => dest.ActionConfigId, opt => opt.MapFrom(src => src.ActionConfigId.ToString()))
                .ForMember(dest => dest.ActionCategory, opt => opt.MapFrom(src => (int)src.ActionCategory))
                .ForMember(dest => dest.RobotType, opt => opt.MapFrom(src => (int)src.RobotType))
                .ForMember(dest => dest.BlockingType, opt => opt.MapFrom(src => (int)src.BlockingType));

            CreateMap<ActionConfiguration, ActionConfigurationListItemDto>()
                .ForMember(dest => dest.ActionConfigId, opt => opt.MapFrom(src => src.ActionConfigId.ToString()))
                .ForMember(dest => dest.ActionCategory, opt => opt.MapFrom(src => (int)src.ActionCategory))
                .ForMember(dest => dest.RobotType, opt => opt.MapFrom(src => (int)src.RobotType))
                .ForMember(dest => dest.BlockingType, opt => opt.MapFrom(src => (int)src.BlockingType));

            // ActionParameterDefinition 映射
            CreateMap<ActionParameterDefinition, ActionParameterDefinitionDto>()
                .ForMember(dest => dest.ParamId, opt => opt.MapFrom(src => src.ParamId.ToString()))
                .ForMember(dest => dest.ActionConfigId, opt => opt.MapFrom(src => src.ActionConfigId.ToString()))
                .ForMember(dest => dest.ParameterValueType, opt => opt.MapFrom(src => (int)src.ParameterValueType))
                .ForMember(dest => dest.ParameterSourceType, opt => opt.MapFrom(src => src.ParameterSourceType.HasValue ? (int?)src.ParameterSourceType.Value : null));

            // NetActionPropertys 映射
            // @author zzy - 添加 WaitResponseType 枚举到 int 的映射
            CreateMap<NetActionPropertys, NetActionPropertysDto>()
                .ForMember(dest => dest.NetActionId, opt => opt.MapFrom(src => src.NetActionId.ToString()))
                .ForMember(dest => dest.WaitResponseType, opt => opt.MapFrom(src => (int)src.WaitResponseType));

            CreateMap<NetActionPropertys, NetActionPropertysListItemDto>()
                .ForMember(dest => dest.NetActionId, opt => opt.MapFrom(src => src.NetActionId.ToString()))
                .ForMember(dest => dest.WaitResponseType, opt => opt.MapFrom(src => (int)src.WaitResponseType));

            // RobotTask 映射
            // @author zzy
            CreateMap<RobotTask, RobotTaskListItemDto>()
                .ForMember(dest => dest.TaskId, opt => opt.MapFrom(src => src.TaskId.ToString()))
                .ForMember(dest => dest.RobotId, opt => opt.MapFrom(src => src.RobotId.HasValue ? src.RobotId.Value.ToString() : null))
                .ForMember(dest => dest.RobotCode, opt => opt.MapFrom(src => src.Robot != null ? src.Robot.RobotCode : null))
                .ForMember(dest => dest.TaskTemplateId, opt => opt.MapFrom(src => src.TaskTemplateId.ToString()))
                .ForMember(dest => dest.TaskTemplateName, opt => opt.MapFrom(src => src.TaskTemplate != null ? src.TaskTemplate.TemplateName : null))
                .ForMember(dest => dest.BeginLocationId, opt => opt.MapFrom(src => src.BeginLocationId.HasValue ? src.BeginLocationId.Value.ToString() : null))
                .ForMember(dest => dest.BeginLocationName, opt => opt.MapFrom(src => src.BeginLocation != null ? src.BeginLocation.LocationName : null))
                .ForMember(dest => dest.EndLocationId, opt => opt.MapFrom(src => src.EndLocationId.HasValue ? src.EndLocationId.Value.ToString() : null))
                .ForMember(dest => dest.EndLocationName, opt => opt.MapFrom(src => src.EndLocation != null ? src.EndLocation.LocationName : null))
                .ForMember(dest => dest.Status, opt => opt.MapFrom(src => (int)src.Status))
                .ForMember(dest => dest.StatusName, opt => opt.MapFrom(src => GetTaskStatusName(src.Status)));

            CreateMap<RobotTask, RobotTaskDto>()
                .ForMember(dest => dest.TaskId, opt => opt.MapFrom(src => src.TaskId.ToString()))
                .ForMember(dest => dest.RobotId, opt => opt.MapFrom(src => src.RobotId.HasValue ? src.RobotId.Value.ToString() : null))
                .ForMember(dest => dest.RobotCode, opt => opt.MapFrom(src => src.Robot != null ? src.Robot.RobotCode : null))
                .ForMember(dest => dest.RobotName, opt => opt.MapFrom(src => src.Robot != null ? src.Robot.RobotName : null))
                .ForMember(dest => dest.TaskTemplateId, opt => opt.MapFrom(src => src.TaskTemplateId.ToString()))
                .ForMember(dest => dest.TaskTemplateName, opt => opt.MapFrom(src => src.TaskTemplate != null ? src.TaskTemplate.TemplateName : null))
                .ForMember(dest => dest.BeginLocationId, opt => opt.MapFrom(src => src.BeginLocationId.HasValue ? src.BeginLocationId.Value.ToString() : null))
                .ForMember(dest => dest.BeginLocationCode, opt => opt.MapFrom(src => src.BeginLocation != null ? src.BeginLocation.LocationCode : null))
                .ForMember(dest => dest.EndLocationId, opt => opt.MapFrom(src => src.EndLocationId.HasValue ? src.EndLocationId.Value.ToString() : null))
                .ForMember(dest => dest.EndLocationCode, opt => opt.MapFrom(src => src.EndLocation != null ? src.EndLocation.LocationCode : null))
                .ForMember(dest => dest.Status, opt => opt.MapFrom(src => (int)src.Status))
                .ForMember(dest => dest.StatusName, opt => opt.MapFrom(src => GetTaskStatusName(src.Status)));

            // RobotSubTask 映射
            // @author zzy
            CreateMap<RobotSubTask, RobotSubTaskDto>()
                .ForMember(dest => dest.SubTaskId, opt => opt.MapFrom(src => src.SubTaskId.ToString()))
                .ForMember(dest => dest.TaskId, opt => opt.MapFrom(src => src.TaskId.ToString()))
                .ForMember(dest => dest.RobotId, opt => opt.MapFrom(src => src.RobotId.HasValue ? src.RobotId.Value.ToString() : null))
                .ForMember(dest => dest.RobotCode, opt => opt.MapFrom(src => src.Robot != null ? src.Robot.RobotCode : null))
                .ForMember(dest => dest.BeginNodeId, opt => opt.MapFrom(src => src.BeginNodeId.ToString()))
                .ForMember(dest => dest.BeginNodeName, opt => opt.MapFrom(src => src.BeginNode != null ? src.BeginNode.NodeName : null))
                .ForMember(dest => dest.EndNodeId, opt => opt.MapFrom(src => src.EndNodeId.ToString()))
                .ForMember(dest => dest.EndNodeName, opt => opt.MapFrom(src => src.EndNode != null ? src.EndNode.NodeName : null))
                .ForMember(dest => dest.Sequence, opt => opt.MapFrom(src => src.Sequence))
                .ForMember(dest => dest.Status, opt => opt.MapFrom(src => (int)src.Status))
                .ForMember(dest => dest.StatusName, opt => opt.MapFrom(src => GetTaskStatusName(src.Status)));

        }

        /// <summary>
        /// 获取任务状态名称
        /// @author zzy
        /// </summary>
        private static string GetTaskStatusName(TaskStatus status)
        {
            return status switch
            {
                TaskStatus.Pending => "等待中",
                TaskStatus.Assigned => "已分配",
                TaskStatus.InProgress => "执行中",
                TaskStatus.WaitingForResource => "等待资源",
                TaskStatus.Completed => "已完成",
                TaskStatus.Cancelled => "已取消",
                TaskStatus.Failed => "执行失败",
                TaskStatus.Timeout => "超时",
                TaskStatus.Reassigned => "重新分配",
                _ => "未知"
            };
        }
    }

    /// <summary>
    /// LocationCoordinates 自定义值解析器
    /// @author zzy
    /// </summary>
    public class LocationCoordinatesResolver : IValueResolver<MapResourceDto, MapResource, NetTopologySuite.Geometries.Polygon?>
    {
        public NetTopologySuite.Geometries.Polygon? Resolve(MapResourceDto source, MapResource destination, NetTopologySuite.Geometries.Polygon? destMember, ResolutionContext context)
        {
            if (source.LocationCoordinates == null || source.LocationCoordinates.Count < 3)
                return null;
            return PolygonConverter.ToPolygonFromXY(source.LocationCoordinates.Select(p => new double[] { p.X, p.Y }));
        }
    }
}