MapController.cs 14.3 KB
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Rcs.Application.Common;
using Rcs.Application.DTOs;
using MassTransit.Mediator;
using Rcs.Application.MessageBus.Commands;
using Rcs.Application.MessageBus.Responses;
using StatusCodes = Microsoft.AspNetCore.Http.StatusCodes;
using Rcs.Application.Dtos;
using Rcs.Domain.Repositories;

namespace Rcs.Api.Controllers
{
    /// <summary>
    /// 地图管理控制器
    /// </summary>
    [ApiController]
    [Route("api/[controller]")]
    public class MapController : ControllerBase
    {
        private readonly ILogger<MapController> _logger;
        private readonly IMediator _mediator;
        private readonly IMapFileRepository _mapFileRepository;

        public MapController(
            ILogger<MapController> logger,
            IMediator mediator,
            IMapFileRepository mapFileRepository)
        {
            _logger = logger ?? throw new ArgumentNullException(nameof(logger));
            _mediator = mediator;
            _mapFileRepository = mapFileRepository;
        }

        /// <summary>
        /// 获取地图列表
        /// </summary>
        /// <returns>地图列表</returns>
        [HttpGet("list")]
        public async Task<IActionResult> GetMapList([FromQuery] GetMapsQuery query, CancellationToken cancellationToken = default)
        {
            var client = _mediator.CreateRequestClient<GetMapsQuery>();
            var response = await client.GetResponse<PagedResponse<MapListItemDto>>(query, cancellationToken);          
            return Ok(response.Message);
        }

        /// <summary>
        /// 根据ID获取地图数据
        /// </summary>
        /// <param name="id">地图ID</param>
        /// <returns>地图详情</returns>
        [HttpGet("{id}")]
        public async Task<IActionResult> GetMapById(string id, CancellationToken cancellationToken = default)
        {
            if(!Guid.TryParse(id, out Guid mapId))
            {
                return BadRequest(ApiResponse.Failed("无效的地图ID格式", StatusCodes.Status400BadRequest));
            }
            var client = _mediator.CreateRequestClient<GetMapQuery>();
            var response = await client.GetResponse<ApiResponse<MapDto>>(new GetMapQuery()
            {
                MapId = mapId
            }, cancellationToken);          
            return Ok(response.Message);
        }
        /// <summary>
        /// 根据ID获取地图详情
        /// </summary>
        /// <param name="id">地图ID</param>
        /// <returns>地图详情</returns>
        [HttpGet("{id}/details")]
        public async Task<IActionResult> GetMapDetailsById(string id, CancellationToken cancellationToken = default)
        {
            if(!Guid.TryParse(id, out Guid mapId))
            {
                return BadRequest(ApiResponse.Failed("无效的地图ID格式", StatusCodes.Status400BadRequest));
            }
            var client = _mediator.CreateRequestClient<GetMapDetailsQuery>();
            var response = await client.GetResponse<ApiResponse<MapDto>>(new GetMapDetailsQuery()
            {
                MapId = mapId
            }, cancellationToken);          
            return Ok(response.Message);
        }
        /// <summary>
        /// 创建地图
        /// </summary>
        /// <param name="dto">创建地图DTO</param>
        /// <returns>创建的地图信息</returns>
        [HttpPost]
        public async Task<IActionResult> CreateMap([FromBody] CreateOrUpdateMapCommand command)
        {
            /*
             test model
             {
              "mapCode": "MAP001",
              "mapName": "主地图",
              "mapType": 1,
              "version": "1.0.0",
              "description": "主要生产区域地图",
              "active": true
            }
             */
            if (!ModelState.IsValid)
            {
                return BadRequest(ApiResponse.Failed("请求数据验证失败", StatusCodes.Status400BadRequest));
            }
            var client = _mediator.CreateRequestClient<CreateOrUpdateMapCommand>();
            var response = await client.GetResponse<ApiResponse>(command);
            
            return Ok(response.Message);

        }
        /// <summary>
        /// 删除地图
        /// </summary>
        /// <param name="id">地图ID</param>
        /// <returns>删除结果</returns>
        [HttpPost("{id}")]
        public async Task<IActionResult> DeleteMap(string id, CancellationToken cancellationToken = default)
        {
            if(!Guid.TryParse(id, out Guid mapId))
            {
                return BadRequest(ApiResponse.Failed("无效的地图ID格式", StatusCodes.Status400BadRequest));
            }
            var client = _mediator.CreateRequestClient<DeleteMapCommand>();
            var response = await client.GetResponse<ApiResponse>(new DeleteMapCommand()
            {
                MapId = mapId
            }, cancellationToken);
            
            return Ok(response.Message);
        }
        [HttpPost("Canvas")]
        public async Task<IActionResult> CanvasMap([FromBody] ManageMapCommand command, CancellationToken cancellationToken = default)
        {
            var client = _mediator.CreateRequestClient<ManageMapCommand>();
            var response = await client.GetResponse<ApiResponse>(command, cancellationToken);
            
            return Ok(response.Message);
        }
        /// <summary>
        /// 复制地图
        /// </summary>
        /// <param name="id">地图ID</param>
        /// <returns>复制结果</returns>
        [HttpPost("{id}/copy")]
        public async Task<IActionResult> CopyMap(string id, CancellationToken cancellationToken = default)
        {
            if(!Guid.TryParse(id, out Guid mapId))
            {
                return BadRequest(ApiResponse.Failed("无效的地图ID格式", StatusCodes.Status400BadRequest));
            }
            var client = _mediator.CreateRequestClient<CopyMapCommand>();
            var response = await client.GetResponse<ApiResponse>(new CopyMapCommand()
            {
                MapId = mapId
            }, cancellationToken);
            
            return Ok(response.Message);
        }

        /// <summary>
        /// 同步地图资源
        /// @author zzy
        /// </summary>
        /// <param name="id">地图ID</param>
        /// <param name="type">同步类型:resource或points</param>
        /// <returns>同步结果</returns>
        [HttpPost("{id}/sync/resource")]
        public async Task<IActionResult> SyncMapResource(string id, CancellationToken cancellationToken = default)
        {
            if (!Guid.TryParse(id, out Guid mapId))
            {
                return BadRequest(ApiResponse.Failed("无效的地图ID格式", StatusCodes.Status400BadRequest));
            }

            var client = _mediator.CreateRequestClient<SyncMapResourceCommand>();
            var response = await client.GetResponse<ApiResponse>(new SyncMapResourceCommand
            {
                MapId = mapId
            }, cancellationToken);

            return Ok(response.Message);
        }
        /// <summary>
        /// 同步地图节点资源
        /// @author zzy
        /// </summary>
        /// <param name="id">地图ID</param>
        /// <returns>同步结果</returns>
        [HttpPost("{id}/sync/points")]
        public async Task<IActionResult> SyncMapRPoints(string id, CancellationToken cancellationToken = default)
        {
            if (!Guid.TryParse(id, out Guid mapId))
            {
                return BadRequest(ApiResponse.Failed("无效的地图ID格式", StatusCodes.Status400BadRequest));
            }

            var client = _mediator.CreateRequestClient<SyncMapPointsCommand>();
            var response = await client.GetResponse<ApiResponse>(new SyncMapPointsCommand
            {
                MapId = mapId
            }, cancellationToken);

            return Ok(response.Message);
        }
        /// <summary>
        /// 更新地图背景图设置
        /// @author zzy
        /// </summary>
        /// <param name="id">地图ID</param>
        /// <param name="opacity">透明度(0-1)</param>
        /// <param name="scale">缩放比例</param>
        /// <param name="rotation">旋转角度(-180到180)</param>
        /// <param name="offsetX">地图左下角偏移量X</param>
        /// <param name="offsetY">地图左下角偏移量Y</param>
        /// <returns>更新结果</returns>
        [HttpPost("{id}/settings")]
        public async Task<IActionResult> UpdateMapFileSettings(
            string id,
            [FromForm] decimal opacity = 0.60m,
            [FromForm] decimal scale = 1.00m,
            [FromForm] decimal rotation = 0.00m,
            [FromForm] decimal offsetX = 0.00m,
            [FromForm] decimal offsetY = 0.00m,
            CancellationToken cancellationToken = default)
        {
            if (!Guid.TryParse(id, out Guid mapId))
            {
                return BadRequest(ApiResponse.Failed("无效的地图ID格式", StatusCodes.Status400BadRequest));
            }

            var client = _mediator.CreateRequestClient<UpdateMapFileSettingsCommand>();
            var response = await client.GetResponse<ApiResponse>(new UpdateMapFileSettingsCommand
            {
                MapId = mapId,
                Opacity = opacity,
                Scale = scale,
                Rotation = rotation,
                OffsetX = offsetX,
                OffsetY = offsetY
            }, cancellationToken);

            return Ok(response.Message);
        }

        /// <summary>
        /// 上传地图文件
        /// @author zzy
        /// </summary>
        /// <param name="id">地图ID</param>
        /// <param name="file">地图文件</param>
        /// <param name="opacity">透明度(0-1)</param>
        /// <param name="scale">缩放比例</param>
        /// <param name="rotation">旋转角度(-180到180)</param>
        /// <param name="offsetX">地图左下角偏移量X</param>
        /// <param name="offsetY">地图左下角偏移量Y</param>
        /// <returns>上传结果</returns>
        [HttpPost("{id}/upload")]
        public async Task<IActionResult> UploadMapFile(
            string id,
            IFormFile file,
            [FromForm] decimal opacity = 0.60m,
            [FromForm] decimal scale = 1.00m,
            [FromForm] decimal rotation = 0.00m,
            [FromForm] decimal offsetX = 0.00m,
            [FromForm] decimal offsetY = 0.00m,
            CancellationToken cancellationToken = default)
        {
            if (!Guid.TryParse(id, out Guid mapId))
            {
                return BadRequest(ApiResponse.Failed("无效的地图ID格式", StatusCodes.Status400BadRequest));
            }

            if (file == null || file.Length == 0)
            {
                return BadRequest(ApiResponse.Failed("请选择要上传的文件", StatusCodes.Status400BadRequest));
            }

            // 将IFormFile转换为Stream
            using var stream = new MemoryStream();
            await file.CopyToAsync(stream, cancellationToken);

            var client = _mediator.CreateRequestClient<UploadMapFileCommand>();
            var response = await client.GetResponse<ApiResponse>(new UploadMapFileCommand
            {
                MapId = id,
                FileStream = stream,
                FileName = file.FileName,
                FileSize = file.Length,
                Opacity = opacity,
                Scale = scale,
                Rotation = rotation,
                OffsetX = offsetX,
                OffsetY = offsetY
            }, cancellationToken);

            return Ok(response.Message);
        }

        /// <summary>
        /// 获取地图文件信息
        /// @author zzy
        /// </summary>
        /// <param name="id">地图ID</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpGet("{id}/file")]
        public async Task<IActionResult> GetMapFile(string id, CancellationToken cancellationToken = default)
        {
            if (!Guid.TryParse(id, out Guid mapId))
            {
                return BadRequest(ApiResponse.Failed("无效的地图ID格式", StatusCodes.Status400BadRequest));
            }

            var mapFiles = await _mapFileRepository.FindAsync(
                x => x.MapId == mapId && x.Active,
                cancellationToken);

            var mapFile = mapFiles.FirstOrDefault();

            if (mapFile == null)
            {
                return Ok(ApiResponse<object>.Successful(null, "未找到地图文件"));
            }

            // 构建完整的文件访问URL
            var scheme = Request.Scheme; // http 或 https
            var host = Request.Host.Value; // localhost:5000
            var relativePath = mapFile.FilePath.Replace("\\", "/");
            var fileUrl = $"{scheme}://{host}/uploads/{relativePath}";

            var result = new
            {
                fileName = mapFile.FileName,
                filePath = relativePath, // 保留相对路径
                fileUrl = fileUrl, // 完整访问URL
                fileSize = mapFile.FileSize,
                opacity = mapFile.Opacity,
                scale = mapFile.Scale,
                rotation = mapFile.Rotation,
                offsetX = mapFile.OffsetX,
                offsetY = mapFile.OffsetY,
                uploadTime = mapFile.UploadTime
            };

            return Ok(ApiResponse<object>.Successful(result, "获取成功"));
        }

        /// <summary>
        /// 删除地图背景图文件
        /// </summary>
        /// <param name="id">地图ID</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        [HttpPost("{id}/file")]
        public async Task<IActionResult> DeleteMapFile(string id, CancellationToken cancellationToken = default)
        {
            if (!Guid.TryParse(id, out Guid mapId))
            {
                return BadRequest(ApiResponse.Failed("无效的地图ID格式", StatusCodes.Status400BadRequest));
            }

            var client = _mediator.CreateRequestClient<DeleteMapFileCommand>();
            var response = await client.GetResponse<ApiResponse>(new DeleteMapFileCommand
            {
                MapId = mapId
            }, cancellationToken);

            return Ok(response.Message);
        }
    }
}