Easyui 实现订单拆分开票功能

Easyui 实现订单拆分开票功能

需求

1、实现一个订单开具多分发票功能;

2、支持拆行;

3、支持拆数量;

流程设计

1、操作页面展示订订单头信息,订单明细信息

2、点击新增发票按钮弹出一个弹出框用于创建一张拆分发票,弹出框可以选择商品明细输入数量。每次添加一张

3、点击弹出框的保存功能实现订单拆分

4、提交到后台之后,生成多张发票

页面设计依次如下




核心代码如下

html 复制代码
<!-- 新增发票按钮-->
<span class="span_title"><a href="javascript:void(0)" style="color: red;font-weight: bold" onclick="addTicketDialog()">新增发票</a></span>

<!-- tablesContainer为添加发票的容器 -->
<div id="extInfoBtn" class="div_detail_margin_left_right div_button div_button_detail">
    <div class="div_button_title">
        <span id="extInfoTitle" class="spanTitleImgOpen" onClick="hideshow('extInfo','extInfoTitle','divExtInfoBtn')"/>
    </div>
    <div class="div_button_title">
        <span class="span_title">开票明细</span>
    </div>
</div>
<div id="extInfo" class="div_detail_margin_left_right">
    <div style="margin-top:10px;margin-bottom:10px;">
        <div id="tablesContainer" >

        </div>

    </div>
</div>

<!-- 弹出框 -->
<div id="addDialog" class="easyui-dialog" style="width:70%;height:500px" data-options="title:'拆分开票',toolbar:'#addToolbar',buttons:'#bb',modal:true,closed: true">
    <table class="easyui-datagrid" id="addTable" style="width:100%;height:365px;"
           data-options="singleSelect:true,collapsible:true,fitColumns:true">
        <thead>
        <tr>
            <th data-options="field:'id',width:80" formatter="formatOpt">操作</th>
            <th data-options="field:'customerLineItem',width:80">项目行号</th>
            <th data-options="field:'taxCode',width:120" formatter="formatTaxCode">税收编码</th>
            <th data-options="field:'projectName',width:300" formatter="formatterProjectName">商品发票名称</th>
            <th data-options="field:'model',width:120" formatter="formatterModel">发票型号</th>
            <th data-options="field:'quantity',width:50,align:'right'">订单数量</th>
            <th data-options="field:'thisTimeQuantity',width:50,align:'right'">本次开票数量</th>
            <th data-options="field:'productUnit',width:50">单位</th>
            <th data-options="field:'feeSku',width:80,align:'right'">含税单价</th>
            <th data-options="field:'tax',width:80,align:'right'" formatter="formatterTax">税率</th>
            <th data-options="field:'feeTotal',width:80">含税总价</th>
        </tr>
        </thead>
    </table>
    <div id="addRemark" style="padding:2px 5px;">
        开票栏备注: <input class="easyui-textbox" id="remark" class="remark" name="remark" style="width:90%">
    </div>
</div>
<div id="bb" style="font-size: 12px;">
    <div style="float: left">
        订单金额:<input id="orderAmount" class="easyui-textbox" disabled/>
        发票金额:<input id="invoiceAmount" class="easyui-textbox" disabled/>
    </div>

    <a href="javascript:void(0)" onclick="saveOne()" class="easyui-linkbutton">保存</a>
    <a href="javascript:void(0)" class="easyui-linkbutton">关闭</a>
</div>
<div id="addToolbar" style="padding:2px 5px;font-size: 12px;">
    开票商品: <select class="easyui-combobox" id="addItem" style="width:300px"></select>
    可开票数量: <input class="easyui-numberbox" id="maxQty" disabled panelHeight="auto" style="width:110px"></input>
    本次开票数量: <input class="easyui-numberbox" id="quantity" name="qty" style="width:110px" data-options="min:0,precision:0"/>
    <a href="javascript:void(0)" class="easyui-linkbutton" onclick="addRow()" iconCls="icon-add">添加</a>
</div>

js核心代码

javascript 复制代码
 /*新增发票编辑窗口*/
function addTicketDialog(){
    endEdit();
    orderItems = $('#detailTable').datagrid('getRows');
    orderItems = orderItems.map(item => ({...item, leftQuantity: item.quantity }));
    // 设置值
    $('#addItem').combobox({
        valueField: 'customerLineItem',
        textField: 'projectName',
        data:orderItems,
        panelHeight:'auto',
        onSelect:handleOnSelect
    });
    $("#orderAmount").textbox('setValue',invoice.orderFee)
    $('#addDialog').dialog('open');
}


function handleOnSelect(rec){
    $('#maxQty').numberbox('setValue',rec.leftQuantity);
    $('#quantity').numberbox({ max:rec.leftQuantity });
    selectedRow = rec
}

/*添加行*/
function addRow(){
    let dg = $('#addTable');
    let rows = dg.datagrid('getRows');
    let thisTimeQuantity = $('#quantity').numberbox('getValue');
    if(thisTimeQuantity == null || thisTimeQuantity == 0){
        $.messager.alert('操作提示','请输入本次开票数量','info')
        return;
    }

    if(rows.some(item => item.itemId === selectedRow.itemId)){
        $.messager.alert('操作提示','此商品已添加,如需修改数量请删除后重新添加','info')
        return;
    }

    selectedRow.thisTimeQuantity = thisTimeQuantity
    selectedRow.thisTimeAmount = thisTimeQuantity * selectedRow.feeSku
    selectedRow.leftQuantity = selectedRow.leftQuantity - thisTimeQuantity
    // 插入行
    dg.datagrid('insertRow',{
        index:rows.length+1,
        row:selectedRow
    });

    // 设置发票金额
    rows = dg.datagrid('getRows');
    let invoiceAmount = rows.reduce((acc, current) => acc + current.feeSku * current.thisTimeQuantity, 0)
    $("#invoiceAmount").textbox('setValue',invoiceAmount)

    // 更新列表展示
    $('#detailTable').datagrid('loadData',orderItems);
}

/*删除行*/
function deleteRow(index){
    let dg = $('#addTable');
    // 从数据源中删除该行数据
    let dataSource = dg.datagrid('getData');
    let deleteOne = dataSource.rows[index]
    updateOrderItems(deleteOne,true);
    dataSource.rows.splice(index, 1);
    dg.datagrid('loadData', dataSource);
    // 重新设置formatter相关逻辑,更新索引
    dg.datagrid('getColumnOption', 'id').formatter = function(value, row, index){
        return '<a href="javascript:void(0)" οnclick="deleteRow('+index+')"><font color="blue" style="text-decoration:underline">删除</font></a> ';
    };
    $('#detailTable').datagrid('loadData',orderItems);
}


function updateOrderItems(one,isAdd){
    let newArray = [];
    for(let i=0;i<orderItems.length;i++){
        let item = orderItems[i]
        if(one.itemId === item.itemId){
            if(isAdd){
                item.leftQuantity = item.leftQuantity + one.thisTimeQuantity
            }else{
                item.leftQuantity = item.leftQuantity - one.thisTimeQuantity
            }
        }
        newArray.push(item)
    }
    orderItems = newArray;
}

/**保存一个**/
function saveOne(){

    let dg = $('#addTable');
    // 从数据源中删除该行数据
    let dataSource = dg.datagrid('getRows');

    if(dataSource === null || dataSource.length ===0){
        $.messager.alert('操作提示','请您添加开票明细!','info')
        return;
    }

    //获取数据
    let one = {}
    one.id = splitList.length;
    one.items = dataSource
    one.remark = $('#remark').textbox('getValue');
    splitList.push(one);

    // 清除数据
    dg.datagrid('loadData', []);
    drewTables();

    // 清空内容
    $('#remark').textbox('setValue','')
    $('#quantity').numberbox('setValue',null)

    $('#addDialog').dialog('close');
}

/**绘制表格**/
function drewTables(){

    let container = $('#tablesContainer');
    container.empty();
    if(splitList.length ===0){
        return;
    }

    for(let i=0;i<splitList.length;i++){
        let one = splitList[i];
        let j = i+1;
        let mainDivStart = '<div  id="ip-'+i+'" style="margin-bottom: 10px;border: 1px solid #cccccc;padding: 2px;">'
        let deleteButton = '发票'+j+' <span style="color: red;font-weight: bold;cursor: pointer" οnclick="removeInvoice('+i+')">删除此发票</span>'
        let table = '<table class="easyui-datagrid" id="ip-table-'+i+'" style="width:100%;" data-options="singleSelect:true,collapsible:true,fitColumns:true">'
     +       '<thead>'
     +       '<tr>'
     +       '<th data-options="field:\'customerLineItem\',width:80">项目行号</th>'
     +   '<th data-options="field:\'skuCodeProj\',width:150">项目商品编码</th>'
     +   '<th data-options="field:\'skuNameProj\',width:300">商品名称</th>'
     +   '<th data-options="field:\'specificationInvoice\',width:120">商品型号</th>'
     +   '<th data-options="field:\'taxCode\',width:120" formatter="formatTaxCode">税收编码</th>'
     +   '<th data-options="field:\'projectName\',width:300" formatter="formatterProjectName">商品发票名称</th>'
     +   '<th data-options="field:\'model\',width:120" formatter="formatterModel">发票型号</th>'
     +   '<th data-options="field:\'thisTimeQuantity\',width:50,align:\'right\'">数量</th>'
     +   '<th data-options="field:\'productUnit\',width:50">单位</th>'
     +   '<th data-options="field:\'feeSku\',width:80,align:\'right\'">含税单价</th>'
     +   '<th data-options="field:\'tax\',width:80,align:\'right\'" formatter="formatterTax">税率</th>'
     +   '<th data-options="field:\'thisTimeAmount\',width:80">含税总价</th>'
    +'</tr>'
    +'</thead>'
    +'</table>'
        let remark = '<div style="padding:2px 5px;">开票栏备注: <input class="easyui-textbox" class="remark" disabled name="remark" value="'+one.remark+'" style="width:90%"></div>'
        let mainDivEnd = '</div>'
        let $allHtml = mainDivStart + deleteButton + table + remark + mainDivEnd
        container.append($allHtml);
        let oneTable = $('#ip-table-' + i);
        oneTable.datagrid({ data:one.items });
    }
}

function removeInvoice(index){
    // 删除元素
    $.messager.confirm('删除提示', '您确认要删除此发票吗?', function(r){
        if (r){
            splitList.splice(index, 1);

            let newArray = []
            for(let i=0;i<splitList.length;i++){
                let one = splitList[i];
                one.id = i
                newArray.push(one)
            }
            splitList = newArray;
            //重新渲染
            drewTables();
        }
    });


}

function endEdit(){
    // 取消编辑
    if (lastIndex !== null) {
        $('#detailTable').datagrid('endEdit', lastIndex);
        lastIndex = null;
    }
}

总结

此方案的优势就是在单独弹出框处理拆分,然后动态的渲染表格,新增一个表格然后再表格中进行行编辑要简单许多

相关推荐
腾讯TNTWeb前端团队6 小时前
helux v5 发布了,像pinia一样优雅地管理你的react状态吧
前端·javascript·react.js
范文杰10 小时前
AI 时代如何更高效开发前端组件?21st.dev 给了一种答案
前端·ai编程
拉不动的猪10 小时前
刷刷题50(常见的js数据通信与渲染问题)
前端·javascript·面试
拉不动的猪10 小时前
JS多线程Webworks中的几种实战场景演示
前端·javascript·面试
FreeCultureBoy11 小时前
macOS 命令行 原生挂载 webdav 方法
前端
uhakadotcom11 小时前
Astro 框架:快速构建内容驱动型网站的利器
前端·javascript·面试
uhakadotcom11 小时前
了解Nest.js和Next.js:如何选择合适的框架
前端·javascript·面试
uhakadotcom12 小时前
React与Next.js:基础知识及应用场景
前端·面试·github
uhakadotcom12 小时前
Remix 框架:性能与易用性的完美结合
前端·javascript·面试
uhakadotcom12 小时前
Node.js 包管理器:npm vs pnpm
前端·javascript·面试