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

Razor Page中JS实现下拉联动填充面板费用及计算欠款

问题描述

我正在开发一个包含Client表、Attendance表和Panel表的ASP.NET应用,在Attendance创建页面需要实现两个功能:

  1. 选择Panel下拉选单后,自动从Panel表获取对应PanelFee填充至只读的PanelCost字段;
  2. 输入AmountPaid后,自动计算并填充AmountOutstanding(公式:PanelCost - AmountPaid)。

目前编写的JavaScript完全不生效:选择Panel后PanelCost无填充,输入AmountPaid后欠款字段也没有计算结果,需要排查并修正。

当前代码片段

Create.cshtml

@model AttendanceCreateModel

<form asp-action="Create">
    <div class="form-group">
        <label asp-for="PanelId" class="control-label"></label>
        <select asp-for="PanelId" asp-items="Model.PanelList" class="form-control"></select>
        <span asp-validation-for="PanelId" class="text-danger"></span>
    </div>
    <div class="form-group">
        <label asp-for="PanelCost" class="control-label"></label>
        <input asp-for="PanelCost" class="form-control" readonly />
        <span asp-validation-for="PanelCost" class="text-danger"></span>
    </div>
    <div class="form-group">
        <label asp-for="AmountPaid" class="control-label"></label>
        <input asp-for="AmountPaid" class="form-control" />
        <span asp-validation-for="AmountPaid" class="text-danger"></span>
    </div>
    <div class="form-group">
        <label asp-for="AmountOutstanding" class="control-label"></label>
        <input asp-for="AmountOutstanding" class="form-control" readonly />
        <span asp-validation-for="AmountOutstanding" class="text-danger"></span>
    </div>
    <div class="form-group">
        <input type="submit" value="Create" class="btn btn-primary" />
    </div>
</form>

@section Scripts {
    @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
    <script>
        $(document).ready(function () {
            $('#PanelId').change(function () {
                var panelId = $(this).val();
                $.get('/Attendance/GetPanelFee/' + panelId, function (data) {
                    $('#PanelCost').val(data);
                });
            });

            $('#AmountPaid').on('input', function () {
                var panelCost = parseFloat($('#PanelCost').val()) || 0;
                var amountPaid = parseFloat($(this).val()) || 0;
                var outstanding = panelCost - amountPaid;
                $('#AmountOutstanding').val(outstanding.toFixed(2));
            });
        });
    </script>
}

CreateModel.cs

public class AttendanceCreateModel : PageModel
{
    private readonly ApplicationDbContext _context;

    public AttendanceCreateModel(ApplicationDbContext context)
    {
        _context = context;
    }

    [BindProperty]
    public Attendance Attendance { get; set; }

    public SelectList PanelList { get; set; }

    public async Task<IActionResult> OnGetAsync()
    {
        var panels = await _context.Panel.Select(p => new { p.Id, p.PanelName }).ToListAsync();
        PanelList = new SelectList(panels, "Id", "PanelName");
        return Page();
    }

    public async Task<IActionResult> OnPostAsync()
    {
        if (!ModelState.IsValid)
        {
            return Page();
        }

        _context.Attendance.Add(Attendance);
        await _context.SaveChangesAsync();

        return RedirectToPage("./Index");
    }

    public async Task<IActionResult> OnGetGetPanelFee(int id)
    {
        var panel = await _context.Panel.FindAsync(id);
        if (panel == null)
        {
            return NotFound();
        }
        return new JsonResult(panel.PanelFee);
    }
}

Panel实体类

public class Panel
{
    public int Id { get; set; }
    public string PanelName { get; set; }
    public decimal PanelFee { get; set; }
    // 其他属性...
}

排查与修正方案

1. 核心问题:DOM选择器不匹配

ASP.NET Core Tag Helper会根据模型层级生成元素ID,你的PanelId、PanelCost等属性属于Attendance绑定对象,实际渲染的ID是Attendance_PanelId、Attendance_PanelCost,而非你JS中写的PanelId。

验证方式:F12打开开发者工具,查看对应元素的ID即可确认。

2. 路由匹配错误

Razor Pages的Handler方法默认路由格式是/页面名?handler=方法名&参数=值,你写的/Attendance/GetPanelFee/xxx无法匹配OnGetGetPanelFee方法。

3. 修正后的完整代码

Create.cshtml 脚本部分

@section Scripts {
    <script src="~/lib/jquery/dist/jquery.min.js"></script>
    @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
    <script>
        $(document).ready(function () {
            // 用实际渲染的ID选择元素
            const panelSelect = $('#Attendance_PanelId');
            const panelCostInput = $('#Attendance_PanelCost');
            const amountPaidInput = $('#Attendance_AmountPaid');
            const outstandingInput = $('#Attendance_AmountOutstanding');

            panelSelect.change(function () {
                const panelId = $(this).val();
                if (!panelId) {
                    panelCostInput.val('');
                    outstandingInput.val('');
                    return;
                }
                // 用Razor Pages标准路由格式请求
                $.get('/Attendance', { handler: 'GetPanelFee', id: panelId }, function (fee) {
                    panelCostInput.val(fee);
                    // 自动触发欠款计算
                    amountPaidInput.trigger('input');
                }).fail(function() {
                    alert('获取Panel费用失败,请重试');
                    panelCostInput.val('');
                });
            });

            amountPaidInput.on('input', function () {
                const panelCost = parseFloat(panelCostInput.val()) || 0;
                const amountPaid = parseFloat($(this).val()) || 0;
                // 避免欠款出现负数
                const outstanding = Math.max(panelCost - amountPaid, 0);
                outstandingInput.val(outstanding.toFixed(2));
            });
        });
    </script>
}

CreateModel.cs Handler优化(可选)

为避免decimal精度丢失,返回时格式化字符串:

public async Task<IActionResult> OnGetGetPanelFee(int id)
{
    var panel = await _context.Panel.FindAsync(id);
    if (panel == null)
    {
        return NotFound("Panel不存在");
    }
    return new JsonResult(panel.PanelFee.ToString("F2"));
}

4. 额外边界处理

  • 下拉框清空时,同步清空费用和欠款字段;
  • 付款金额为空/非数字时,按0计算;
  • 付款超过费用时,欠款显示0而非负数;
  • 添加请求失败的提示,提升用户体验。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 03:44:51