订单编辑

关于在前端js调用Foxtable的基础知识,我们前面已经介绍完毕了,现在开始接触一些具体的例子,第一个例子是一个普通的订单编辑窗口。

本示例可
参考示例文件"CaseStudy\WebViewer\调用Foxtable对象.Table"的窗口"订单编辑"。

本示例完全基于JS实现了订单的编辑、删除、增加、保存和撤销等功能:



所有的代码都在AfterLoad事件中,可以看到代码逻辑和我们之前在Foxtable编程完全一样:

'''Async
Dim
wv As WebViewer = e.Form.Controls("WebViewer1").WebViewer
Await
wv.EnsureCoreWebView2Async(Nothing) '初始化浏览器
wv.CoreWebView2.AddHostObjectToScript(
"Orders", Tables("订单")) '注入订单表
'
定义订单编辑页面
Dim
html As String = <![CDATA[
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>
订单编辑</title>
    <style>
        *{font-size:15px; margin:5px;}
        label{display:inline-block; width:70px; text-align:right;}
        input{padding:6px 8px; width:200px; border:1px solid #ccc; border-radius:4px;}
        button{padding:8px 18px; font-size:14px; margin:8px 5px; cursor:pointer;}
        .btn-box{margin-top:20px;}
    </style>
</head>
<body>
    <h3>
订单表编辑</h3>
    <div>
        <label>
产品:</label><input type="text" id="txtProduct" placeholder="例如:PD01" /><br>
        <label>
客户:</label><input type="text" id="txtCustomer" placeholder="例如:CS03" /><br>
        <label>
雇员:</label><input type="text" id="txtEmployee" placeholder="例如:EP02" /><br>
        <label>
单价:</label><input type="number" id="txtPrice" step="0.01" min="0" placeholder="数值" /><br>
        <label>
折扣:</label><input type="number" id="txtDiscount" step="0.01" min="0" max="1" placeholder="0-1之间的小数" /><br>
        <label>
数量:</label><input type="number" id="txtQty" step="1" min="1" placeholder="整数" /><br>
        <label>
日期:</label><input type="date" id="txtDate" /><br>
    </div>
    <div class="btn-box">
        <button onclick="prevRow()">
上一行</button>
        <button onclick="nextRow()">
下一行</button>
        <button onclick="addRow()">
增加行</button>
        <button onclick="delRow()">
删除行</button>
        <button onclick="cancelEdit()" style="background:#f0ad4e;color:#fff;border:none;">
撤销</button>
        <button onclick="saveRow()" style="background:#5cb85c;color:#fff;border:none;">
保存</button>
    </div>
    <script>
        //
获得订单表
        const Orders = window.chrome.webview.hostObjects.sync.Orders;       

        // 极简工具函数:OADate浮点数转JS可读日期
        function oaToDate(oaDate) {
            const baseDays = 25569;
            return new Date((oaDate - baseDays) * 86400 * 1000);
        }

        //
读取当前行数据到各输入框
        function loadCurrentRowData() {
            const currRow = Orders.Current;
            if(currRow === null){
                //
无当前行,清空所有输入框
                document.getElementById("txtProduct").value = "";
                document.getElementById("txtCustomer").value = "";
                document.getElementById("txtEmployee").value = "";
                document.getElementById("txtPrice").value = "";
                document.getElementById("txtDiscount").value = "";
                document.getElementById("txtQty").value = "";
                document.getElementById("txtDate").value = "";
                return;
            }
            //
有当前行,读取数据写入输入框
            document.getElementById("txtProduct").value = currRow["
产品"];
            document.getElementById("txtCustomer").value = currRow["
客户"];
            document.getElementById("txtEmployee").value = currRow["
雇员"];
            document.getElementById("txtPrice").value = currRow["
单价"];
            document.getElementById("txtDiscount").value = currRow["
折扣"];
            document.getElementById("txtQty").value = currRow["
数量"];
            let dtVal = currRow["
日期"];
            if(dtVal){
                let date =
oaToDate(dtVal); //转为js日期
                document.getElementById("txtDate").value = date.toISOString().split('T')[0];
            }else{
                document.getElementById("txtDate").value = "";
            }
        }
        //
上一行
        function prevRow() {
            let currPos = Orders.Position;
            if (currPos > 0) {
                Orders.Position = currPos - 1;
                loadCurrentRowData();
            }else{
                alert("
已经是第一行!");
            }
        }
        //
下一行
        function nextRow() {
            let currPos = Orders.Position;
            let rowCount = Orders.Count;
            if (currPos < rowCount - 1) {
                Orders.Position = currPos + 1;
                loadCurrentRowData();
            }else{
                alert("
已经是最后一行!");
            }
        }
        //
增加行
        function addRow() {
            Orders.AddNew();
            loadCurrentRowData();
            alert("
新增空白订单行,可直接编辑!");
        }
        //
删除行
        function delRow() {
            const currRow = Orders.Current;
            if(currRow === null){
                alert("
暂无当前订单行,无法删除!");
                return;
            }
            if(confirm("
确定要删除当前订单行吗?")){
                currRow.Delete();
                loadCurrentRowData();
                alert("
当前行已删除!");
            }
        }
        //
撤销编辑
        function cancelEdit() {
            const currRow = Orders.Current;
            if(currRow !== null){
                loadCurrentRowData();
                alert("
已撤销编辑,恢复为当前行原始数据!");
            }
        }
        //
保存
        function saveRow() {
            const currRow = Orders.Current;
            if(currRow === null){
                alert("
暂无当前订单行,无需保存!");
                return;
            }
            try{
                currRow["
产品"] = document.getElementById("txtProduct").value.trim();
                currRow["
客户"] = document.getElementById("txtCustomer").value.trim();
                currRow["
雇员"] = document.getElementById("txtEmployee").value.trim();
                currRow["
单价"] = parseFloat(document.getElementById("txtPrice").value);
                currRow["
折扣"] = parseFloat(document.getElementById("txtDiscount").value);
                currRow["
数量"] = parseInt(document.getElementById("txtQty").value);
                currRow["
日期"] = new Date(document.getElementById("txtDate").value);
                currRow.Save();
                alert("
当前订单数据保存成功!");
            }catch(err){
                alert("
保存失败:" + err.message);
            }
        }
        //
从当前行加载数据到输入框
        window.onload = () => { loadCurrentRowData(); };
    </script>
</body>
</html>
]]>
.Value
wv.NavigateToString(html)

与Foxtable事件联动

如果你既要在Foxtable操作,也要在Web页面操作,那么就需要二者配合起来。

例如前面用Web做了一个订单编辑页面,希望Foxtable中选择不同的行时,能自动刷新订单编辑页面, 首先查阅上面的代码,发现负责刷新数据的js函数是loadCurrentRowData,然后在订单表的CurrentChanged事件加上代码:

If Forms("编辑订单").Opened Then
   
Dim wv As WebViewer = Forms("编辑订单").Controls("WebViewer1").WebViewer
    wv.CoreWebView2.ExecuteScriptAsync(
"loadCurrentRowData()")
End
If

提醒:加上事件联动后,你可以在前面AfterLoad事件代码中,找到上一行、下一行的按钮代码,删除对loadCurrentRowData的调用。


本页地址:http://www.foxtable.com/webhelp/topics/6234.htm