layui数据表单怎么写出此效果?

问题遇到的现象和发生背景

img

img

获取页面固定五行空数据行,然后鼠标移入序号列,序号变为加减按钮,点击加则动态添加一行空数据,反之,则减;

还有鼠标移入则会有伪类属性,input输入框还有选择商品按钮则会显示出来,在点击输入框出现光标,则会有隐藏下拉菜单弹出,然后选择一项,后面的数据内容则会回填;

点击选择商品则会有模态框弹出;

我想要解答思路和方法(最好有代码,用JQ写更好)
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
        <link rel="stylesheet" href="//unpkg.com/layui@2.6.8/dist/css/layui.css">
        <style>
            .layui-table-cell .btn {
                display: none;
            }
            .layui-table-cell:hover .index {
                display: none;
            }
            .layui-table-cell:hover .btn {
                display: block;
            }
            .layui-table-cell .layui-input-inline {
                display: none;
                align-items: center;
            }
            .layui-table-cell .layui-input-inline.active,
            .layui-table-cell:hover .layui-input-inline {
                display: flex;
            }
            .layui-table-cell .layui-input-inline > input {
                height: 28px;
                margin-right: 4px;
            }
            .layui-table-cell .layui-input-inline > a {
                color: #145eff;
            }
            .layui-table-cell .layui-input-inline > a:hover {
                opacity: .8;
            }
            #goodsLayer {
                display: none;
            }
            #goodsSelector {
                position: absolute;
                background-color: #fff;
                box-shadow: 0 2px 4px rgba(0, 0, 0, .2);
                display: none;
            }
            #goodsSelector li {
                cursor: pointer;
                padding: 0 10px;
                line-height: 36px;
                white-space: nowrap;
                overflow: hidden;
                text-overflow: ellipsis;
            }
            #goodsSelector li:hover {
                background-color: #5fb878;
                color: #fff;
            }
        </style>
    </head>
    <body>
        <table id="table" lay-filter="table"></table>
        <!-- 选择商品层 -->
        <div id="goodsLayer">
            <table id="goodsTable" lay-filter="goodsTable"></table>
        </div>
        <div id="goodsSelector" class="goods-selector">
            <ul id="selectUl">
                <script id="selectLi" type="text/html">
                    {{#  layui.each(d, function(index, item){ }}
                        <li data-code="{{item.code}}">{{item.name}}</li>
                      {{#  }); }}
                </script>
            </ul>
        </div>
        <script src="https://cdn.bootcdn.net/ajax/libs/layui/2.6.8/layui.min.js"></script>
        <script>
            layui.use(['jquery', 'table', 'layer', 'laytpl'], function(){
                let $ = layui.jquery,
                    table = layui.table,
                    layer = layui.layer,
                    laytpl = layui.laytpl
                
                const data = [
                    { serialNum: '', name: '', code: null},
                    { serialNum: '', name: '', code: null},
                    { serialNum: '', name: '', code: null},
                    { serialNum: '', name: '', code: null},
                    { serialNum: '', name: '', code: null}
                ]
                const emptyData = { serialNum: '', name: '', code: null}
                const searchData = [
                    { serialNum: 'SP121', name: '篮球', code: 001 },
                    { serialNum: 'SP122', name: '足球', code: 002 },
                    { serialNum: 'SP123', name: '平板', code: 003 },
                    { serialNum: 'SP124', name: '手机', code: 004 },
                    { serialNum: 'SP125', name: '耳机', code: 005 }
                ]
                // 渲染table
                table.render({
                    elem: '#table',
                    height: 312,
                    data: data,
                    page: true,
                    cols: [[
                        { title: '序号', width: 100, align: 'center', templet: function(e) {
                            return '<span class="index">'+ e.LAY_INDEX +'</span>'
                                    +'<div class="btn">'
                                        +'<button class="layui-btn layui-btn-primary layui-btn-xs" lay-event="add">+</button>'
                                        +'<button class="layui-btn layui-btn-primary layui-btn-xs" lay-event="remove">-</button>'
                                    +'</div>'
                        } },
                        { field: 'name', title: '商品名称', width: 300, templet: function(e) {
                            const active = e.name ? 'active' : ''
                            return '<div class="layui-input-inline add-input-'+ e.LAY_INDEX +' '+ active +'" lay-event="handelSelect">'
                                        +'<input class="layui-input" value="'+ e.name +'" lay-event="selectGoods" />'
                                        +'<a class="" href="javascript:;" lay-event="addGoods">添加商品</a>'
                                    +'</div>'
                        } },
                        { field: 'serialNum', title: '商品编号' },
                        { field: 'code', title: '条形码', width:80 }
                    ]]
                })
                let dataIndex = null
                let curItem = null
                // 行内点击事件
                table.on('tool(table)', function(obj) {
                    const layEvent = obj.event
                    dataIndex = Number($(obj.tr[0]).attr('data-index'))
                    // 获取add-input盒子距离x,y 加上高度
                    const x = $('.add-input-'+ (dataIndex+1) +'')[0].getBoundingClientRect().x + 'px'
                    const y = $('.add-input-'+ (dataIndex+1) +'')[0].getBoundingClientRect().y + 28 + 'px'
                    switch(obj.event) {
                        case 'add':
                            data.splice(dataIndex + 1, 0, emptyData)
                            table.reload('table', {
                                data: data
                            })
                        break
                        case 'remove':
                            layer.confirm('确认删除当前行吗?', function(index){
                                data.splice(dataIndex, 1)
                                layer.close(index)
                                table.reload('table', {
                                    data: data
                                })
                            })
                        break
                        case 'handelSelect':
                            // 点击添加 active 让当前点击选择一直显示
                            $(obj.tr).find('.layui-input-inline').addClass('active')
                        break
                        case 'selectGoods':
                            const width = $('.add-input-'+ (Number(dataIndex)+1) +'').find('.layui-input').innerWidth()
                            $('#goodsSelector').css({
                                top: y,
                                left: x,
                                width: width,
                                display: 'block'
                            })
                        break
                        case 'addGoods':
                            layer.open({
                                type: 1,
                                title: false,
                                shade: 0.1,
                                offset: [y, x],
                                content: $('#goodsLayer'),
                                btn: ['确定', '取消'],
                                yes: function(index, layero) {
                                    layer.close(index)
                                    renderSelTable(dataIndex, checkData)
                                },
                                end: function(index, layero) {
                                    // 选框关闭没有选择,隐藏添加商品
                                    !obj.data.name && $(obj.tr).find('.layui-input-inline').removeClass('active')
                                }
                            })
                        break
                    }
                })
                
                
                // 渲染下拉列表
                var getTpl = selectLi.innerHTML, view = document.getElementById('selectUl');
                laytpl(getTpl).render(searchData, function(html){
                    view.innerHTML = html;
                });
                // 下拉框选择
                $('#goodsSelector li').click(function() {
                    checkData = searchData[$(this).index()]
                    renderSelTable(dataIndex, checkData)
                    hideSelect()
                })
                
                
                // 渲染选择商品表格
                table.render({
                    elem: '#goodsTable',
                    height: 312,
                    data: searchData,
                    page: true,
                    cols: [[
                        { type: 'radio' },
                        { field: 'name', title: '商品名称', width: 300 },
                        { field: 'serialNum', title: '商品编号' },
                        { field: 'code', title: '条形码', width:80 }
                    ]]
                })
                let checkData = null
                table.on('radio(goodsTable)', function(obj){
                    checkData = obj.data
                })
                // 点击空白处隐藏下拉框
                $(document).click(function(e) {
                    const tClass = $(e.target).attr('class')
                    if (tClass !== 'layui-input') {
                        hideSelect()
                    }
                })
                
                // 渲染选择后的table
                function renderSelTable(dataIndex, checkData) {
                    data[dataIndex] = checkData
                    table.reload('table', {
                        data: data
                    })
                }
                // 隐藏下拉框
                function hideSelect() {
                    $('#goodsSelector').css('display', 'none')
                    // 下拉框没有选择,隐藏添加商品
                    const value = $('.add-input-'+ (dataIndex+1) +'').find('.layui-input').val()
                    console.log(value)
                    !value && $('.add-input-'+ (dataIndex+1) +'').removeClass('active')
                }
            })
        </script>
    </body>
</html>