预计所需阅读时间:10分钟

之前修改的商城订单列表页是这样的:

order_list

做完了列表页面,然后加了取消订单的功能,这个用的方法就比较简单,每个订单对应的取消按钮绑定一个链接,发送Post请求到后台的视图函数,然后改变订单状态为“已取消”,然后返回json到前端,JS来修改网页状态即可。

如果是修改订单、端口、用户、文章这些功能,一般都会跳转到另外的修改页面去修改。但这次我想用modal模态窗口实现发货功能,在弹出来的模态窗口上填写物流公司与物流订单号码。

这个依照Bootstrap4前端框架的规则很快就添加上了,然后为编写对应的视图函数和Javascript的。但是,发现这个功能差没有生效。第一原因,是多个订单使用同一个模太窗口,传到后台的数据无法一一对应。于是用模版语法生成多个模态窗口:

{% for order in pagination.items %}
    <div class="modal fade" id="sendOrder_{{ order.id }}" tabindex="-1" role="dialog"
         aria-labelledby="exampleModalLabel"
         aria-hidden="true">
        <div class="modal-dialog" role="document">
            <div class="modal-content">
                <div class="modal-header">
                    <h5 class="modal-title" id="exampleModalLabel">物流信息</h5>
                    <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                        <span aria-hidden="true">&times;</span>
                    </button>
                </div>
                <div class="modal-body">
                    <p class="d-none" id="orderId_{{ order.id }}">{{ order.id }}</p>
                    <div class="form-group">
                        <label for="logis_company_{{ order.id }}">物流公司:</label>
                        <input class="form-control logis_company" type="text" id="logis_company_{{ order.id }}"
                               placeholder="请填写公司名称">
                    </div>
                    <div class="form-group">
                        <label for="logis_number_{{ order.id }}">物流单号:</label>
                        <input class="form-control logis_number" type="text" id="logis_number_{{ order.id }}"
                               placeholder="请填写物流订单号码">
                    </div>
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
                    <button type="button" id="logis_save_{{ order.id }}" class="btn btn-primary logis_save"
                    >保存
                    </button>
                </div>
            </div>
        </div>
    </div>
{% endfor %}

// 发货按钮也要在一下模版的循环语法之内
<button type="button" class="btn btn-info btn-sm btn-primary logis_send"
    data-toggle="modal" data-remote="{{ order.id }}"
    data-target="#sendOrder_{{ order.id }}">
    发货
</button>

不同的发货按钮对应不同的模态窗口,也有不同的ID,虽然它们看起来窗口的界面是一样的。

但是,即使这样,我调了JS很久也无法将填写好物流信息发送到到后台的视图函数,经过一番思考,没实现功能的第二个原因是订单号没有变成一个Javascript变量,用一个JS函数来处理,再传到后台。因为不同的模态窗口之中的保存按钮是不同。如果用$('.logis_save').on("click", function (event) {...}的方式来选择按钮并绑定点击事件,这样是选择到了多个按钮,但实际要估的事件是不一样的——给不同的订单发货,所以不同的按钮要绑定不同的事件。当然,如果您有更高明的方法和思路也欢迎指出来。

于是我再用模版语法的循环写了不同的JS函数,对应不同的保存按钮的功能:

// 提交物流信息
{% for order in pagination.items %}
    $(function () {
        $("#logis_save_{{ order.id }}").on("click", function (event) {
            console.log("{{ order.id }}_ok")
            logis_company = $("#logis_company_{{ order.id }}").val()
            logis_number = $("#logis_number_{{ order.id }}").val()
            url = "/admin/order/logis_edit/" + {{ order.id }}
                console.log(logis_company, logis_number, url)
            if (logis_company == "") {
                $("#logis_company_{{ order.id }}").focus()
                return false
            }
            if (logis_number == "") {
                $("#logis_number_{{ order.id }}").focus()
                return false
            }

            $.ajax({
                type: "post",
                url: url,
                data: {
                    'logis_company': logis_company,
                    'logis_number': logis_number,
                },
                dataType: "json",
                beforeSend: function (xhr) {
                    xhr.setRequestHeader("X-CSRFToken", csrf_token)
                },
                success: function (data) {
                    $("#logis_company_{{ order.id }}").val("")
                    $("#logis_number_{{ order.id }}").val("")
                    if (data.result == "saved") {
                        window.location.reload()
                    }
                }
            })
        })
    })
{% endfor %}

不用的模态窗口意味它们有不同的表单,用logis_number = $("#logis_number_{{ order.id }}").val()来获取不同的物流单号。如果没有填写对应的信息,则用$("#logis_number_{{ order.id }}").focus()设为焦点,让使用者补充完物流信息。

这样,最终在Flask框架里,在订单列表页面用modal模态窗口实现了发货功能。