You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在ASP.NET Core Razor页面中实现地图实时订单配送位置追踪?

实现ASP.NET Core Razor页面订单实时位置追踪方案

核心逻辑

整个功能分为三个关键环节:

  • 配送端(如骑手APP)定时上报当前位置到后端
  • 后端接收并存储位置数据,同时支持实时推送或查询
  • 前端Razor页面获取位置数据,在地图上渲染并更新

后端实现

1. 定义数据实体

用EF Core创建订单和位置存储模型:

public class Order
{
    public int Id { get; set; }
    public string CustomerId { get; set; }
    public OrderStatus Status { get; set; }
    // 其他订单字段(如收货人、地址等)
}

public class DeliveryLocation
{
    public int Id { get; set; }
    public int OrderId { get; set; }
    public decimal Longitude { get; set; }
    public decimal Latitude { get; set; }
    public DateTime UpdateTime { get; set; }

    public Order Order { get; set; }
}

public enum OrderStatus
{
    Processing,
    Delivering,
    Completed
}

2. 位置上报API

创建API控制器接收配送端的位置请求:

[ApiController]
[Route("api/delivery")]
public class DeliveryController : ControllerBase
{
    private readonly AppDbContext _dbContext;
    private readonly IHubContext<LocationHub> _hubContext;

    public DeliveryController(AppDbContext dbContext, IHubContext<LocationHub> hubContext)
    {
        _dbContext = dbContext;
        _hubContext = hubContext;
    }

    [HttpPost("location")]
    public async Task<IActionResult> UpdateLocation([FromBody] LocationUpdateRequest request)
    {
        // 验证订单有效性
        var order = await _dbContext.Orders.FindAsync(request.OrderId);
        if (order == null || order.Status != OrderStatus.Delivering)
            return BadRequest("无效订单或当前不处于配送状态");

        // 存储最新位置
        var location = new DeliveryLocation
        {
            OrderId = request.OrderId,
            Longitude = request.Longitude,
            Latitude = request.Latitude,
            UpdateTime = DateTime.UtcNow
        };
        _dbContext.DeliveryLocations.Add(location);
        await _dbContext.SaveChangesAsync();

        // 通过SignalR推送给对应订单的客户
        await _hubContext.Clients.Group($"Order_{request.OrderId}")
            .SendAsync("ReceiveLocationUpdate", new
            {
                Longitude = request.Longitude,
                Latitude = request.Latitude,
                UpdateTime = location.UpdateTime
            });

        return Ok();
    }
}

public class LocationUpdateRequest
{
    public int OrderId { get; set; }
    public decimal Longitude { get; set; }
    public decimal Latitude { get; set; }
}

3. SignalR实时推送配置

如果需要低延迟的实时更新,配置SignalR服务:

// Program.cs
builder.Services.AddSignalR();

app.MapHub<LocationHub>("/locationHub");

创建SignalR Hub类:

public class LocationHub : Hub
{
    public async Task JoinOrderGroup(int orderId)
    {
        await Groups.AddToGroupAsync(Context.ConnectionId, $"Order_{orderId}");
    }
}

前端Razor页面实现

1. 页面结构(带地图容器)

@page "/orders/track/{orderId:int}"
@model TrackOrderModel

<div class="container mt-4">
    <h3>订单实时追踪</h3>
    <div id="map" style="width: 100%; height: 600px; border-radius: 8px;"></div>
</div>

2. JavaScript逻辑(SignalR+地图渲染)

@section Scripts {
    <script src="https://webapi.amap.com/maps?v=1.4.15&key=你的高德地图API密钥"></script>
    <script src="/js/signalr/dist/browser/signalr.js"></script>

    <script>
        const orderId = @Model.OrderId;
        let map, marker;

        // 初始化地图
        function initMap() {
            map = new AMap.Map('map', {
                zoom: 15,
                resizeEnable: true
            });
            // 获取初始位置
            fetch(`/api/orders/${orderId}/latest-location`)
                .then(res => res.json())
                .then(data => {
                    if (data) updateMarker(data.longitude, data.latitude);
                });
        }

        // 更新地图标记位置
        function updateMarker(lng, lat) {
            const position = new AMap.LngLat(lng, lat);
            if (!marker) {
                marker = new AMap.Marker({ position });
                map.add(marker);
                map.setCenter(position);
            } else {
                marker.setPosition(position);
                map.setCenter(position);
            }
        }

        // 连接SignalR接收实时更新
        const connection = new signalR.HubConnectionBuilder()
            .withUrl("/locationHub")
            .build();

        connection.on("ReceiveLocationUpdate", (data) => {
            updateMarker(data.longitude, data.latitude);
        });

        connection.start()
            .then(() => connection.invoke("JoinOrderGroup", orderId))
            .catch(err => console.error(err));

        window.onload = initMap;
    </script>
}

3. Razor页面模型(权限验证)

public class TrackOrderModel : PageModel
{
    private readonly AppDbContext _dbContext;
    public int OrderId { get; set; }

    public TrackOrderModel(AppDbContext dbContext)
    {
        _dbContext = dbContext;
    }

    public async Task<IActionResult> OnGet(int orderId)
    {
        // 验证当前用户是订单所属客户
        var order = await _dbContext.Orders.FirstOrDefaultAsync(o => 
            o.Id == orderId && o.CustomerId == User.Identity.Name);
        
        if (order == null || order.Status != OrderStatus.Delivering)
            return NotFound();

        OrderId = orderId;
        return Page();
    }
}

可选方案:轮询(无SignalR场景)

如果不需要低延迟,用简单轮询替代SignalR:

// 替换SignalR相关代码
setInterval(() => {
    fetch(`/api/orders/${orderId}/latest-location`)
        .then(res => res.json())
        .then(data => {
            if (data) updateMarker(data.longitude, data.latitude);
        });
}, 5000); // 每5秒查询一次最新位置

关键注意事项

  • 权限控制:必须验证访问用户是订单的所属客户,防止位置信息泄露
  • 数据优化:用Redis缓存每个订单的最新位置,减少数据库查询压力;定期归档历史位置数据
  • 异常处理:前端需处理网络异常、后端返回错误的情况,给用户友好提示
  • 地图服务:可根据需求选择高德、百度或谷歌地图JS API,注意申请合法的API密钥

内容的提问来源于stack exchange,提问作者Amal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 12:20:39