【Side Project】 (顾客)订单UX功能实作

我们已经可以从顾客填写菜单、成立订单、一直到将订单送到老板手上。
这篇开始要来处理顾客填写订单时UX上的功能实作,
让客户觉得网页版菜单更加亲民一点。

为了方便,开始前先附上Customer.cshtml HTML部分的程序码


<div>
    <p>这是顾客-点菜单</p>
</div>
<div>

    <table id="menu"
           class="table table-bordered table-warning">
        <thead>
            <tr class="table-active">
                <th colspan="3" class="text-center "><h1>店名</h1></th>
            </tr>
            <tr class="table-light">
                <th data-field="item">品名</th>
                <th data-field="price">单价</th>
                <th data-field="count">数量</th>
            </tr>
        </thead>
        <tbody id="menu_body">
            
        </tbody>
        <tfoot>
            <tr>
                <td colspan="2"></td>
                <th class="bg-warning">小计</th>
            </tr>
            <tr>
                <td colspan="2" >
                    <div class="input-group flex-nowrap">
                        <span class="input-group-text" id="phoneText">手机</span>
                        <input type="text" id="phoneNum" class="form-control" maxlength="10" onkeyup="value = value.replace(/[^\d]/g,'')" placeholder="手机号码" aria-label="phoneNumber" aria-describedby="phoneText">
                    </div>
                </td>
                
                <th class="bg-warning" id="total_price">0</th>
            </tr>
            <tr>
                <td colspan="2"></td>
                <td>
                    <button id="submitBtn" type="button" class="btn btn-primary">
                        送出
                    </button>
                </td>
            </tr>
        </tfoot>
    </table>
    <input id="menu_data" style="visibility:hidden" [email protected] />
</div>
<!-- 送出後的弹出视窗 -->
<div class="modal fade" id="commitModal" tabindex="-1" role="dialog" aria-labelledby="commitModalTitle" aria-hidden="true">
    <div class="modal-dialog modal-dialog-centered" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title" id="commitModalTitle">店名</h5>
                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                    <span aria-hidden="true">×</span>
                </button>
            </div>
            <div class="modal-body">
                您已经成功订餐
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-secondary" data-dismiss="modal" >关闭</button>
            </div>
        </div>
    </div>
</div>

清空订单资讯

当完成订单之後,将原本的资讯删除,
方便顾客需要填写新的单子。

  1. 打开 Customer.cshtml
  2. 新增count的name属性
function addItemRow(uid, item, price) {
        var data = `
            <tr id=uid`+ uid + `>
                <td class="item"> `+ item + `</td>
                <td class="price">`+ price + `</td>
                <td class="count">
                    <div class="input-group mb-3">
                      <input type="text" class="form-control" placeholder="" aria-label="Count" name="item_count"  value="0">
                    </div>
                </td>
            </tr>
`
        $('#menu_body').append(data);
        
    }

为了等一下方便取得元素,给count里面的input一个名字。

  1. 修改ajax中 success部分的程序码
success: function (data) {
            //清空资讯
            $("#phoneNum").val('')
            $("input[name='item_count']").val('0')
            $("#total_price").text('0')
            //开启互动视窗
            $("#commitModal").modal('show')
            

        }

这边要注意要使用的是val()而不是text()

电话号码验证

电话号码的验证我们这边暂时就先简单的只规定最大值10个以内数字即可。
我们直接在input上面来绑定事件。

<input type="text" id="phoneNum" class="form-control" maxlength="10" onkeyup="value = value.replace(/[^\d]/g,'')" placeholder="手机号码" aria-label="phoneNumber" aria-describedby="phoneText">

当按键弹起的时候onkeyup()我们就将数字以外的字元删除,
在帮我们的最大长度maxlength设定为10

小计计算

  1. 新增 onchange事件
$('#menu_body').on("change", 'input[name="item_count"]', function () {
        calculate_price()
    });

这边要注意一点,我们input是动态生成的,所以这边也需要用动态的方式绑定事件。
2. 新增 calculate_price()

function calculate_price() {
        
        var total_price = 0
        $("#menu_body > tr").each(function () {

            var count = $(this).children(".count").children("div").children("input").val()

            if (count > 0) {//有点餐的才计算

                item = $(this).children(".item").text()
                price = $(this).children(".price").text()
                total_price = total_price + (count * price)
            }

        })
        $("#total_price").text(total_price)
    }

每当顾客修改数量的时候,就会即时的帮忙计算价钱。

结语

有些人可能会问,为什麽这些功能要留到现在才做开发?
我想有一点开发经验的小夥伴应该有遇过,
有一些比较没有经验的PM(或是一些接触客户的职位)三不五时就会拿着客户的需求来问说,
能不能顺便加这个功能,加来加去,到最後才发现跟预想的不一样通通都重来。

之所以把这些功能放在後面处理是因为,在没有任何实体东西出来的时候,
构想出来的所有东西都只是脑中的经验告诉你的,
当经验又不足够时,很容易变成写10行改8行。
花大量的时间在修修补补上,这样的方式倒不如直接一开始就走最简单的道路,
先一路通往终点後,再回头审视应该要怎麽添加其他功能。

另外如果是客制化开发、多人开发、或是需要与其他夥伴沟通的时候,
也有可能因为大家脑中所构思的东西不同导致方向不同步。
如果是先一次将核心功能完成(能从开始通往结束完整的流程),
再逐步增添功能的方式,就可以减少这样的问题发生。


<<:  【把玩Azure DevOps】Day26 YAML格式以外的Pipeline传统编辑器(Classic Editor)

>>:  Day 23 Password Attacks - 密码攻击 (hydra, pw-inspector)

EIP (OA) 与 BPM 的差异为何?

常有客户问到 EIP (OA)内建的 workflow 与所谓的BPM 有何不同?? 为何两者价格差...

Day 2 ( 入门 ) 螃蟹跑来跑去

螃蟹跑来跑去 教学原文参考:螃蟹跑来跑去 这篇文章会介绍,如何在 Scratch 3 里使用角色移动...

[专案上线第01天] - 新来的主管说要写 Vue Test Utils 单元测试

前言 该系列是为了让看过Vue官方文件或学过Vue但是却不知道怎麽下手去重构现在有的网站而去规画的系...

Day 2 - Vue与MVVM

Vue作为前端三大框架之一,它的重要性已是不可言喻,除此之外,相较於React与Angular,Vu...

【day1】豚花돈꽃韩式料理三访

在近三个月的防疫禁止内用期间 最想念的食物之一就是韩式烤肉了 (不用自己动手烤的那一种) 这家豚花돈...