Edit函数

Edit函数用于生成订单编辑页面edit.htm。

按照我们之前的设计思路,订单的增加与编辑,以及订单明细的增加、编辑和删除,都在这个页面完成,所以Edit函数的代码比较长,超过100行。

该函数的代码为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115

Dim e As RequestEventArgs = args(0)
Dim
wb As New weui
'
删除订单明细
If
e.GetValues.ContainsKey("deldid") Then
    DataTables(
"
订单明细").SQLDeleteFor("[_Identify] = " & e.GetValues("deldid"))
End
If
'
订单编辑
Dim
pr As DataRow '订单
Dim
srs As List(of DataRow) '订单明细集合
Dim
Page As Integer '页码变量
If
e.GetValues.ContainsKey("page") Then  '如果地址中有page参数
    Integer.TryParse(e.GetValues("page"), page)
'
提取page参数
End
If
If
e.GetValues.ContainsKey("oid") = False Then '如果没有传递订单编号,则新增与一个订单
    pr = DataTables(
"
订单").SQLAddNew() '
    pr(
"
订单编号") = Functions.Execute("GetOrderID") '利用自定义函数GetOrderID为新增订单生成编号.
    pr(
"
日期") = Date.Today()
Else
'如果传递了订单编号,则找出此订单进行编辑
    pr = DataTables("订单").SQLFind("订单编号='" & e.GetValues("oid") & "'")
    If pr Is Nothing Then '多用户情况下,必须考虑其他用户删除订单的可能.
        wb.InSertHtml("此订单已被其他用户删除!")
        e.WriteString(wb.Build)
        Return ""  '必须返回
    End
If

    srs DataTables("订单明细").SQLSelect("订单编号='" & pr("订单编号"& "'") '获取订单明细
End If
Dim
url As String = "edit.htm?page=" & page &  "&oid=" & pr("订单编号"'传递页码和订单编号
wb
.AddForm("","form1",url)
With wb.AddInputGroup("form1","ipg1",iif(e.GetValues.ContainsKey("oid"),"编辑订单","新增订单"))
    With .AddInput("订单编号","编号","text")
        .Value = pr("订单编号")
        .Readonly = True
    End With
    .AddInput("客户","客户","text").Value = pr("客户")
    .AddInput("日期","日期","date").Value = pr("日期")
    If e.GetValues.ContainsKey("oid"Then '如果是旧订单,则汇总显示数量和金额
       
Dim qty As Integer
        Dim amt As Integer
        For Each sr As DataRow In srs
            qty = qty + sr(
"
数量")
            amt = amt + sr(
"
数量") * sr("单价")
        Next
        .AddInput(
"
总数量","总数量","number").value = qty
        .AddInput(
"
总金额","总金额","number").value = amt
    End
If

End
With
'
订单明细编辑
Dim
mr As DataRow '要编辑的订单明细
Dim
IsNew As Boolean '此变量用于标记是否要新增明细
If
e.GetValues.ContainsKey("oid") = False OrElse e.GetValues.ContainsKey("addnext") '如果是新增订单,或这包括addnext参数
    IsNew = True
'
IsNew参数设置为True,表明需要新增订单明细
ElseIf
e.GetValues.ContainsKey("did") Then '如果传递了订单明细主键
    mr = DataTables(
"
订单明细").SQLFind("[_Identify]=" & e.GetValues("did")) '找出此订单明细进行编辑
End
If
If
IsNew OrElse mr IsNot Nothing  Then
    With wb.AddInputGroup("form1","ipg2",iif(IsNew,
"
新增明细","编辑明细"))
        .Attribute = "onchange='calc()'"
'
调用js函数,自动计算金额
        If IsNew Then
'
如果是新增订单明细
            .AddInput(
"
产品","产品","text")
            .AddInput(
"
数量","数量","number")
            .AddInput(
"
单价","单价","number").Step= "0.01"
            .AddInput(
"
金额","金额","number")
        Else
            .AddHiddenValue("DetailID",mr("_Identify"))
'
插入一个隐藏的订单明细主键,此值将随表单数据一并提交到服务器.
            .AddInput(
"
产品","产品","text").Value = mr("产品")
            .AddInput(
"
数量","数量","number").value = mr("数量")
            With .AddInput(
"
单价","单价","number")
                .Step= "0.01"
                .value = mr(
"
单价")
            End With
            .AddInput(
"
金额","金额","number").value = mr("数量") * mr("单价") '后台没有金额列,要通过数量和单价计算得出
        End If
    End
With

End
If
'
生成订单明细表格
If
e.GetValues.ContainsKey("oid") AndAlso  srs.count > 0 Then '如果不是新增订单,且订单明细行数大于0,则生成订单明细表格.
    With wb.AddTable("form1","detailTable")
'
为了区分,明细表的名字设为detailTable
        .head.AddRow(
"
产品","数量","单价","金额")
        .ActiveSheet = "menu"
'
指定菜单
        For Each sr As DataRow In srs
            With .Body.AddRow(sr(
"
产品"),sr("数量"),sr("单价"))
                .AddCell(sr(
"
数量") * sr("单价"))
                .Primarykey = sr("_Identify")
'
为此行指定主键值
            End With
        Next
    End With
   
'
设计菜单
    With wb.AddActionSheet("","menu")
        .Add("mnudAdd",
"
增加明细").Attribute="onclick='addDetail()'" '调用js函数
        .Add("mnuEdit",
"
编辑明细").Attribute ="onclick='editDetail()'"
        .Add("mnuDelete",
"
删除明细").Attribute ="onclick=""show('dlg1')"""
        .Add("mnuCancel",
"
取消","",True)
    End
With

End
If
With
wb.AddDialog("","dlg1", "删除确认","您确定要删除当前明细吗?")
    .AddButton("btnCancel",
"
取消").Kind = 1
    .AddButton("btnOK",
"
确定").Attribute = "onclick='delDetail()'"
End
With
With
wb.AddButtonGroup("form1","btg1",False)
    .Add("btn1",
"
增加明细", "submit").FormAction = url & "&addnext=true" '加上addnext参数,表示保存后进入增加明细状态
    .Add("btn2",
"
保存", "submit") '正常提交,保存后进入编辑状态
    If  e.GetValues.ContainsKey("oid") = False Then
'
如过是新增订单
        .Add("btn3",
"
取消", "button","list.htm?page=" & page & "&deloid=" & pr("订单编号")) '删除新增订单后返回列表
    ElseIf IsNew OrElse mr IsNot Nothing  Then
'
如果在给旧订单新增或修改明细,则直接返回编辑状态
        .Add("btn3",
"
取消", "button",url) '返回编辑状态
    Else
        .Add("btn3",
"
返回", "button","list.htm?page=" & page) '返回列表
    End
If

End
With
pr
.Save() '必须保存,而且必须在最后保存,因为SQLAddNew增加的行,保存之后就会销毁,无法再调用
If
e.PostValues.Count > 0 Then '如果是通过提交按钮访问,则给一个已经保存的提示给用户,时长500毫秒
    wb.AddToast("","t1",
"
已经保存",0).Msec= 500
End
If
wb
.AppendHTML("<script src='./lib/order.js'></script>") '引入脚本文件
e
.WriteString(wb.Build) '生成网页

我们前面已经提到,上面的函数完成了5项任务,所以我们要分5种情况来解析代码。
我强烈建议你直接看上面的代码,自行分析,代码的逻辑很清晰,而且我加上了注释,理解起来不困难,实在看不懂的时候,再来看下面的解析不迟。
只要你明白了之前已经理顺的设计思路,看懂上述代码应该不会有问题的。

增加订单

我们已经知道,当用户在list.htm中,单击"增加订单"按钮,会向服务器发送访问请求:
edit.htm?page=2
服务端收到这个访问请求后,触发HttpRequest事件,将请求转给Edit函数处理。

以下是edit函数的处理流程:

第11行到第13行代码,从GetValues集合中提取page参数,保存在变量page中,page变量的值等于2。
由于没有传递oid参数,第14行代码的条件成立,执行第15行到第17行代码。
第15行代码新增一个订单。
第16行代码利用自定义函数GetOrderID为新订单生成订单编号。
第17行代码将订单日期设置为当天日期。

假定新增订单编号为161203006,第27行代码合成了一个链接,保存在url中,内容为:
edit.htm?page=2&oid=161203006
第28行代码新增一个表单,数据接收链接为url,即:edit.htm?page=2&oid=161203006。
第29到第46行代码,生成了订单输入框。
由于第36行代码的条件不成立,不会生成总数量和总金额输入框。

第50行代码的条件成立,IsNew参数设置为True,表明需要新增一个订单明细。
第59到第62行代码,为订单明细生成输入框。

第57行代码调用了js函数calc,这个函数的代码为:
function calc(){
    document.getElementById("金额").value = document.getElementById("数量").value * document.getElementById("单价").value;
}

这样用户输入订单明细的数量和单价后,能自动计算出金额。
注意这里没有单独给数量和单价输入框定义onchange事件,而是给他们的父容器定义onchange事件,在父容器定义的事件,对于子元素有效,JavaScript这个特性真不错。


第76行行代码的条件不成立,所以不会生成明细表格及相关菜单。
第101行代码定义了一个提交按钮,标题为"保存"。
第100行代码定义了一个提交按钮,标题为"增加明细",数据接收链接为:edit.htm?page=2&oid=161203006&addnext=true
这样用户单击"保存明细"后,服务器通过分许get参数,就知道
用户要保存本次输入结果,然后开始下一个明细的输入。
第103行代码定义了一个取消按钮,链接为:
list.htm?page=2&deloid=161203006
这样用户单击取消按钮,会返回list.htm,并显示第3页数据,在显示数据之前会先删除新增加的订单。

第111行代码判断本次访问是否含有有表单数据。
如果本次访问包括有表单数据,则在第112行代码创建一个Toast,显示0.5秒,内容为"已经保存".
需要注意的时候,表单数据的保存是通过Save函数完成的,Edit函数只负责生成网页内容。

综上所示,edit.htm在新增订单状态下的显示内容为:

编辑订单

假定客户端正在访问list.htm,浏览到第3页,选择该页中订单编号为161203005的订单,然后执行菜单命令“编辑订单”。
服务端会收到以下访问请求:
edit.htm?page=2&oid=161203005
服务端收到这个访问请求后,触发HttpRequest事件,将请求转给Edit函数处理。

下面是Edit函数的处理流程,和增加订单相同的部分就不重复讲述了:

第19行代码根据传递过来的订单编号找出订单,保存在变量pr中。
第25行代码提取出这个订单所有的订单明细,保存在集合srs中。
第29行到第46行代码,为这个订单生成了输入框。
由于后台的订单表并不存在总数量和总金额两列,所以第37到第44行代码,累加了订单明细的数量和金额,赋值给对应输入框的value属性。

由于没有传递addnext和did参数,所以第50行代码和第52行代码的条件都不成立。
因此第55行代码的条件也不成立,本次请求不会生成订单明细输入框。

第76到第94行代码,生成订单明细表格,以及操作明细的菜单。
由于订单明细表的金额是表达式列,无法用CreateDataTable自动生成,所以只能逐行生成表格,逐行设置主键。

第107行代码定义了一个返回按钮,链接为:list.htm?page=2
这样用户单击返回按钮,会返回list.htm,并显示第3页数据。

综上所述,在编辑订单状态下,edit.htm显示内容为:



新增明细

假定用户正在编辑编号为161203005,单击了"新增明细"按钮。
服务器会收到以下访问请求:
edit.htm?page=2&oid=161203005&addnext=true
服务端收到这个访问请求后,触发HttpRequest事件,由于PostValue集合包括有表单数据,所以HttpRequest事件先执行Save函数保存数据,然后将请求转给Edit函数处理。

Edit函数的处理流程和编辑订单基本相同,下面只讲述不同的地方:

由于访问请求中包括addnext参数,第50行代码的条件成立。
第51行代码将变量IsNew设置为True,表明需要新增明细。
第55行和第58行代码的条件成立,执行第59到第62行代码,为新增明细定义输入框。

第104行代码的条件成立,第105代码生成一个取消按钮,这个取消按钮的链接地址为:
edit.htm?page=2&oid=161203005
返回按钮的类型不是submit,所以单击这个按钮,不会提交数据,而是直接返回到订单编辑状态,等于取消了本次新增明细操作。

综上所述,在新增明细状态下,edit.htm的显示内容为:

小提示:如果想直接增加订单明细,不想保存当前输入结果,可以点击菜单中的"增加明细"命令。

编辑明细

假定用户正在编辑编号为161203005的订单,连续点击订单明细表格的同一单元格,在弹出的菜单中执行"编辑明细"命令,会调用js函数editDetail。
editDetail函数的代码为:
function editDetail(){
   location = form1.action + "&did=" + detailtable.primarykey;
}

form1.action获取表单的action属性(数据接收链接),值为:edit.htm?page=2&oid=161203005
假定用户点击的订单明细的主键为567,那么执行js函数editDetail,会向服务器发出访问请求:
edit.htm?page=2&oid=161203005&did=567
服务端收到这个访问请求后,触发HttpRequest事件,将请求转给Edit函数处理。

edit函数的处理流程和新增明细基本相同,不同的部分只有:

由于访问请求中包括did参数(订单明细主键),第52行代码的条件成立。
第53行代码根据did参数,找出对应的订单明细,保存再变量mr中。
第64到第71行代码,为此订单明细生成输入框。
第64行代码,插入了一个隐藏的输入框,名为DetailID,值为此明细的主键。
这样服务器收到用户提交的表单数据后,通过判断PostValues集合是否包括DetailID参数,就能知道是用户新增明细还是编辑明细。
第71行代码,由于订单明细表的金额列是表达式列,并不存在于后台数据表,所以需要用代码计算出金额,并赋值给金额输入框的value属性

综上所述,在编辑明细状态下,edit.htm的显示内容为:

删除明细

假定用户正在编辑编号为161203005,连续点击订单明细表格的同一单元格,在弹出的菜单中执行"删除明细"命令, 会显示一个对话框(第91行代码):

如果用户单击确定,会调用js函数delDetail(第97行代码),该函数的代码为:
function delDetail() {
   location = form1.action + "&deldid=" + detailtable.primarykey;
}

假定用户在订单明细表格中点击的是主键为568的明细,那么执行js函数delDetail,会向服务器发出访问请求:
edit.htm?page=2&oid=161203005&deldid=568
服务端收到这个访问请求后,触发HttpRequest事件,将请求转给Edit函数处理。

Edit函数的处理流程如下:

第4行代码判断GetValues集合是否包括deldid参数。
如果包括过deldid参数,则执行第5行代码,删除主键等于deldid参数的订单明细。
接下来处理流程,和编辑订单请求完全相同,就不重复了。

综上所述,删除订单明细后,edit.htm重新进入订单编辑状态,显示内容为:


本页地址:http://www.foxtable.com/mobilehelp/topics/0130.htm