博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Node.js 切近实战(七) 之Excel在线(文件&文件组)
阅读量:5789 次
发布时间:2019-06-18

本文共 8222 字,大约阅读时间需要 27 分钟。

hot3.png

今天我们来看一下Excel在线部分的文件和文件组。首先我们来看一下页面,调一下胃口。俗话说无图无真相,先看图。

没错,还是Telerik Kendo UI,其实我面试的时候当听到别人说自己用的是EasyUI和ExtJs的时候,我就不那么上心,但是如果有人用的是Kendo UI for&JS的话,我就会多关注一点。

先看一下页面整体代码。

很简单,还是BootStrap布局,jade模板。注意下最底下的css样式,在jade模板中,如果想要在页面定义css,就要像上面这样写。注意这里我们引用了一个部分页,popup.jade,里面其实就是第一幅图里面New,Rename等按钮弹出的modal页。

OK,首先我们看到的是左边的树,这个树叫kendoTreeView,我们来看一下这个树是怎么生成的。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

var url = "/filegroup/list/" + userObj.UserID;

var dataSource = new kendo.data.HierarchicalDataSource({

        transport: {

            read: {

                url: url,

                dataType: "json"

            }

        },

        schema: {

            model: {

                id: "_id",

                children: "subgroup",

                expanded: true,

                hasChildren: function (node) {

                    return (node.subgroup && node.subgroup.length > 0);

                },

                spriteCssClass: "folder"

            }

        }

});

     

$("#treeview-filegroup").kendoTreeView({

        dataSource: dataSource,

        dataTextField: ["filecount"],

        dataValueField: ["_id"],

        change: function (e) {

            var tree = e.sender;

            selNode = tree.select();

            var data = tree.dataItem(selNode);

             

            if (data._id) {

                selGroupId = data._id;

                $("#chk_all").prop('checked'false);

                getFilelist(data._id);

            }

        }

    });

OK,这段代码就是生成树的代码,注意这里的dataSource,当页面加载以后,会请求url,filegroup/list/{0},我们来看一下后台这个api。

1

router.get('/filegroup/list/:userId', fileRoutes.fileGroupList);

再看一下fileGroupList方法。

1

2

3

4

5

exports.fileGroupList = function (req, res) {

    fileGroupModel.find({ 'userid': req.params.userId }, null, { sort: { name: 1 } } , function (error, fileGroup) {

        res.json(fileGroup);

    });

}

其实就是根据传入的userid查询了一下fileGroup Collection,查出来后,注意这里的schema,它的model定义树节点id是我们mongodb的主键,children是subgroup(上节讲过group和subgroup的model定义,不明白的去上节看),hasChildrenC返回是否有子节点。spriteCssClass设置父节点样式,注意我们第一幅图定义的页面样式就用在这里。OK,接下里我们看树的change事件,当有选中的节点时,将右边列表表头的全选复选框uncheck,并根据选中的_id去mongodb查询group下面的数据,我们来看一下getFilelist方法。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

function getFilelist(groupId) {

    if (!groupId) return;

     

    $.get("/filegroup/" + groupId, function (result) {

        var grid = $("#file_list").data("kendoGrid");

        if (result) {

            var dataSource = new kendo.data.DataSource({

                pageSize: 10,

                data: result,

                schema: {

                    parse: function (response) {

                        $.each(response, function (idx, elem) {

                            if (elem.createdate && typeof elem.createdate === "string") {

                                elem.createdate = kendo.parseDate(elem.createdate, "yyyy-MM-ddTHH:mm:ss.fffZ");

                            }

                             

                            if (elem.lasteditdate && typeof elem.lasteditdate === "string") {

                                elem.lasteditdate = kendo.parseDate(elem.lasteditdate, "yyyy-MM-ddTHH:mm:ss.fffZ");

                            }

                        });

                        return response;

                    }

                }

            });

             

            grid.setDataSource(dataSource);

        }

        else {

            grid.dataSource.data([]);

        }

    });

}

直接调用rest api filegroup/{0}查询数据,得到结果以后,构造kendo Grid的dataSource,对日期进行格式化。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

router.get('/filegroup/:id', fileRoutes.fileGroup);

exports.fileGroup = function (req, res) {

    var groupId = req.params.id;

    fileGroupModel.findById(groupId).populate('file').exec(function (error, doc) {

        if (!doc || doc.length == 0) {

            fileGroupModel.findOne({ 'subgroup._id': groupId })

            .populate('subgroup')

            .populate('subgroup.file')

            .exec(function (error, docs) {

                if (docs) {

                    var subGroupIndex = -1;

                    docs.subgroup.forEach(function (element, index, arra) {

                        if (subGroupIndex > -1) return;

                         

                        if (element._id == groupId) {

                            subGroupIndex = index;

                        }

                    });

                     

                    if (subGroupIndex > -1) {

                        res.json(docs.subgroup[subGroupIndex].file);

                    }

                }

            });

        }

        else {

            res.json(doc.file);

        }

    });

}

这里要注意,首先我们也不知道这里传入的是groupId还是subgroupId,所以我们先拿groupId查询,如果查到了,就返回数据,如果没查到,就拿_id去查subgroup,查询subgroup,注意这里要使用subgroup._id作为查询条件,因为subgroup是嵌入在group中的,是一个整体。查完之后注意这里的两个populate,如果没有populate的话,意味着这些嵌入的subgroup以及引用的file都不会被包含在查询结果中,我们来看一下查询的结果,在后台加一句console.log(docs)即可。有两个subgroup,两个下面都有文件。

我们用robomongo也许看的更清晰一些,两个group,一个下面有7个文件,一个有2个文件。

此时这个结果的话,我们还得找到我们页面传递的_id对应的subgroup下面的file。所以在代码中又有了循环匹配id确定subgroup索引下标的过程,找到后,直接根据索引拿出file。是不是很麻烦,如果你有什么好的办法,可以给我留言。

接下来我们来看一下kendo grid,首先看一下这个全选。

1

2

3

4

5

6

$("#chk_all").click(function () {

    var isChecked = $(this).prop("checked");

    $("#file_list table:eq(1)").find("tr").each(function () {

        $(this).children("td:first").find("input[type='checkbox']").first().prop('checked', isChecked);

    });

});

看起来很简单,找到第一个table找到所有tr,再找到第一个td,锁定checkbox让它选中或者不选中。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

$("#file_list").kendoGrid({

        scrollable: true,

        selectable: true,

        allowCopy: true,

        resizable: false,

        sortable: true,

        pageable: {

            refresh: true,

            pageSizes: [10, 20, 50, 100],

            buttonCount: 5

        },

        toolbar: [

            { name: 'share', imageClass: 'glyphicon glyphicon-share-alt' },

            { name: 'unshare', imageClass: 'glyphicon glyphicon-lock' },

            { name: 'batch_delete', text: "Delete" , imageClass: 'glyphicon glyphicon-trash' }, 

            { name: 'export', imageClass: 'k-icon k-i-excel' }],

        columns: [{

                template: "<div class='center-align-text'>" +

                    "<input id='chkId_#=_id#' type='checkbox' class='k-checkbox' value='#=_id#' onclick='chkHeader_click'/>" 

                    "<label class='k-checkbox-label' for='chkId_#=_id#'></label></div>",

                field: "",

                title: "<div class='center-align-text'>" +

                    "<input type='checkbox' class='k-checkbox' id='chk_all'/>" 

                    "<label class='k-checkbox-label' for='chk_all'></label></div>",

                width: 40

            },

            {

                field: "fullname"

                title: "File Name"

            }, {

                field: "isshared"

                title: "Shared" ,

                width: 85, 

                template: "<div><input type='checkbox' class='k-checkbox' value='#=isshared#' #=isshared ? \"checked='checked'\":\"\" # />" 

                "<label class='k-checkbox-label'></label></div>",

                sortable: false

            },

            {

                command: [

                    {

                        name: "preview",

                        text: ""

                        imageClass: 'glyphicon glyphicon-search',

                        click: showDetails

                    }, {

                        name: "delete",

                        text: ""

                        imageClass: 'glyphicon glyphicon-trash',

                        click: confirmFileDelete

                    }, {

                        name: "rename",

                        text: "",

                        imageClass: 'glyphicon glyphicon-list-alt',

                        click: fileRename

                    }, {

                        name: "edits"

                        text: ""

                        imageClass: 'glyphicon glyphicon-pencil',

                        click: viewfile

                    }

                ], 

                width: 310,

                title: "Operation"

            }]

    });

注意grid中的Shared列,使用的是kendo的模板#=#这种写法。最后我们再看一下command列,这个列的话其实就是定义一些按钮,每个按钮都定义好了click事件。就看第一个showDetails,看看js代码

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

function showDetails(e) {

    var wnd = $("#wd_details").kendoWindow({

        title: "File Detail Info",

        modal: true,

        visible: false,

        resizable: false,

        minWidth: 300

    }).data("kendoWindow");

     

    var detailsTemplate = kendo.template($("#popup_detail").html());

    e.preventDefault();

     

    var dataItem = this.dataItem($(e.currentTarget).closest("tr"));

    wnd.content(detailsTemplate(dataItem));

    wnd.center().open();

}

在这里其实就是弹出一个kendo window,这个弹出页中又加载了kendo 模板popup_detail,我们来看一下这个template。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

script#popup_detail(type="text/x-kendo-template")

 dl

  dt

   label File Name:

  dd #=fullname#

  dt

   label Shared:

  dd #=isshared#

  dt

   label CreateDate:

  dd #=kendo.toString(createdate,'MM/dd/yyyy HH:mm tt')#

  dt

   label LastEditUser:

  dd #=lastedituser#

  dt

   label LastEditDate:

  dd #=kendo.toString(lasteditdate,'MM/dd/yyyy HH:mm tt')#

只要我们将一个对象给模板,模板就会自己替换对应的内容。在这里我们会先拿到点击行的对象,然后通过.content赋给模板,最后弹出modal页。

就是这么简单,点击重命名按钮,就会弹出重命名页面。

rename功能其实很简单,看看前台和后台。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

$("#btn_fileRename").click(function () {

    var fileName = $.trim($("#new_fileName").val());

    if (!fileName) {

        showMsg("info""Please input new file name!");

        return;

    }

     

    var postData = {

        id: $("#hfd_fileId").val(),

        filename: fileName

    };

     

    $.ajax({

        url: '/file/rename'

        type: 'PUT'

        dataType: 'json',

        data: { postData: JSON.stringify(postData) },

        success: function (res) {

            if (!res.isSuc) {

                showMsg('error', res.msg);

                return;

            }

             

            $("#wd_fileRename").data("kendoWindow").close();

            getFilelist(selGroupId);

        }

    });

});

1

2

3

4

5

6

7

8

9

10

11

12

13

router.put('/file/rename', fileRoutes.fileRename);

exports.fileRename = function (req, res) {

    var data = JSON.parse(req.body.postData);

    fileModel.findByIdAndUpdate(data.id, { $set: { name: data.filename, lasteditdate: Date.now() } }

        function (error, result) {

        if (error) {

            res.json({ isSuc: false, msg: error.message });

        }

        else {

            res.json({ isSuc: true });

        }

    });

}

nodejs,用起来就是这么爽,好了今天就到这里,明天我们继续会讲剩下的group&subgroup创建,文件删除,共享设置等功能,敬请期待。

结束语

免费学习更多精品课程,登录乐搏学院官网

,请务必保留此出处

转载于:https://my.oschina.net/learnbo/blog/760054

你可能感兴趣的文章
基础,基础,还是基础之JAVA基础
查看>>
JS prototype 属性
查看>>
HTTP库Axios
查看>>
gen already exists but is not a source folder. Convert to a source folder or rename it 的解决办法...
查看>>
20个Linux服务器性能调优技巧
查看>>
填坑记:Uncaught RangeError: Maximum call stack size exceeded
查看>>
SpringCloud之消息总线(Spring Cloud Bus)(八)
查看>>
KVO原理分析及使用进阶
查看>>
【348天】每日项目总结系列086(2018.01.19)
查看>>
【294天】我爱刷题系列053(2017.11.26)
查看>>
可替换元素和非可替换元素
查看>>
2016/08/25 The Secret Assumption of Agile
查看>>
(Portal 开发读书笔记)Portlet间交互-PortletSession
查看>>
搭建vsftpd服务器,使用匿名账户登入
查看>>
JAVA中循环删除list中元素的方法总结
查看>>
Java虚拟机管理的内存运行时数据区域解释
查看>>
人人都会深度学习之Tensorflow基础快速入门
查看>>
ChPlayer播放器的使用
查看>>
js 经过修改改良的全浏览器支持的软键盘,随机排列
查看>>
Mysql读写分离
查看>>