define(['avalon', 'jquery', 'modelFactory', 'ztree', 'jscal2'], function (avalon, $, factory) {

    /*联系人信片*/
    new function () {
        var contactsCard = avalon.ui.contactsCard = function (el, data, vmodels) {
            var ops = {};
            if (el) {
                var elDataOps = el ? avalon(el).data() : {};
                $.extend(ops, data.contactsCardOptions, elDataOps);
            }
            var elWrapper = avalon(el),
            model = avalon.vmodels.contactsCard,curId,
            loadData = function (id) {
                if (!id) {
                    avalon.log('缺少id ： ' + id)
                    model.entity = factory.create('Contacts')
                    return
                }
                if (curId != id) curId = id;
                else {
                    return;
                }
                model.createEntity();
                $.get('/Customer/InitContacts/' + id + '?_d=' + new Date())
                .done(function (ret) {
                    if (ret.result) {
                        model.entity = ret.data.contacts;
                        if (!model.entity.Picture)
                            model.entity.Picture = model.entity.Thumbnail = '/Content/Themes/Base/Images/contract_default.png'

                    }
                })
            },
            setPosition = function (el) {
                var top = 0,
                postion = el.offset(),
                height = $('body').height(),
                card = $(document.getElementById('contactsCard'))
                //判断浏览器高度，来确定显示在上面还是下面
                if ((height - postion.top) > 205)
                    top = postion.top + 20
                else
                    top = postion.top - 205
                card.css({ 'top': top + 'px', 'left': postion.left + 'px' })
            }
            if (el) {
                $(el).hover(function () {
                    var $that = $(this)
                    setPosition($that)
                    var data = $that.data();
                    if (data.id) model.id = data.id;
                    if (model.id) {
                        loadData(model.id);
                        model.show = true
                    }
                }, function () {
                    model.show = false
                })
            }

            if (model) {
                return model
            }
            model = avalon.define('contactsCard', function (scope) {
                scope.show = false
                scope.entity = {}
                scope.id = ''
                scope.createEntity = function () {
                    model.entity = factory.create('Contacts')
                    model.entity.Picture = model.entity.Thumbnail = '/Content/Themes/Base/Images/contract_default.png'
                }
            })
            model.createEntity();
            model.$watch('id', function (n, o) {
                if (n !== o)
                    loadData(n)
            })
            
            if (ops.id) model.id = ops.id;
            avalon.nextTick(function () {
                $(document.body).append(avalon.ui.contactsCard.defaults.tmpl)
                avalon.scan(document.getElementById('contactsCard'), model)
            })

            return model
        }

        contactsCard.defaults = {
            $skipArray: ['tmpl'],
            tmpl: '<div class="businessCardWarp" id="contactsCard" ms-visible="show">'
    + '<div class="businessCardLeft"><p class="pname">{{entity.Name|truncate(10)}}({{entity.Sex == 0 ? "男" : "女"}})</p>'
    + '<p class="pname2">{{entity.Post}}<br />{{entity.Department}}</p><div class="picture">'
    + '<img ms-src="entity.Picture" width="100" height="100" style="width: 100px; height: 100px;"></div>'
    + '</div><div class="businessCardRight"><ul><li><span>联系人角色：</span>{{entity.ContactRoleDisplay}}</li><li><span>工作电话：</span>{{entity.OfficeTel}}</li>'
    + '<li><span>手机号码1：</span>{{entity.MobileNumber1}}</li><li><span>手机号码2：</span>{{entity.MobileNumber2}}</li><li><span>电子邮箱：</span>{{entity.Email}}</li><li><span>QQ号码：</span>{{entity.QQ}}</li>'
    + '</ul></div></div>'
        }
    }

    /* 检测重复客户 */
    new function () {
        var existsRepeatCustomer = avalon.ui.existsRepeatCustomer = function (el, data, vmodels) {
            var model, CBCRM = avalon.vmodels.CBCRM,
                opts = data.existsRepeatCustomerOptions,
                tmplSrc = opts.tmpl,
                url = opts.url
            if (avalon.vmodels.repeatCustomers)
                delete avalon.vmodels.repeatCustomers
            model = avalon.define('repeatCustomers', function (scope) {
                scope.list = []
                scope.key = ''
                scope.init = function () {
                    CBCRM.loadView(tmplSrc, function (tmpl) {
                        var dialog = messageBox.openHtml('检测重复客户', '800px', '', tmpl, null,
                            function () {
                                model.key = ''
                                model.list.removeAll()
                            }),
                            content = dialog.content().firstChild
                        avalon.scan(content, model)
                    })
                }
                scope.loadData = function () {
                    var key = model.key
                    if (key) {
                        $.post('/Customer/ExistsCustomer', { name: key.trim() })
                              .done(function (ret) {
                                  if (ret.result) {
                                      messageBox.ok(ret.message)
                                  } else {
                                      model.list = ret.data
                                  }
                              })
                    } else
                        messageBox.error('请输入客户名称关键字再点击搜索')
                }
                scope.toSearch = function (e) {
                    if (e.keyCode === 13)
                        model.loadData()
                }
            })

            avalon(el).bind('click', function () {
                model.init()
            })

            return model
        }

        existsRepeatCustomer.defaults = {
            $skipArray: ['tmpl'],
            key: '',
            tmpl: '/Customer/ExistsRepeatCustomer.html',
            url: ''
        }
    }()

    /* 跟单阶段 */
    new function () {
        var followStage = avalon.ui.followStage = function (el, data, vmodels) {
            var model = avalon.define(data.followStageId, function (scope) {
                avalon.mix(scope, data.followStageOptions)
            })
            avalon.nextTick(function () {
                avalon.innerHTML(el, model.tmpl)
                avalon.scan(el, model)
            })
            return model
        }

        followStage.defaults = {
            $skipArray: ['tmpl'],
            tmpl: '<div id="stage" class="bindStage"><ul ms-each-f="datasource">' +
                '<li ms-live-click="setStage" ms-hover="stagehover" class="selectItem" ms-class-current="f.curr"> {{$index+1}}<p class="gray" ms-html="f.label"></p></li></ul></div>',
            datasource: [],
            readonly: false,
            setStage: function () {
                var itemVm = this.$vmodel,
                    item = itemVm[itemVm.$itemName],
                    pvm = this.$vmodels[1]
                if (!pvm.readonly) {
                    pvm.datasource.forEach(function (d) {
                        d.curr = false
                    })
                    item.curr = true
                    pvm.onSetStage.call(this, item)
                }
            },
            onSetStage: function (item) { }
        }
    }()

    /*下拉代理区域树*/
    new function () {
        var dropDownProxyAreaTree = avalon.ui.dropDownProxyAreaTree = function (el, data, vmodels) {
            var options = avalon.mix(true, {}, avalon.ui.dropDownProxyAreaTree.defaults
                , data.dropDownProxyAreaTreeOptions)
            , model
            options.dropDownTreeId = data.dropDownProxyAreaTreeId
            var $vm = avalon.ui.dropDownTree(el, options, vmodels)
            return $vm
        }
        dropDownProxyAreaTree.defaults = {
            q: '输入代理区域检索',
            treeopts: {
                async: {
                    url: function (treeId, treeNode) {
                        var url = '/Customer/GetProxyArea'
                        return url
                    },
                    enable: true,
                    type: 'get',
                    dataFilter: function (treeId, parentNode, responseData) {
                        var ret = []
                        if (responseData.data) {
                            if (responseData.data.length) {
                                ret = ret.concat(responseData.data)
                            }
                        }
                        return ret
                    }
                },
                data: {
                    simpleData: {
                        enable: true,
                        idKey: 'Id',
                        pIdKey: 'Parent'
                    },
                    key: {
                        name: 'Name'
                    }
                },
                check: {
                    enable: true
                }
            }
        }
    }()

    /*下拉客户/联系人树*/
    new function () {
        avalon.ui.dropDownCustomerContactsTree = function (el, data, vmodels) {
            var options = avalon.mix(true, {}, avalon.ui.dropDownCustomerContactsTree.defaults
                , data.dropDownCustomerContactsTreeOptions)
            options.dropDownTreeId = data.dropDownCustomerContactsTreeId
            var $vm = avalon.ui.dropDownTree(el, options, vmodels)
            return $vm
        }

        avalon.ui.dropDownCustomerContactsTree.defaults = {
            q: '输入客户名称关键字检索',
            treeopts: {
                async: {
                    url: function (treeId, treeNode) {
                        var url = '/Customer/GetCustomerContacts',
                            vm = avalon.vmodels[treeId.replace('zTree', '')]
                        if (vm && vm.q && vm.q !== vm.qcopy) {
                            if (avalon.vmodels.CBCRM.$debug)
                                avalon.log('customerName : ' + vm.q)
                            url += '?customerName=' + vm.q
                        }
                        return url
                    },
                    enable: true,
                    type: 'get',
                    dataFilter: function (treeId, parentNode, responseData) {
                        var ret = []
                        if (responseData.data) {
                            var l = responseData.data.customers.length;
                            if (l) {
                                ret = ret.concat(responseData.data.customers)
                            }
                        }
                        return ret
                    }
                },
                data: {
                    simpleData: {
                        enable: true,
                        idKey: 'Id',
                        pIdKey: 'ParentId'
                    },
                    key: {
                        name: 'Name'
                    }
                }
            }
        }
    }()

    /*进度条*/
    new function () {
        avalon.ui.processbar = function (el, data, vmodels) {
            var elWrapper = avalon(el),
            model = avalon.define(data.processbarId, function (scope) {
                avalon.mix(scope, avalon.ui.processbar.defaults, data.processbarOptions)
                scope.setVal = function (v) {
                    if (!model.readonly) {
                        model.val = v
                        model.valChanged.call(model, v)
                    }
                }
                scope.mouseover = function () {
                    if (!model.readonly)
                        model.showcurr = false
                }
                scope.mouseout = function () {
                    if (!model.readonly)
                        model.showcurr = true
                }
            })

            avalon.nextTick(function () {
                avalon.innerHTML(el, model.tmpl)
                avalon.scan(el, model)
            })

            return model
        }

        avalon.ui.processbar.defaults = {
            $skipArray: ['tmpl'],
            tmpl: '<div class="temperature" ms-title="val+ \'%\'"><div class="processbar"><ul class="studyplay_starBg" style="width: 110px; ">'
            + '<li ms-hover="studyplay_starovering" class="studyplay_starovering" style="z-index: 0; display: list-item;" ms-visible="showcurr" ms-css-width="val+10"></li>'
            + '<li ms-mouseout="mouseout" ms-mouseover="mouseover" ms-click="setVal(0)" ms-hover="studyplay_starovering:!readonly" class="studyplay_starON" style="width:10px;z-index:11;"></li>'
            + '<li ms-mouseout="mouseout" ms-mouseover="mouseover" ms-click="setVal(10)" ms-hover="studyplay_starovering:!readonly" class="studyplay_starON" style="width:20px;z-index:10;"></li>'
            + '<li ms-mouseout="mouseout" ms-mouseover="mouseover" ms-click="setVal(20)" ms-hover="studyplay_starovering:!readonly" class="studyplay_starON" style="width:30px;z-index:9;"></li>'
            + '<li ms-mouseout="mouseout" ms-mouseover="mouseover" ms-click="setVal(30)" ms-hover="studyplay_starovering:!readonly" class="studyplay_starON" style="width:40px;z-index:8;"></li>'
            + '<li ms-mouseout="mouseout" ms-mouseover="mouseover" ms-click="setVal(40)" ms-hover="studyplay_starovering:!readonly" class="studyplay_starON" style="width:50px;z-index:7;"></li>'
            + '<li ms-mouseout="mouseout" ms-mouseover="mouseover" ms-click="setVal(50)" ms-hover="studyplay_starovering:!readonly" class="studyplay_starON" style="width:60px;z-index:6;"></li>'
            + '<li ms-mouseout="mouseout" ms-mouseover="mouseover" ms-click="setVal(60)" ms-hover="studyplay_starovering:!readonly" class="studyplay_starON" style="width:70px;z-index:5;"></li>'
            + '<li ms-mouseout="mouseout" ms-mouseover="mouseover" ms-click="setVal(70)" ms-hover="studyplay_starovering:!readonly" class="studyplay_starON" style="width:80px;z-index:4;"></li>'
            + '<li ms-mouseout="mouseout" ms-mouseover="mouseover" ms-click="setVal(80)" ms-hover="studyplay_starovering:!readonly" class="studyplay_starON" style="width:90px;z-index:3;"></li>'
            + '<li ms-mouseout="mouseout" ms-mouseover="mouseover" ms-click="setVal(90)" ms-hover="studyplay_starovering:!readonly" class="studyplay_starON" style="width:100px;z-index:2;"></li>'
            + '<li ms-mouseout="mouseout" ms-mouseover="mouseover" ms-click="setVal(100)" ms-hover="studyplay_starovering:!readonly" class="studyplay_starON" style="width:110px;z-index:1;"></li>'
            + '</ul></div></div><label style="width:60px;display:inline;">&nbsp;{{val}}%</label>',
            val: 0,
            readonly: false,
            valChanged: function (val) {
                avalon.log('curr val : ' + val)
            },
            showcurr: true
        }
    }()

    /*评级*/
    new function () {
        avalon.ui.raty = function (el, data, vmodels) {
            var elWrapper = avalon(el),
            model = avalon.define(data.ratyId, function (scope) {
                avalon.mix(true, scope, avalon.ui.raty.defaults, data.ratyOptions)
                scope.destroy = function () {
                    var ui = avalon.vmodels[data.ratyId]
                    ui.datasource.removeAll()
                    delete avalon.vmodels[data.ratyId]
                    data = null
                }
                scope.ratyChange = function () {
                    if (model.readonly) return
                    var itemvm = this.$vmodel.raty,
                    sourcevm = this.$vmodels[1]
                    sourcevm.val = itemvm.val
                    sourcevm.ratyChanged.call(this, sourcevm.val)
                }
                scope.mouseover = function () {
                    if (model.readonly) return
                    var itemvm = this.$vmodel.raty
                    sourcevm = this.$vmodels[1]
                    sourcevm.datasource.forEach(function (r) {
                        if (sourcevm.val < r.val && r.val <= itemvm.val)
                            r.icon = sourcevm.ratyon
                    })
                }
                scope.mouseout = function () {
                    if (model.readonly) return
                    var itemvm = this.$vmodel.raty
                    sourcevm = this.$vmodels[1]
                    sourcevm.datasource.forEach(function (r) {
                        if (sourcevm.val < r.val && r.val <= itemvm.val)
                            r.icon = sourcevm.ratyoff
                    })
                }
            })

            model.$watch('val', function (n, o) {
                var that = this
                if (n != o) {
                    that.datasource.forEach(function (r) {
                        r.icon = r.val > n ? that.ratyoff : that.ratyon
                    })
                }
            })

            if (model.val) model.val = model.val

            avalon.nextTick(function () {
                elWrapper.attr('ms-each-raty', 'datasource')
                avalon.innerHTML(el, model.itemtmpl)
                avalon.scan(el, model)
            })
            return model

        }

        avalon.ui.raty.defaults = {
            $skipArray: ['itemtmpl', 'ratyon', 'ratyoff'],
            ratyon: '/Content/Themes/Base/Images/raty/star-on.png', //选中评级图标
            ratyoff: '/Content/Themes/Base/Images/raty/star-off.png', //未选中评级图标
            datasource: [
                {
                    label: '一星',
                    val: 1,
                    icon: ''
                },
                {
                    label: '二星',
                    val: 2,
                    icon: ''
                },
                {
                    label: '三星',
                    val: 3,
                    icon: ''
                },
                {
                    label: '四星',
                    val: 4,
                    icon: ''
                },
                {
                    label: '五星',
                    val: 5,
                    icon: ''
                }
            ],
            val: 0,
            unit:"星",
            readonly: false,//设置ui为只读
            ratyChanged: function () {
                avalon.log('this.$vmodel  this.$vmodels[1] arguments[0] : this.$vmodels[1].val')
            },
            itemtmpl: '<img style="cursor: pointer;" ms-src="raty.icon || ratyoff" ms-alt="readonly?(val+unit):raty.label" ms-title="readonly?(val+unit):raty.label" ms-live-click="ratyChange" ms-live-mouseover="mouseover" ms-live-mouseout="mouseout">&nbsp;'
        }
    }()

    /*下拉品牌*/
    new function () {
        avalon.ui.dropDownBrand = function (el, data, vmodels) {
            var opts = avalon.mix({}, avalon.ui.dropDownBrand.defaults, data.dropDownBrandOptions),
            panelId = data.dropDownBrandId + "panel",
            dropPName = 'dropDownPanel',
            panelvm,
            model = avalon.define(data.dropDownBrandId, function (scope) {
                avalon.mix(scope, opts)
                scope.destroy = function () {
                    var vm = avalon.vmodels.data.dropDownBrandId
                    if (vm) delete avalon.vmodels.data.dropDownBrandId
                    avalon.vmodels[panelId].destroy()
                }
                scope.loadData = function () {
                    $.get(model.url || opts.url, { key: model.key || '' })
                    .done(function (ret) {
                        if (ret.result) {
                            model.datasource = ret.data
                        }
                    })
                }
            })


            model.$watch('url', function (n, o) {
                if (n != o && n) {
                    loadData()
                }
            })

            panelvm = avalon.ui[dropPName](el, {
                dropDownTreeOptions: {
                    target: opts.target,
                    height: opts.height,
                    width: opts.width,
                    initevent: opts.initevent
                },
                dropDownPanelId: panelId
            }, [model].concat(vmodels))

            panelvm.showBefore = function () {
                this.content = opts.tmpl
                avalon.scan(this.panel.firstChild, model)
                panelvm.showBefore = null
                model.loadData()
            }

            return model
        }

        avalon.ui.dropDownBrand.defaults = {
            $skipArray: ['tmpl'],
            url: '/Product/Brand',
            key: '',
            width: 260,
            height: false,
            initevent: true,
            datasource: [],
            tmpl: '<div><div class="boxTitlenob" style="margin-left: 0;"><h2><span class="rseachbox">'
+ '<input style="margin-bottom: 0px;" type="text" ms-duplex="key"><button ms-click="loadData" type="button" class="inputbt"></button></span></h2></div>'
+ '<table id="tableSelectBrand" width="580px" align="center" border="0" cellspacing="1" cellpadding="0" class="tableList">'
+ '<tbody id="BrandList"><tr style="cursor: pointer; background-color: rgb(255, 255, 255);"><td>'
+ '<ul class="BrandListUl" id="BrandListUl" ms-each-brand="datasource">'
+ '<li><img ms-attr-src="brand.Img" ms-attr-alt="brand.Name" ms-title="brand.Name" /></li>'
+ '</ul></td></tr></tbody></table></div>'
        }
    }()

    /*下拉产品*/
    new function () {
        avalon.ui.dropDownProduct = function (el, data, vmodels) {
            var opts = avalon.mix({}, avalon.ui.dropDownProduct.defaults, data.dropDownProductOptions),
            panelId = data.dropDownProductId + "panel",
            dropPName = 'dropDownPanel',
            panelvm,
            model = avalon.define(data.dropDownProductId, function (scope) {
                avalon.mix(scope, opts)
                scope.destroy = function () {
                    var vm = avalon.vmodels.data.dropDownProductId
                    if (vm) delete avalon.vmodels.data.dropDownProductId
                    avalon.vmodels[panelId].destroy()
                }
                scope.sproductOpts = {
                    enablesetsize: false,
                    initload: false,
                    pagesize: 5,
                    paging: function () {
                        scope.loadData(this.currentindex + 1)
                    }
                }
                scope.loadData = function (pageindex) {
                    $.get(model.url() || opts.url(), { key: model.key || '', pageIndex: pageindex, pageSize: 5 })
                    .done(function (ret) {
                        if (ret.result) {
                            model.datasource = ret.data.Source
                            avalon.vmodels.sproductupaing.total = ret.data.RecordTotal
                        }
                    })
                }
            })

            panelvm = avalon.ui[dropPName](el, {
                dropDownTreeOptions: {
                    target: opts.target,
                    height: opts.height,
                    width: opts.width,
                    initevent: opts.initevent
                },
                dropDownPanelId: panelId
            }, [model].concat(vmodels))

            panelvm.showBefore = function () {
                this.content = opts.tmpl
                avalon.scan(this.panel, model)
                panelvm.showBefore = null
                model.loadData()
            }

            return model
        }

        avalon.ui.dropDownProduct.defaults = {
            $skipArray: ['tmpl'],
            url: function () { return '/Product/Product' },
            key: '',
            width: 600,
            height: false,
            initevent: true,
            datasource: [],
            productReturned: function () {

            },
            productReturn: function () {
                var vm = this.$vmodel,
                product = vm[vm.$itemName]
                this.$vmodels[1].productReturned.call(this, product)
            },
            tmpl: '<table width="100%" border="0" align="center" cellpadding="0" cellspacing="0"> '
                + '<tr> <td valign="top" style="width:600px;"> '
                + '<div class="boxTitlenob"> <h2><span class="rseachbox"> '
                + '<input  ms-duplex="key" placeholder="输入产品关键字"  type="text" style="margin-bottom: 0px; font-size:9px; color: #989898;" /> '
                + '<button class="inputbt" type="button"  ms-click="loadData(1)"> </button> </span> </h2></div> '
                + '<table width="" border="0" cellspacing="1" cellpadding="0" class="tableList bottom10"> '
                + '<thead><tr class="head">'
                + '<td width="20%" align="center"> 产品名称</td> <td width="8%" align="center">规格/型号</td> '
                + '<td width="10%" align="center">库存量</td><td width="5%" align="center">单价</td> '
                + '<td width="8%" align="center">单位</td></tr></thead> '
                + '<tbody><tr ms-repeat-product="datasource" style="cursor:pointer;" title="点击选择产品" ms-live-click="productReturn">'
                + '<td align="left">{{product.Name}}</td><td align="center"> {{product.Standard}}</td> '
                + '<td align="center">{{product.CurrentStockNum}}</td><td align="center">{{product.StockPrice||""}}</td> '
                + '<td align="center">{{product.UnitsDisplay}}</td></tr></tbody> '
                + '<tfoot><tr><td colspan="7" ms-widget="paging,sproductupaing,sproductOpts"></td></tr></tfoot></table> '
                + '</td></tr></table> '
        }
    }()

    /*下拉菜单*/
    new function () {
        avalon.ui.dropDownMenu = function (el, data, vmodels) {
            var opts = avalon.mix({}, avalon.ui.dropDownMenu.defaults, data.dropDownMenuOptions),
            model = avalon.define(data.dropDownMenuId, function (scope) {
                scope.menus = opts.menus
                scope.rootLabel = opts.rootLabel
                scope.expand = opts.expand
                // scope.enableHoverExpand = opts.enableHoverExpand
                scope.rootChange = opts.rootChange || function () {
                    model.expand = !model.expand
                }
                scope.itemChange = function (e) {
                    var vm = this.$vmodel,
                        itemVm = vm[vm.$itemName]
                    model.menus.forEach(function (item) {
                        item.curr = false
                    })
                    itemVm.curr = true
                    model.expand = false
                    model.itemChanged.call(this, e)
                }
                scope.itemChanged = opts.itemChanged || function () {
                }
            })

            avalon.nextTick(function () {
                avalon.innerHTML(el, opts.tmpl)
                avalon.scan(el, [model].concat(vmodels))
            })
            return model
        }

        avalon.ui.dropDownMenu.defaults = {
            tmpl: "<div class='dropdown_root' ms-click='rootChange' ms-hover='dropdown_root_hover'>{{rootLabel}}<span class='triangle-down' ms-class='triangle-up:expand'></span></div>" +
                "<ul class='dropdown_roles' ms-each-menu='menus' ms-visible='expand'>" +
                "<li ms-live-click='itemChange' ms-hover='hover' ms-class='curr_label:menu.curr' ms-class-noselected='!menu.curr' ms-class-last='$last' ms-title='menu.label'>{{menu.label|truncate(10)}} "
                + "<span ms-visible='menu.curr' ms-class='curr_role:menu.curr'>&radic;</span>"
                + "<span ms-if='menu.group' class='triangle-down' ms-hover='triangle-up'></span></li></ul>",
            menus: [],
            rootLabel: 'dropDownMenu',
            // enableHoverExpand:false,
            expand: false
        }

    }()

    new function () {
        avalon.ui.loading = function (el, data, vmodels) {
            var opts = avalon.mix({}, avalon.ui.loading.defaults, data.loadingOptions)
            model = avalon.define(data.loadingId, function (scope) {
                avalon.mix(scope, opts)
            })
            model.$watch('show', function (n) {
                if (n) {
                    setTimeout(function () {
                        model.show = false
                    }, opts.timeout)
                }
            })

            avalon.nextTick(function () {
                avalon(el).addClass('spinner').attr('ms-if', 'show')
                avalon.innerHTML(el, avalon.ui.loading.defaults.tmpl)
                avalon.scan(el, model)
            })

            return model
        }

        avalon.ui.loading.defaults = {
            tmpl: "<div></div><div></div><div></div><div></div><div></div>",
            show: true,
            timeout: 5
        }
    }

    /*角色列表*/
    new function () {
        avalon.ui.roleList = function (el, data, vmodels) {
            var opts = avalon.mix({}, avalon.ui.roleList.defaults, data.roleListOptions)
            , model = avalon.define(data.roleListId, function (scope) {
                avalon.mix(scope, opts)
                if (!scope.findRoleByName) {
                    scope.findRoleByName = function () {
                        loadRole()
                    }
                }
                if (!scope.toEnter) {
                    scope.toEnter = function (e) {
                        if (e.keyCode === 13)
                            loadRole()
                    }
                }
                if (!scope.unSelectAll) {
                    scope.unSelectAll = function () {
                        model.datasource.forEach(function (item) {
                            item.curr = false;
                        })
                    }
                }
            }),
            loadRole = function () {
                $.get(opts.url, { roleName: model.key })
                .done(function (ret) {
                    if (ret.result) {
                        if (!ret.data.Source || !ret.data.Source.length) {
                            model.datasource.removeAll()
                        } else {
                            ret.data.Source.forEach(function (d, i) {
                                d.curr = i === 0
                            })
                            model.datasource = ret.data.Source
                        }
                    }
                })
            }


            avalon.nextTick(function () {
                avalon.innerHTML(el, opts.tmpl)
                avalon.scan(el, [model].concat(vmodels))
                loadRole()
            })
            return model

        }

        avalon.ui.roleList.defaults = {
            $skipArray: ['tmpl'],
            datasource: [],
            url: '/Settings/Permission/',
            roleChang: function (e) {
                var vm = this.$vmodel,
                    item = vm[vm.$itemName],
                pvm = this.$vmodels[1]
                pvm.datasource.forEach(function (item) {
                    item.curr = false
                })
                item.curr = true
                pvm.roleChanged.call(this, e)
            },
            roleChanged: function () {
                var item = this.$vmodels[1]
                avalon.log('this = event dom obj , arguments[0] = event')
                avalon.log('roleName : ' + item.Name + ' roleId : ' + item.Id)
            },
            key: '',
            tmpl: '<div class="boxTitle full_screen_height" style="width:215px;"><h2 style="margin-bottom:0px;" ms-html="lang.FindByRole"></h2>'
            + '<table width="100%" border="0" cellspacing="0" cellpadding="0"><tbody><tr style="background:#F7F7F7;">'
            + '<td  height="44" align="center" ><div class="input-append" style="margin-bottom:0px;">'
            + '<input type="text" style="width:130px;" ms-attr-placeholder="lang.FindByRoleName" ms-duplex="key" ms-keypress="toEnter">'
            + '<button type="button" ms-click="findRoleByName" class="add-on ibtsearch" style="height:28px; font-size:12px; padding:3px 12px;" ms-html="lang.SearchBtn"></button>'
            + '</div></td></tr><tr><td colspan="2"><div class="folderbox" style="overflow-x:hidden;overflow-y:auto;"><ul>'
            + '<li ms-repeat-role="datasource" ms-hover="hover" ms-class-selected="role.curr" ms-live-click="roleChang"><a href="javascript:void(0)" ms-if="role.Name" ms-title="role.Name" ms-html="role.Name"></a></li></ul></div></td></tr></tbody></table></div>'
        }
    }()

    /*树Ztree*/
    new function () {
        avalon.ui.zTree = function (el, data, vmodels) {
            var $el = $(el), treeid = data.zTreeId, dataOps = avalon(el).data() || {};
            var options = $.extend(true, {}, avalon.ui.zTree.defaults, dataOps);
            $.extend(true, options, data.zTreeOptions);
            var treeopts = $.extend(true, {}, options.treeopts);
            delete options.treeopts;
            if (options.url) treeopts.async.url = options.url;
            var oldvm = avalon.vmodels[treeid];
            if (oldvm) oldvm.destroy();
            model = avalon.define(treeid, function (vm) {
                avalon.mix(vm, options)
                vm.$treeObj = null
                vm.createTree = function (ops) {
                    var treeOpt = $.extend({}, treeopts, ops || {});
                    var tree = model.$treeObj;
                    if (tree) {
                        tree.destroy();
                        model.$treeObj = tree = null;
                    }
                    var datasource = null;
                    if (model.datasource) datasource = model.datasource.$model;
                    model.$treeObj = tree = $.fn.zTree.init($el, treeOpt, datasource);
                    avalon.log("Create ZTree OK!");
                    if (model.onCreate) model.onCreate.call(model, model.$treeObj);
                    return tree;
                }
                vm.destroy = function () {
                    if ($el) {
                        $el.html("");
                        opts = null
                        $el = null
                        if (model) {
                            //if (model.$treeObj) model.$treeObj.destroy();
                            model.$treeObj = null
                            avalon.vmodels[treeid] = model = null
                        }
                    }
                }
            })
            model.$watch('datasource', function (n) {
                if(n)model.createTree();
            })
            model.createTree()
            
            return model
        }
        avalon.ui.zTree.defaults = {
            datasource: null,
            url:"",
            treeopts: {
                async: {
                    url: '',
                    type: 'GET',
                    enable: true,
                    autoParam: ["Id=id"],
                    dataFilter: function (treeId, parentNode, responseData) {
                        var ret = []
                        if (responseData.data &&responseData.data.length) {
                            ret=responseData.data
                        }
                        return ret
                    }
                },
                data: {
                    simpleData: {
                        enable: true,
                        idKey: 'Id'
                    },
                    key: {
                        name: 'Name'
                    }
                },
                view: {}
            }
        }
    }

    /*产品分类树*/
    new function () {
        avalon.ui.productCategoryTree = function (el, data, vmodels) {
            var $el = $(el),
                //opts = avalon.mix({}, avalon.ui.productCategoryTree.defaults, data.productCategoryTreeOptions),
                createTree = function (treeOpt) {
                    var tree = $.fn.zTree.init($el, treeOpt, model.datasource)
                    $el.undelegate('.onnodeevent', 'click').delegate('.onnodeevent', 'click', function () {
                        var $cur = $(this),
                            data = $cur.data(),
                            call = model.events[data.call] || ''
                        if (call) {
                            avalon.log('正在执行函数：' + data.call)
                            call($cur, data)
                            avalon.log('已完执行函数：' + data.call)
                        } else {
                            avalon.log('没有在events中找到函数：' + data.call)
                        }
                    })
                    avalon.log('已成功构建产品分类树')
                    return tree;
                }
            data.productCategoryTreeOptions.treeopts = $.extend(true, {}, avalon.ui.productCategoryTree.defaults.treeopts,
                data.productCategoryTreeOptions.treeopts);
            var model = avalon.vmodels[data.productCategoryTreeId];
            if (model) model.destroy();
            model = avalon.define(data.productCategoryTreeId, function (vm) {
                avalon.mix(vm, data.productCategoryTreeOptions)
                vm.$treeObj = null
                vm.destroy = function () {
                    if ($el) {
                        $el.undelegate('.onnodeevent', 'click').html('')
                        opts = null
                        $el = null
                        if (model) {
                            model.$treeObj = null
                            model = null
                        }
                    }
                }
            })
            model.$watch('datasource', function () {
                if (!model) return;
                var treeOpts = model.treeopts ? model.treeopts.$model : null;
                model.$treeObj = createTree(treeOpts)
            })
            //avalon.nextTick(function () {
            model.$treeObj = createTree(model.treeopts.$model)
            //})
            return model
        }
        avalon.ui.productCategoryTree.defaults = {
            $skpiArray: ['treeopts', 'events'],
            datasource: null,
            treeopts: {
                async: {
                    url: '/Product/Category',
                    type: 'GET',
                    enable: true,
                    dataFilter: function (treeId, parentNode, responseData) {
                        var ret = []
                        if (responseData.data) {
                            if (responseData.data.length) {
                                ret = ret.concat(responseData.data)
                            }
                        }
                        return ret
                    }
                },
                data: {
                    simpleData: {
                        enable: true,
                        idKey: 'Id'
                    },
                    key: {
                        name: 'Name'
                    }
                },
                view: {
                    addHoverDom: function (treeId, treeNode) {
                        var id = treeNode.Id,
                            $addBtn = $("#addBtn_" + id), addStr, dataStr
                        if ($addBtn.length > 0) {
                            $addBtn.show()
                            $("#editBtn_" + id).show()
                            $("#removeBtn_" + id).show()
                            return
                        }
                        dataStr = ' data-id="' + id + '" data-treeid="' + treeId + '"' +
                            ' data-name="' + treeNode.Name + '" data-tadd=' + treeNode.ADD + ' data-tedit=' + treeNode.EDIT + ' data-tdelete=' + treeNode.DELETE + ''
                        addStr = "<span data-call='add' class='button add onnodeevent' id='addBtn_" + id
                            + "' " + dataStr + " title='新增子分类' onfocus='this.blur();'></span><span data-call='edit' class='button edit onnodeevent' id='editBtn_" + id
                            + "' " + dataStr + " title='编辑分类' onfocus='this.blur();'></span><span data-call='remove' class='button remove onnodeevent' id='removeBtn_" + id
                            + "' " + dataStr + " title='移除分类' onfocus='this.blur();'></span>"
                        $("#" + treeNode.tId + "_span").after(addStr)
                    },
                    removeHoverDom: function (treeId, treeNode) {
                        var id = treeNode.Id
                        $("#addBtn_" + id).hide()
                        $("#editBtn_" + id).hide()
                        $("#removeBtn_" + id).hide()
                    },
                    selectedMulti: false
                }
            },
            events: {}
        }
    }

    /*下拉产品分类树*/
    new function () {
        avalon.ui.dropDownPCategoryTree = function (el, data, vmodels) {
            var options = avalon.mix(true, {}, avalon.ui.dropDownPCategoryTree.defaults, data.dropDownPCategoryTreeOptions)
            options.dropDownTreeId = data.dropDownPCategoryTreeId
            var $vm = avalon.ui.dropDownTree(el, options, vmodels)
            return $vm;
        }

        avalon.ui.dropDownPCategoryTree.defaults = {
            q: '输入名称检索',
            treeopts: {
                async: {
                    url: '/Product/Category',
                    enable: true,
                    type: 'get',
                    dataFilter: function (treeId, parentNode, responseData) {
                        var ret = []
                        if (responseData.data) {
                            if (responseData.data.length) {
                                ret = ret.concat(responseData.data)
                            }
                        }
                        return ret
                    }
                },
                data: {
                    simpleData: {
                        enable: true,
                        idKey: 'Id'
                    },
                    key: {
                        name: 'Name'
                    }
                }
            }
        }
    }

    /*部门树*/
    new function () {
        var treemsgLoad = "数据载入中…", treemsgNoData = "暂无数据";
        avalon.ui.groupTree = function (el, data, vmodels) {
            var $vm, $el = $(el),
                createTree = function (treeopts, events) {
                    if ($vm.$tree && $vm.$tree.destroy) $vm.$tree.destroy();
                    var datasource = $vm.datasource || [];
                    datasource = datasource.$model || [];
                    var tree = $.fn.zTree.init($el, treeopts, datasource)
                    $el.undelegate('.ongroupevent', 'click').delegate('.ongroupevent', 'click', function () {
                        var $cur = $(this),
                            data = $cur.data(),
                            call = events[data.call] || ''
                        if (call) {
                            avalon.log('正在执行函数：' + data.call)
                            call($cur, data)
                            avalon.log('已完执行函数：' + data.call)
                        } else {
                            avalon.log('没有在events中找到函数：' + data.call)
                        }
                    })
                    avalon.log('已成功构建部门树')
                    return tree;
                },
                tLoadEl = $('<div ms-if="treeLoading" style="position: absolute;width: 80px;height: 20px;">{{treeLoadingMsg}}</div>');
            var options = $.extend(true, {}, avalon.ui.groupTree.defaults,
                data.groupTreeOptions);
            var treeopts = $.extend(true, {
                async: {
                    /*/Settings/GetGroupPostUser/9060001*/
                    url: function (treeId, treeNode) {
                        var url = $vm.$url;
                        return url
                    },
                    type: 'GET',
                    enable: true,
                    dataFilter: function (treeId, parentNode, responseData) {
                        var ret = [], list = responseData.data.groups || responseData.data;
                        if (responseData.result) {
                            ret = ret.concat(list);
                        }
                        return ret
                    }
                }
            }, options.treeopts || {});
            if (treeopts.async.enable) {
                var oldurl = treeopts.async.url;
                treeopts.async.url = function (treeId, treeNode) {
                    if (typeof (oldurl) == "function") return oldurl.apply(this, arguments);
                    else return oldurl;
                }
            }
            options.treeopts = treeopts;
            if (options.dataAuth)
                options.$url += "/" + options.dataAuth;
            $vm = avalon.define(data.groupTreeId, function (vm) {
                avalon.mix(vm, options)
                vm.destroy = function () {
                    if ($el) $el.undelegate('.ongroupevent', 'click').html('')
                    opts = null
                    $el = null
                    if ($vm) {
                        $vm.$treeObj = null;
                        $vm = null
                    }
                }
                vm.showLoading = function (l) {
                    if (l==null) {
                        $vm.treeLoading = true;
                        $vm.treeLoadingMsg = treemsgLoad;
                    } else {
                        $vm.treeLoading = false;
                        $vm.treeLoadingMsg = l > 0 ? "" : treemsgNoData;
                    }
                }
                vm.$tree = null;
            })
            $vm.$watch('datasource', function () {
                $vm.$tree = createTree($vm.treeopts.$model, $vm.events)
            })
            //$el.after(tLoadEl);
            avalon.nextTick(function () {
                $vm.$tree = createTree($vm.treeopts.$model, $vm.events);
                var offset = $el.offset();
                offset.top += $el.height() / 2;
                offset.left += $el.width() / 2;
                tLoadEl.offset(offset)
            })
            return $vm
        }
        avalon.ui.groupTree.defaults = {
            $skpiArray: ['treeopts', 'events'],
            datasource: [],
            dataAuth:'',
            $url: "/Settings/GetGroupPost",
            $tree: null,
            treeLoading: false,
            treeLoadingMsg:"",
            treeopts: {
                data: {
                    simpleData: {
                        enable: true,
                        idKey: 'Id',
                        pIdKey: 'ParentId'
                    },
                    key: {
                        name: 'Name'
                    }
                },
                view: {
                    addHoverDom: function (treeId, treeNode) {
                        var id = treeNode.Id,
                            $addBtn = $("#addBtn_" + id), addStr, dataStr
                        if ($addBtn.length > 0) {
                            $addBtn.show()
                            $("#editBtn_" + id).show()
                            $("#removeBtn_" + id).show()
                            return
                        }
                        dataStr = ' data-id="' + id + '" data-treeid="' + treeId + '"' +
                            ' data-groupname="' + treeNode.Name + '"'
                        addStr = "<span data-call='add' class='button add ongroupevent' id='addBtn_" + id
                            + "' " + dataStr + " title='添加下属部门' onfocus='this.blur();'></span><span data-call='edit' class='button edit ongroupevent' id='editBtn_" + id
                            + "' " + dataStr + " title='编辑部门' onfocus='this.blur();'></span><span data-call='remove' class='button remove ongroupevent' id='removeBtn_" + id
                            + "' " + dataStr + " title='移除部门' onfocus='this.blur();'></span>"
                        $("#" + treeNode.tId + "_span").after(addStr)
                    },
                    removeHoverDom: function (treeId, treeNode) {
                        var id = treeNode.Id
                        $("#addBtn_" + id).hide()
                        $("#editBtn_" + id).hide()
                        $("#removeBtn_" + id).hide()
                    },
                    selectedMulti: false
                }
            },
            events: {}
        }
    }

    /*分页*/
    new function () {

        var createPages = function () {
            var vm = this, c = vm.currentindex, p = Math.ceil(vm.total / vm.pagesize), pages = [],
                s = vm.showpages, max = p, left = c, right = c
            if (typeof max === 'undefined' || isNaN(max)) {
                pages[0] = 0
            }
            if (max === 0) {
                pages.push(c)
            } else if (p <= s) {
                for (var i = 0; i < p; i++) {
                    pages.push(i)
                }
            } else {
                pages.push(c)
                while (true) {
                    if (pages.length >= s) {
                        break
                    }
                    if (left >= 1) {//在日常生活是以1开始的
                        pages.unshift(--left)
                    }
                    if (pages.length >= s) {
                        break
                    }
                    if (right + 1 < max) {
                        pages.push(++right)
                    }
                }
            }
            vm.maxpage = max;
            vm.pages = pages;
            /*avalon.nextTick(function () {
            avalon.log("currentindex:" + c);
            avalon.log("total:" + vm.total);
            avalon.log("pagesize:" + vm.pagesize);
            avalon.log("pagetotal:" + p);
            avalon.log("max:" + max);
            avalon.log("pages:" + pages.join(","));
            });*/
        },
        paging = function (cur, old) {
            if (cur != old) {
                createPages.call(this)
                if (!setTota) {
                    if (this.initload === false && this.currentindex === 0) {
                        delete this.initload
                        return
                    }
                    this.paging.call(this, cur+1, this.pagesize, old)
                } else {
                    setTota = false
                }
            }
        },
        setTota = false,setIndex=false

        avalon.ui.paging = function (el, data, $vmodels) {
            var $vm,
            $el = avalon(el),
            elDataOps = $el.data() || {},
            options = avalon.mix({}, avalon.ui.paging.defaults, elDataOps, data, data.pagingOptions)
            delete options.pagingId
            delete options.pagingOptions
            delete options.element
            setTota = false
            var pvm = $vmodels[0];
            if (pvm && options.gridid) {
                var grid = pvm[options.gridid];
                if (grid.$pageOps) avalon.mix(options, grid.$pageOps);
                if (grid.pageid) data.pagingId = grid.pageid;
            }
            $vm = avalon.define(data.pagingId, function (vm) {
                avalon.mix(vm, options)
                vm.destroy = function () {
                    var dui = $(el), pui = dui.parent();
                    if (pui.prop("tagName") == "TR") pui.remove();
                    else dui.remove();
                    dui = null;
                    pui = null;
                    delete avalon.vmodels[data.pagingId];
                }
                if (!vm.paging) {
                    vm.paging = function () {
                        avalon.log("this =$vmodel,pageindex = this.currentindex,pagesize = this.pagesize")
                    }
                }
                vm.reload = function () {
                    $vm.paging.call($vm)
                }
                vm.sizeChanged = function (event) {
                    if (!vm.pagelink) {
                        event.preventDefault()
                    }
                    var size = parseInt(avalon(this).val(), 10)
                    if (isNaN(size)) {
                        avalon.log(size)
                        return
                    }
                    if (size != vm.pagesize) {
                        vm.pagesize = size
                        paging.call($vm, vm.currentindex, -1)
                    }
                }
                vm.setIndex = function (page) {
                    $vm.currentindex = page - 1;
                }
                vm.gotoPage = function (page) {
                    var old = $vm.currentindex
                    vm.currentindex = page
                    paging.call($vm, page, old)
                }
                vm.jumpPage = function (event) {
                    if (!vm.pagelink) {
                        event.preventDefault()
                    }
                    var page = this.$vmodel.$model.item
                    if (page !== vm.currentindex) {
                        if (isNaN(page)) {
                            avalon.log(page)
                        } else {
                            $vm.gotoPage(page)
                        }
                    }
                }
                vm.jumpFirstPage = function (event) {
                    if (!vm.pagelink) {
                        event.preventDefault()
                    }
                    //vm.currentindex = 0
                    $vm.gotoPage(0)
                }
                vm.jumpLastPage = function (event) {
                    if (!vm.pagelink) {
                        event.preventDefault()
                    }
                    //vm.currentindex = vm.maxpage - 1
                    $vm.gotoPage($vm.maxpage - 1)
                    if (isNaN(vm.maxpage)) {
                        avalon.log(vm.maxpage)
                    }
                }
            })
            $vm.$watch("total", function (s, old) {
                avalon.log("currenttotal:" + s)
                avalon.log("oldtotal:" + old)
                if (!s && s !== 0) {
                    this.total = 0
                    return
                }
                if (s != old) {
                    setTota = true
                    if (s <= $vm.pagesize || ($vm.pagesize * $vm.currentindex > s)) {
                        $vm.currentindex = 0
                    }
                    paging.call(this, s || 0, old || 0)
                }
            })
            //$vm.$watch("currentindex", function (s, old) {
            //    avalon.log("currentindex:" + s)
            //    avalon.log("oldindex:" + old)
            //    paging.call(this, s, old)
            //})
            avalon.nextTick(function () {
                if (!$el.hasClass($vm.pagingclass)) {
                    $el.addClass($vm.pagingclass)
                    avalon.innerHTML(el, options.template)
                    avalon.scan(el, $vm)
                    createPages.call($vm)
                    //$vm.paging.call($vm)
                    paging.call($vm, 0, -1)
                }
            })
            return $vm
        }

        avalon.ui.paging.defaults = {
            $skipArray: ['template'],
            pagesize: 20, //每页显示多少条目
            showpages: 10, //一共显示多页
            currentindex: 0,
            pagelink: '', //页码链接
            setsizetext: '每页显示数量',
            current: 'current', //当前页和鼠标经过页码时样式
            showtotal: true,
            enablesetsize: true,
            initload: true, //分页创建时是否读取数据
            total: 0,
            pages: [],
            firsttext: "首页",
            lasttext: "末页",
            pagesizeopts: [20, 50, 100, 200, 500, 1000],
            firstpage: true,
            lastpage: true,
            maxpage: 0,

            pagingclass: 'ipage',
            template: '<div class="pageitems"><a href="#" ms-visible="firstpage" class="first_last" ms-click="jumpFirstPage">{{firsttext}}</a>'
            + '<div class="pagenums"><a ms-repeat-item="pages" ms-href="pagelink + item" ms-click="jumpPage" ms-class-active="item === currentindex" ms-hover="current">{{item+1}}</a>'
            + '</div><a href="#" ms-visible="lastpage" class="first_last" ms-click="jumpLastPage">{{lasttext}}</a>'
            + '</div><div class="pageoption" ms-visible="showtotal||enablesetsize"><span ms-if="enablesetsize">{{setsizetext}}</span>'
            + ' <select ms-change="sizeChanged" ms-if="enablesetsize"><option ms-repeat-item="pagesizeopts" ms-value="item">{{item}}</option>'
            + '</select> <span ms-visible="showtotal" style="margin-left:5px;">总共{{total}}条</span></div>'
        }
    }

    /*用户信片*/
    new function () {
        avalon.ui.userCard = function (el, data, vmodels) {
            var elWrapper = avalon(el),
            nodeData = elWrapper.data(),
            userId = nodeData['userid'],curId,
            model = avalon.vmodels.userCard,
            loadUser = function (userId) {
                if (!userId) {
                    avalon.log('缺少userid ： ' + userId)
                    return
                }
                if (curId == userId) return;
                else curId = userId;
                $.get('/Settings/GetUser/' + userId)
                .done(function (ret) {
                    if (ret.result) {
                        if (ret.data.Group) {
                            ret.data.GroupName = ret.data.Group.Name
                        }
                        switch (ret.data.Sex) {
                            case 0:
                                ret.data.Picture = '/Content/Themes/Base/Images/man_default.png'
                                break
                            case 1:
                                ret.data.Picture = '/Content/Themes/Base/Images/lady_default.png'
                                break
                        }
                        model.entity = avalon.mix({}, factory.create('UserCard'), ret.data);
                        model.entity.RoleName = ret.data.Role.Name;
                    }
                })
            },
            setPosition = function (el) {
                var top = 0,
                postion = el.offset(),
                height = $('body').height(),
                card = $(document.getElementById('businessCardWarp'))
                //判断浏览器高度，来确定显示在上面还是下面
                if ((height - postion.top) > 205)
                    top = postion.top + 20
                else
                    top = postion.top - 205
                card.css({ 'top': top + 'px', 'left': postion.left + 'px' })
            }

            $(el).hover(function () {
                var $that = $(this)
                nodeData = $that.data(),
                userId = nodeData['userid']
                if (userId) {
                    avalon.log('curr user id : ' + userId)
                    loadUser(userId)
                    setPosition($that)
                    model.show = true
                }
            }, function () {
                model.show = false
            })

            if (model) {
                return model
            }

            model = avalon.define('userCard', function (scope) {
                scope.show = false
                scope.entity = {}
            })

            model.entity = factory.create('UserCard')

            avalon.nextTick(function () {
                var card
                $(document.body).append(avalon.ui.userCard.defaults.tmpl)
                card = document.getElementById('businessCardWarp')
                avalon.scan(card, model)
            })

            return model
        }

        avalon.ui.userCard.defaults = {
            $skipArray: ['tmpl'],
            tmpl: '<div class="businessCardWarp" id="businessCardWarp" ms-visible="show">'
    + '<div class="businessCardLeft"><p class="pname">{{entity.FullName|truncate(10)}}({{entity.Sex == 0 ? "男" : "女"}})</p>'
    + '<p class="pname2">{{entity.RoleName}}<br />{{entity.GroupName}}</p><div class="picture">'
    + '<img ms-src="entity.Picture" width="100" height="100" style="width: 100px; height: 100px;"></div>'
    + '</div><div class="businessCardRight"><ul><li><span>办公电话：</span>{{entity.TelPhone}}</li>'
    + '<li><span>状态：</span><b ms-class-green="entity.IsAvailable" ms-class-red="!entity.IsAvailable">{{entity.IsAvailable ? "启用" : "禁用"}}</b></li><li><span>联系手机：</span>{{entity.Phone}}</li><li><span>电子邮箱：</span>{{entity.Email}}</li><li><span>创建时间：</span>{{entity.AddTime}}</li>'
    + '</ul></div></div>'
        }
    }

    /// <summary>
    /// 下拉部门树
    /// </summary>
    new function () {
        avalon.ui.dropDownGroupTree = function (el, data, vmodels) {
            var options = avalon.mix(true, {}, avalon.ui.dropDownGroupTree.defaults, data.dropDownGroupTreeOptions)
            , $vm;
            options.dropDownTreeId = data.dropDownGroupTreeId;
            var treeopts = $.extend(true, {
                async: {
                    url: function (treeId, treeNode) {
                        var url = $vm.$url, q = $vm.q, qcopy = $vm.qcopy;
                        url += "?getPost=" + $vm.getPost;
                        if (q && q != qcopy) url += "&q=" + encodeURIComponent(q);
                        return url
                    },
                    enable: true,
                    type: 'get',
                    dataFilter: function (treeId, parentNode, responseData) {
                        var ret = []
                        if (responseData && responseData.result) {
                            ret = $.isArray(responseData.data) ? responseData.data : responseData.data.groups;
                        }
                        ret.forEach(function (g) {
                            if (options.getPost && !options.onlyGroup) g.children = g.Posts || [];
                        });
                        if (typeof ($vm.dataFilter) == "function") {
                            ret = $vm.dataFilter.call(this, ret, responseData, treeId, parentNode);
                        }
                        return ret
                    }
                },
                data: {
                    simpleData: {
                        enable: true,
                        idKey: 'Id',
                        pIdKey: 'ParentId'
                    },
                    key: {
                        name: 'Name'
                    }
                }
            }, options.treeopts || {});
            options.treeopts = treeopts;
            if (options.dataAuth)
                options.$url += "/" + options.dataAuth;
            if (options.checkType) {
                var check = options.treeopts.check || {};
                options.treeopts.check=$.extend(true, check, {
                    enable: true,
                    chkStyle: options.multiple ? 'checkbox' : 'radio',
                    radioType: "all"
                });
                switch (options.checkType) {
                    case "all":
                        options.getPost = true;
                        break;
                    case "group":
                        break;
                    case "post":
                        options.getPost = true;
                        options.dataFilter = function (gs, ret) {
                            gs.forEach(function (g) {
                                g.nocheck = true;
                            });
                            return gs;
                        }
                        break;
                }
            }
            $vm = avalon.ui.dropDownTree(el, options, vmodels)
            // avalon.vmodels[options.dropDownTreeId + 'panel'].toggle(true)
            return $vm;
        }

        avalon.ui.dropDownGroupTree.defaults = {
            q: '输入部门关键字检索',
            dropDownTreeId: Math.random() + '',
            $url: "/Settings/GetGroupPost",
            getPost: false,
            onlyGroup:false,
            dataFilter: false,
            multiple: false,
            checkType: "",//group,post,all
            treeopts: {}
        }

    }

    /// <summary>
    /// 下拉地区树
    /// </summary>
    new function () {
        avalon.ui.dropDownAreasTree = function (el, data, vmodels) {
            var options = avalon.mix(true, {}, avalon.ui.dropDownAreasTree.defaults,
                data.dropDownAreasTreeOptions)
            , model
            options.dropDownTreeId = data.dropDownAreasTreeId
            var $vm = avalon.ui.dropDownTree(el, options, vmodels)
            // avalon.vmodels[options.dropDownTreeId + 'panel'].toggle(true)
            return $vm
        }

        avalon.ui.dropDownAreasTree.defaults = {
            q: '输入地区关键字检索',
            enablesearch: false,
            dropDownTreeId: Math.random() + '',
            treeopts: {
                async: {
                    url: function (treeId, treeNode) {
                        var url = '/Settings/GetAllArea'
                        return url
                    },
                    enable: true,
                    type: 'post',
                    dataFilter: function (treeId, parentNode, responseData) {
                        var ret = []
                        if (responseData.data && responseData.data.length) {
                            ret = responseData.data
                            ret[0].open = true
                        }
                        return ret
                    }
                },
                data: {
                    simpleData: {
                        enable: true,
                        idKey: 'Id',
                        pIdKey: 'ParentId'
                    },
                    key: {
                        name: 'Data'
                    }
                }
            }
        }

    }

    /// <summary>
    /// 下拉角色树
    /// </summary>
    new function () {
        avalon.ui.dropDownRoleTree = function (el, data, vmodels) {

        }
    }

    /// <summary>
    /// 下拉用户树
    /// </summary>
    new function () {
        avalon.ui.dropDownUserTree = function (el, data, vmodels) {
            console('fuck')
        }
    }

    /// <summary>
    /// 下拉职位树
    /// </summary>
    new function () {
        avalon.ui.dropDownPostTree = function (el, data, vmodels) {
            console('fuck')
        }

    }

    /// <summary>
    /// 下拉部门职位树
    /// </summary>
    new function () {
        avalon.ui.dropDownGroupPostTree = function (el, data, vmodels) {
            console('fuck')
        }
    }

    /// <summary>
    /// 下拉部门职位用户树
    /// </summary>
    new function () {
        avalon.ui.dropDownGroupPostUserTree = function (el, data, vmodels) {
            var options = {}, model
            options.dropDownTreeOptions = avalon.mix(true, {}, avalon.ui.dropDownGroupPostUserTree.defaults, data.dropDownGroupPostUserTreeOptions)
            options.dropDownTreeId = data.dropDownGroupPostUserTreeId
            delete options.dropDownTreeOptions.dropDownGroupPostUserTreeId
            var $vm = avalon.ui.dropDownTree(el, options, vmodels)
            return $vm;
        }

        avalon.ui.dropDownGroupPostUserTree.defaults = {
            q: '输入部门/职位/员工名检索',
            treeopts: {
                async: {
                    url: function (treeId, treeNode) {
                        var url = '/Settings/GetGroupPostUser',
                            vm = avalon.vmodels[treeId.replace('zTree', '')]
                        if (vm && vm.q && vm.q !== vm.qcopy) {
                            if (avalon.vmodels.CBCRM.$debug)
                                avalon.log('empName : ' + vm.q)
                            url += '?empName=' + vm.q
                        }
                        return url
                    },
                    enable: true,
                    type: 'get',
                    dataFilter: function (treeId, parentNode, responseData) {
                        var ret = [], len, curr
                        if (responseData.data && responseData.data.groups.length) {
                            ret = ret.concat(responseData.data.groups)
                        }
                        len = ret.length
                        if (len) {
                            while (len) {
                                curr = ret[--len]
                                curr.Posts.forEach(function (p, i) {
                                    curr.Posts[i].ParentId = p.Boss ? p.Boss.Id : p.Group
                                    p.Users.forEach(function (u, i) {
                                        var u = p.Users[i]
                                        u.ParentId = u.PositionId
                                        u.Name = u.FullName
                                    })
                                    ret = ret.concat(p.Users)
                                })
                                ret = ret.concat(curr.Posts)
                            }
                        }
                        return ret
                    }
                },
                data: {
                    simpleData: {
                        enable: true,
                        idKey: 'Id',
                        pIdKey: 'ParentId'
                    },
                    key: {
                        name: 'Name'
                    }
                }
            }
        }
    }

    /// <summary>
    /// 下拉树
    /// </summary>
    new function () {
        var treemsgLoad = "数据载入中…", treemsgNoData = "暂无数据";
        avalon.ui.dropDownTree = function (el, data, vmodels) {
            var $el = avalon(el),_isInit=false,
                options = avalon.mix(true, {}, avalon.ui.dropDownTree.defaults, data.dropDownTreeOptions || data),
                panelId = data.dropDownTreeId + "panel",
                dropPName = 'dropDownPanel',
                $node,
                $tree,
                $pvm,$vm = avalon.vmodels[data.dropDownTreeId]
            if ($vm) {
                return $vm
            }
            var zAsync=options.treeopts && options.treeopts.async;
            if (zAsync && zAsync.enable) {
                var oldurl = zAsync.url;
                zAsync.url = function (treeId, treeNode) {
                    $vm.loadingTree();
                    if (typeof (oldurl) == "function") return oldurl.call(this, treeId, treeNode);
                    else return oldurl;
                }
                if (typeof (zAsync.dataFilter) == "function") {
                    var oldft = zAsync.dataFilter;
                    zAsync.dataFilter = function (treeId, parentNode, responseData) {
                        if ($vm.dataFilter) $vm.dataFilter.call(this, treeId, parentNode, responseData);
                        var rows = oldft.call(this, treeId, parentNode, responseData) || [];
                        //初始化的时候要选择的项
                        $vm.initChecked.call(this, treeId, parentNode, responseData,rows);
                        $vm.loadingTree(rows.length);
                        return rows;
                    }
                }
                options.treeopts.async = zAsync;
            }
            $vm = avalon.define(data.dropDownTreeId + '', function (vm) {
                vm.initChecked = function (treeId, parentNode, responseData,rows) {
                    if (!$vm.checkedIds) return;
                    var ids = $vm.checkedIds.call(this, treeId, parentNode, responseData, rows);
                    if (!ids || !ids.length) return;
                    var isStr = typeof (ids[0]) == "string";
                    rows.forEach(function (item) {
                        var id = item.Id;
                        if (!id) return;
                        if (isStr) id = id.toString();
                        if (ids.indexOf(id) != -1) {
                            item.checked = true;
                        }
                    });
                }
                avalon.mix(vm, options)
                vm.destroy = function () {
                    var pvm = avalon.vmodels[data.dropDownTreeId + 'panel']
                    if ($vm && $vm.treeId) {
                        $.fn.zTree.destroy($vm.treeId)
                        $vm = $node = $tree = $pvm = null
                        delete avalon.vmodels[data.dropDownTreeId]
                    }
                    if (pvm) {
                        pvm.destroy()
                        $pvm = null
                        delete avalon.vmodels[data.dropDownTreeId + 'panel']
                    }
                }
                vm.qcopy = vm.q
                vm.datasourceCopy = vm.datasource
                vm.treeId = data.dropDownTreeId + 'zTree'
                vm.search = function (e) {
                    var self = this.$vmodel
                    if (self.time) {
                        clearTimeout(self.time)
                    }
                    vm.time = setTimeout(function () {
                        self.q = avalon(e.target).val()
                        self.loadData.call(self)
                        delete self.time
                    }, 800)
                }
                vm.focus = function (e) {
                    if (vm.q === vm.qcopy) {
                        vm.q = ""
                    }
                }
                vm.blur = function (e) {
                    if (!vm.q) {
                        vm.q = vm.qcopy
                    }
                }
                vm.loadData = function () {
                    var vvm = this
                        , ztree = $vm.getTree();
                    if (vvm.q === vvm.qcopy || !vvm.treeId) {
                        return false
                    }
                    if (ztree)
                        ztree.reAsyncChildNodes(null, "refresh")
                }
                vm.reload = function () {
                    var ztree = $vm.getTree();
                    if (ztree)
                        ztree.reAsyncChildNodes(null, "refresh");
                }
                vm.getTree = function () {
                    return $.fn.zTree.getZTreeObj($vm.treeId)
                }
                vm.loadingTree=function(l){
                    if(l==null){
                        $vm.dataCount = 0;
                        $vm.treemsg = treemsgLoad;
                    }else{
                        $vm.dataCount = l;
                        $vm.treemsg = l ? "" : treemsgNoData;
                    }
                }
                vm.okClick = function (e) {
                    var ret = $vm.okCall.call(this, $vm.getTree(), $pvm);
                    if (ret===false) $pvm.stopHide = true;
                    else $pvm.hide();
                }
                vm.cancelClick = function (e) {
                    var ret = $vm.cancelCall.call(this, $vm.getTree(), $pvm);
                    if (ret === false) $pvm.stopHide = true;
                    else $pvm.hide();
                }
            })
            $vm.$watch("datasource", function (n) {
                var self = this, l = -1;
                if (n && n.length != null) l = n.length;
                $vm.loadingTree(l);
                $.fn.zTree.init($(self.treeId), $vm.treeopts, n);//self.datasource.$model
            })
            $pvm = avalon.ui[dropPName](el, {
                dropDownPanelOptions: {
                    target: options.target,
                    height: $vm.height,
                    width: $vm.width,
                    initevent: options.initevent
                },
                dropDownPanelId: panelId
            }, [$vm].concat(vmodels))
            $pvm.showBefore = function () {
                if (!_isInit) {
                    _isInit = true;
                    this.content = options.template
                    $node = $(this.panel.firstChild)
                    avalon.scan($node[0], $vm)
                    $tree = $vm.treeId ? $("#" + $vm.treeId) : $node.find("." + $vm.treeclass)
                    if ($tree.length) {
                        $.fn.zTree.init($tree, $vm.treeopts.$model, $vm.datasource ? $vm.datasource.$model : null);
                    }
                    //$el.data("loaded", 1)
                    $el = $pvm.showBefore = $node = null;
                    if ($vm.onInit) $vm.onInit.call(this, $vm.getTree(), $pvm);
                }
                //if ($vm.onShow) $vm.onShow.call(this, $vm.getTree(), $pvm);
            }
            return $vm
        }
        
        avalon.ui.dropDownTree.defaults = {
            $skpiArray: ['treeopts', 'template'],
            template: '<div><div class="boxTitlenob" ms-if="enablesearch" ms-css-width="width" ms-css-margin="searchmargin"><h2><span class="rseachbox">'
        + '<input type="text" style="margin-bottom: 0px;color:#999999;" ms-keyup="search" ms-focus="focus" ms-blur="blur" ms-duplex="q" ms-attr-placeholder="q" /><button type="button" class="inputbt"></button>'
        + '</span></h2></div><ul ms-attr-l="dataCount" ms-attr-id="treeId" ms-attr-class="treeclass" ms-css-width="treewidth" ms-css-height="treeheight"></ul>' 
        +'<div ms-if="dataCount==0" style="position: absolute;left: 40%;top: 40%;width: 80px;height: 20px;">{{treemsg}}</div>'
        + '<div ms-if="showBtnBar" style="float:right;margin-top:10px;"><button class="btn btn-primary" ms-click="okClick">确定</button><button ms-click="cancelClick" class="btn">取消</button></div></div>',
            searchmargin: false,
            enablesearch: true,
            target: '',
            treeclass: "ztree",
            q: "输入关键字检索",
            width: 260,
            height: false,
            treewidth: 250,
            treeheight: 350,
            datasource: null,
            dataCount: 0,
            treemsg: treemsgLoad,
            //ztree配置项
            treeopts: {},
            showBtnBar:false,
            okBtn: "",
            cancelBtn: "",
            okCall: function (tree, pannel) { return true; },
            cancelCall: function (tree, pannel) { return true;},
            onInit: function (tree, pannel) { },
            checkIds: false
        }
    }

    /// <summary>
    /// 下拉弹出层
    /// </summary>
    new function () {
        var show = function (e) {
            var $target = e.$target.length ? e.$target : e.$el,
                targetWth = $target.outerWidth(),
                $targetoffset = $target.offset(),
                left = $targetoffset.left,
                top = $targetoffset.top,
                $menuContent = $(e.target),
                contentWth = $menuContent.outerWidth(),
                $window = $(window),
                windowWth = $window.outerWidth(),
                right = left + contentWth,
                $vm = e.$vmodel
            if (right > windowWth) {
                //left -= (windowWth - left + targetWth) - (right - windowWth)
                left -= right - windowWth
            }
            $vm.left = left
            $vm.top = $targetoffset.top + $target.outerHeight()
            if ($.isFunction($vm.showBefore))
                $vm.showBefore.call($vm, e)
            $vm.isshow = true
            if ($.isFunction($vm.showAfter))
                $vm.showAfter.call($vm, e)
            $("body").bind("mousedown", { $vmodel: $vm }, hide)
        },
        hide = function (e) {
            var $vm = e.data.$vmodel;
            if ($vm.stopHide) {
                $vm.stopHide = false;
                return;
            }
            //var $target = $(e.target)
            $vm.isshow = false
            $("body").unbind("mousedown", hide)
        }

        avalon.ui.dropDownPanel = function (el, data, vmodels) {
            var $el = avalon(el),
                $container,
                $node,
                $target,
                options = avalon.mix({}, avalon.ui.dropDownPanel.defaults, data.dropDownPanelOptions),
                $vm
            $container = $(options.container)
            //$target = $(options.target)
            $node = $(options.template)
            $container.append($node)
            $node.bind("show", show)
            if (options.initevent) {
                $el.bind("click", function (e) {
                    $vm.toggle(true)
                })
            }
            $vm = avalon.define(data.dropDownPanelId, function (vm) {
                avalon.mix(vm, options)
                vm.$skipArray = ['stopHide']
                vm.stopHide = false;
                vm.dropDownPanelId = data.dropDownPanelId
                vm.destroy = function () {
                    $vm.container = null
                    $el.unbind("click")
                    $("#" + $vm.dropDownPanelId).unbind('show').remove()
                    $el = null
                }
                vm.mousedown = function (e) {
                    e.stopPropagation()
                }
                vm.hide = function () {
                    $vm.isshow = false
                    $("body").unbind("mousedown", hide);
                }
                vm.showAfter = function (e) {
                    avalon.log("vm：e.$vmodel，$el：e.$el。")
                }
                vm.showBefore = function (e) {
                    avalon.log("vm：e.$vmodel，$el：e.$el。")
                }
                vm.toggle = function (isshow) {
                    var e = $.Event(isshow ? "show" : "hide", {
                        $target: $($vm.target),
                        $el: $(el),
                        $vmodel: vm
                    })
                    $node.trigger(e)
                    if (!isshow) $vm.hide();
                }
                vm.panel = $node[0]
            })
            avalon.scan($node[0], $vm)
            return $vm
        }

        avalon.ui.dropDownPanel.defaults = {
            $skipArray: ['container', 'panel'],
            width: '',
            height: '',
            left: 0,
            top: 0,
            container: document.body,
            isshow: false,
            droppanelclass: "dropdownPanel",
            content: "",
            panel: '',
            target: '',
            tmpl: '',
            tmplsrc: '',
            initevent: true, //是否初始化元素点击事件
            template: '<div ms-attr-class="droppanelclass" ms-visible="isshow" ms-mousedown="mousedown" ms-attr-id="dropDownPanelId" '
        + 'ms-css-width="width" ms-css-height="height" ms-css-left="left" ms-css-top="top" ms-html="content" ms-include="tmpl" ms-include-src="tmplsrc"></div>'
        }
    }

    /// <summary>
    /// 日期选择
    /// </summary>
    new function () {
        var date = avalon.ui.date = function (el, data, vmodels) {
            var elDataOps = avalon(el).data() || {};
            var ops = $.extend({}, data.dateOptions, elDataOps);
            if (typeof (ops.onSelect) == "string") {
                var sfn = ops.onSelect,pvm;
                for (var i = 0, l = vmodels.length; i < l; i++) {
                    if (typeof (vmodels[i][sfn]) == "function") {
                        pvm = vmodels[i];
                        break;
                    }
                }
                ops.onSelect = function (date, formatDate, format) {
                    if (pvm) pvm.apply(this, arguments);
                }
            }
            var model = avalon.define(data.dateId, function (scope) {
                avalon.mix(scope, ops);
            })
            , $el = $(el)
            , showtime = /%H:%M/.test(ops.format)
            , val = $el.val()
            , format = []
            , reg = /(\d{4})([-|/]+)(\d{1,2})[-|/]+(\d{1,2})(?:\s+(\d{1,2})(:{1})(\d{1,2}):{1}(\d{1,2}))?/
            , matchs
            , duplex = $el.attr('ms-duplex')
            , props = duplex ? duplex.split('.') : ''
            , prop = null
            , nearVM = null
            , VM = null
            , VMIndex = 0
            , VMLen = vmodels.length
            , i = 0
            , propLen = 0
            , end = false
            if (val) {
                matchs = reg.exec(val)
                matchs.forEach(function (item, i) {
                    if (item) {
                        switch (i) {
                            case 1:
                                format.push('%Y')
                                break
                            case 2:
                                format.push(item)
                                break
                            case 3:
                                format.push('%m')
                                format.push(matchs[2])
                                break
                            case 4:
                                format.push('%d')
                                break
                            case 5:
                                format.push(' ')
                                format.push('%H')
                                break
                            case 6:
                                format.push(item)
                                break
                            case 7:
                                format.push('%M')
                                format.push(matchs[6])
                                break
                            case 8:
                                format.push('%S')
                                break
                        }
                    }
                })
            }
            if (format.length) {
                model.format = format.join('')
            }

            if (duplex) {
                propLen = props.length
                do {
                    nearVM = vmodels[VMIndex]
                    for (i = 0; prop = props[i++];) {
                        if (i === propLen) {
                            duplex = prop
                            end = true
                            break
                        }
                        if (nearVM.hasOwnProperty(prop)) {
                            nearVM = nearVM[prop]
                        }
                    }
                    if (end)
                        break
                    VMIndex++
                } while (VMIndex < VMLen)
            }
            $el.after(ops.icon)
            Calendar.setup({
                inputField: el,
                trigger: $el.next('img')[0],
                onSelect: function () {
                    var formatDate = this.selection.print(model.format)[0]
                    if (duplex && nearVM && nearVM.hasOwnProperty(duplex)) {
                        nearVM[duplex] = formatDate
                    }
                    model.onSelect.call(this, this.date, formatDate, model.format)
                    this.hide()
                },
                showTime: showtime ? 24 : showtime,
                dateFormat: ops.format
            })
            return model
        }

        date.defaults = {
            $skipArray: ['icon', 'format'],
            onSelect: function (date, formatDate, format) {
                avalon.log('this : Calendar instance\r\ndate : ' + date + '\r\nformat : '
                 + format + '\r\nformatDate : ' + formatDate)
            },
            format: '%Y-%m-%d %H:%M',
            icon: '<img src="/Content/Themes/Base/Images/ico/day.gif" alt="点击选择日期" title="点击选择日期" style="cursor:pointer;position: relative;left: -18px;top: 6px; vertical-align:top;" />'
        }
    }

    new function () {
        var gridui = avalon.ui.grid = function (el, data, vmodels) {
            var elDataOps = avalon(el).data() || {};
            var ops = $.extend({}, data.gridOptions, elDataOps);
            var pvm = $vmodels[0];
            var gvm = pvm[options.gridid];
            var mvvm = avalon.define("", function (vm) {

            });
            return mvvm;
        }
        gridui.defaults = {
            bgel:"<div></div>"
        }
    }
    return avalon
})