<%
'######################################################################
'## easp.extjson.asp
'## -------------------------------------------------------------------
'## Feature     :   EasyAsp ExtJson Class
'## Version     :   v2.0
'## Author      :   Easp.智者(Liaoyizhi[at]gmail.com)
'## Update Date :   2010/01/29 14:30
'## Description :   EasyAsp ExtJson类（插件）
'##					本类针对ExtJs将SQL的执行结果生成特定格式的Json数据
'##					配置项说明：
'##					.Sql		= Easp.db.wGR("TableName","","")							'字符串；可用Easp的Easp.db.wGR方法生成SQL，也可以直接写SQL字串
'##					.Replace	= Array("原字段名:替换字段名","原字段名2:替换字段名2")			'数组；设置要替换的字段名
'##					.Plus		= Array("新字段名:取值的字段名","新字段名2:=值")				'数组；新增字段：可用原有字段的值，也可直接赋值（赋值的话在值前面加等号"="）
'##					.Fun		= Array("字段名:函数名(v)","字段名2:函数名2(v,参数1，参数2)"）	'数组；绑定函数：作用于字段的值（v代表字段的值）
'##					.Total		= "totalProperty"											'字符串；设置总记录数的字段名，默认"root"
'##					.Root		= "root"													'字符串；设置root节点的字段名，默认"totalProperty"
'##					.Encode		= False														'布尔值；设置是否对值进行编码，默认 True
'##					公共方法：
'##					.Paging start,limit														'设置分页参数：不设置将返回所有数据
'##					.GetJson(sql,"type[:start:limit]")										'返回JSON字符串
'##						sql：sql字符串，如果在配置项中设置了sql，则此处可留空
'##						type：数据类型
'##							"1"或"grid"或空值	：生成grid使用的数据
'##							"2","form"			：生成form使用的数据
'##							"3","combo"			：生成combo使用的数据（实际上是数组）
'##						start：开始记录位置
'##						limit：读取记录条数
'##					.Flush																	'直接输出为Json文件到浏览器
'##
'## Examples	:	Example1：
'##					Easp.W Easp.Ext("extjson").GetJson("select * From table","grid:0:10")	'直接调用，最简单的方式
'##					Example2：
'##					With Easp.Ext("extjson")
'##						.Sql = Easp.db.wGR("table:id,name","class = 1","date desc")			'设置Sql字符串，直接用Easp生成
'##						.Total = "total"													'设置总记录数节点名称为total
'##						.Root = "root"														'设置根节点名称为root
'##						.Paging 0,30														'设置分页参数，通常为变量
'##						.Encode = False														'关闭对值的编码（不建议关闭）
'##						.Plus = Array("test:=123","test2:id")								'增加两个字段，第一个直接赋值，第二个使用id字段的值
'##						.Replace = Array("id:ttt","name:xxx","test2:test3")					'将id字段名替换为ttt，name字段名替换为xxx，将刚才增加的test2替换为test3
'##						.Fun = Array("test:abc(v)","date:Easp.DateTime(v,""yyyy-mm-dd"")")	'对test字段的值绑定abc函数，对date字段的值绑定Easp.DateTime函数（注意双引号）
'##						.GetJson "","grid"													'返回Json字符串，格式为grid
'##						.Flush																'输出到浏览器
'##					End With
'##
'######################################################################

Class EasyAsp_ExtJson
    ' ============================================
    '    变量声明
    ' ============================================
    Private s_sql, s_totalname, s_rootname, s_json
    Private i_start, i_limit
    Private arr_replacefieldname, arr_plusfields, arr_funbind
    Private b_encode

    ' ============================================
    '    设置Json参数及Sql语句
    ' ============================================
    '设置要替换字段名的字段

    Public Property Let [Replace](ByVal arr)
        arr_replacefieldname = arr
    End Property

    '设置要增加的字段

    Public Property Let Plus(ByVal arr)
        arr_plusfields = arr
    End Property

    '设置要绑定的处理函数

    Public Property Let Fun(ByVal arr)
        arr_funbind = arr
    End Property

    '设置Sql

    Public Property Let Sql(ByVal s)
        s_sql = s
    End Property

    '属性：Total节点名称

    Public Property Let Total(ByVal s)
        s_totalname = s
    End Property

    '属性：Root节点名称

    Public Property Let Root(ByVal s)
        s_rootname = s
    End Property

    '属性：是否对值进行JsEncode编码

    Public Property Let Encode(ByVal b)
        b_encode = b
    End Property

    ' ============================================
    '    类初始化
    ' ============================================

    Private Sub Class_Initialize()
        s_sql = ""
        s_totalname = "totalProperty"
        s_rootname = "root"
        s_json = ""
        i_start = ""
        i_limit = ""
        arr_replacefieldname = ""
        arr_plusfields = ""
        arr_funbind = ""
        b_encode = True
        Easp.Error(40001) = "出错文件：" & Easp.PluginPath & "easp.extjson.asp (ExtJson插件)<br />未设置SQL语句。"
        Easp.Error(40002) = "出错文件：" & Easp.PluginPath & "easp.extjson.asp (ExtJson插件)<br />添加Json字段时出错："
        Easp.Error(40003) = "出错文件：" & Easp.PluginPath & "easp.extjson.asp (ExtJson插件)<br />绑定函数时出错："
    End Sub

    ' ============================================
    '    类终结
    ' ============================================

    Private Sub Class_Terminate()
    End Sub

    ' ============================================
    '    公共方法，设置分页参数
    ' ============================================

    Public Sub Paging(ByVal Start, ByVal Limit)
        i_start = Start
        i_limit = Limit
    End Sub

    ' ============================================
    '    公共方法，生成Json字符串
    ' ============================================

    Public Function GetJson(ByVal sql, ByVal s)
        If Easp.IsN(s_sql) And Easp.IsN(sql) Then
            Easp.Error.Raise 40001
            Exit Function
        End If
        If Easp.IsN(s_sql) Then s_sql = sql
        Dim Rs, i, o, p, TotalCount, JsonStr, Rows, JsonType
        o = Easp_Param(s)
        JsonType = o(0)
        If Easp.Has(o(1)) Then
            p = Easp_Param(o(1))
            If Easp.Has(p(0)) Then If Easp.IsN(i_start) Then i_start = p(0)
            If Easp.Has(p(1)) Then If Easp.IsN(i_limit) Then i_limit = p(1)
        End If
        '获取数据
        Set Rs = Easp.db.GRS(s_sql)
        '计算记录总数
        TotalCount = CInt(Rs.RecordCount)
        '判断是否分页以及Start+Limit是否大于记录总数
        If Easp.Has(i_start) And Easp.Has(i_limit) Then
            Rows = CInt(i_start) + CInt(i_limit)
            If Rows >= TotalCount Then
                Rows = TotalCount
            End If
            i = i_start + 1
        Else
            Rows = Rs.RecordCount
            i = 1
        End If
        '按类别生成Json字符串
        Select Case LCase(JsonType)
            Case "", "1", "grid"
                JsonStr = CStr("{""" & s_totalname & """:"""& TotalCount & """,""" & s_rootname & """:[")
                JsonStr = JsonStr & GetRowsData(Rs, i, Rows, True, "{:}")
                JsonStr = JsonStr & "]}"
            Case "2", "form"
                JsonStr = "["
                JsonStr = JsonStr & "{" & GetColumnsData(Rs, True) & "}"
                JsonStr = JsonStr &"]"
            Case "3", "combo"
                JsonStr = "["
                JsonStr = JsonStr & GetRowsData(Rs, i, Rows, False, "[:]")
                JsonStr = JsonStr &"]"
        End Select
        GetJson = JsonStr '返回Json
        s_json = JsonStr
        Easp.db.C(Rs)
    End Function

    ' ============================================
    '    公共方法，直接输出为Json文件
    ' ============================================

    Public Sub Flush()
        Response.Clear()
        Response.Charset = "UTF-8"
        Response.ContentType = "application/json"
        Easp.NoCache()
        Easp.W s_json
    End Sub

    ' ============================================
    '    公共方法，直接输出为Json文件
    ' ============================================

    Public Function ShowJson()
        ShowJson = s_json
    End Function

    ' ============================================
    '    私有方法，JsEncode
    ' ============================================

    Private Function JsEncode(ByVal s)
        JsEncode = Easp.IIf(b_encode, Easp.JSEncode(s), s)
    End Function

    ' ============================================
    '    私有方法，返回经函数处理后的值
    ' ============================================

    Private Function GetFunctionValue(ByVal n, ByVal v)
        Dim TempArr, i, o, TempValue
        TempArr = arr_funbind
        For i = 0 To UBound(TempArr)
            o = Easp_Param(TempArr(i))
            If LCase(o(0)) = LCase(n) Then
                On Error Resume Next
                TempValue = Eval(o(1))
                If Err.Number <> 0 Then
                    Easp.Error.Msg = "绑定的函数不存在或函数的参数个数不正确 [" & o(1) & "]。"
                    Easp.Error.Raise 40003
                End If
                Err.Clear()
                Exit For
                TempArr = ""
                o = ""
                i = ""
            End If
        Next
        GetFunctionValue = Easp.IIf(Easp.IsN(TempValue), v, TempValue)
        TempValue = ""
    End Function

    ' ============================================
    '    私有方法，返回替换后的字段名
    ' ============================================

    Private Function GetReplaceName(ByVal s)
        Dim TempArr, i, o
        TempArr = arr_replacefieldname
        For i = 0 To UBound(TempArr)
            o = Easp_Param(TempArr(i))
            If LCase(o(0)) = LCase(s) Then
                GetReplaceName = o(1)
                Exit For
                TempArr = ""
                o = ""
                i = ""
            End If
        Next
        If Easp.IsN(GetReplaceName) Then GetReplaceName = s
    End Function

    ' ============================================
    '    私有方法，返回各列数据字符串
    ' ============================================

    Private Function GetColumnsData(ByVal Rs, ByVal b)
        Dim ColumnsStr, i, j, o, p, TempArr
        ColumnsStr = ""
        For i = 0 To Rs.Fields.Count - 1
            Dim FieldName, FieldValue
            FieldName = Rs.Fields(i).Name
            FieldValue = Rs.Fields(i).Value
            '替换字段名
            If IsArray(arr_replacefieldname) Then FieldName = GetReplaceName(FieldName)
            '绑定处理函数
            If IsArray(arr_funbind) Then FieldValue = GetFunctionValue(FieldName, FieldValue)
            If b Then ColumnsStr = ColumnsStr & Chr(34) & FieldName & Chr(34) & ":"
            ColumnsStr = ColumnsStr & Chr(34) & JsEncode(FieldValue) & Chr(34)
            If Not i = Rs.Fields.Count - 1 Then ColumnsStr = ColumnsStr & "," '不是最后一列（字段）,则加逗号
        Next

        '添加字段(列)
        If IsArray(arr_plusfields) Then
            ColumnsStr = ColumnsStr & ","
            TempArr = arr_plusfields
            For j = 0 To UBound(TempArr)
                Dim NewFieldName, NewFieldValue
                o = Easp_Param(TempArr(j))
                NewFieldName = o(0)
                If IsArray(arr_replacefieldname) Then NewFieldName = GetReplaceName(NewFieldName)
                If b Then ColumnsStr = ColumnsStr & Chr(34) & NewFieldName & Chr(34) & ":"
                If Mid(o(1), 1, 1) = "=" Then
                    NewFieldValue = Easp.CRight(o(1), "=")
                Else
                    On Error Resume Next
                    NewFieldValue = Rs.Fields(o(1)).Value
                    If Err.Number <> 0 Then
                        Easp.Error.Msg = "在数据库中未找到相应的字段名 [" & o(1) & "]。"
                        Easp.Error.Raise 40002
                    End If
                    Err.Clear()
                End If
                If IsArray(arr_funbind) Then NewFieldValue = GetFunctionValue(NewFieldName, NewFieldValue)
                ColumnsStr = ColumnsStr & Chr(34) & JsEncode(NewFieldValue) & Chr(34)
                If Not j = UBound(TempArr) Then ColumnsStr = ColumnsStr & ","
                NewFieldValue = ""
            Next
            TempArr = ""
            o = ""
            i = ""
            j = ""
        End If
        ColumnsStr = ColumnsStr & ""
        GetColumnsData = ColumnsStr
    End Function

    ' ============================================
    '    私有方法，返回一行数据字符串
    ' ============================================

    Private Function GetRowsData(ByVal Rs, ByVal Start, ByVal Rows, ByVal ShowFieldName, ByVal Brackets)
        Dim Columns
        If Easp.Has(Rs) Then
            For i = Start To Rows
                Rs.AbsolutePosition = i '将记录指针移到i(记录开始处)
                Columns = Columns & Easp.CLeft(Brackets, ":") & GetColumnsData(Rs, ShowFieldName) & Easp.CRight(Brackets, ":") '读取记录中的各列数据
                If i <> Rows Then Columns = Columns & "," '不是最后一条记录，则加逗号
            Next
        End If
        GetRowsData = Columns
    End Function

End Class
%>