文档章节

Node.js 切近实战(七) 之Excel在线(文件&文件组)

乐搏学院
 乐搏学院
发布于 2016/10/18 14:30
字数 1942
阅读 10
收藏 0

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

wKioL1d6hXWx-U3mAADpvT66v2g395.png

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

先看一下页面整体代码。

wKiom1d6hn7TeaCTAAEYoILJIqw841.png

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

wKiom1d6h7bT1hhFAABuLvwydac892.png

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,两个下面都有文件。

wKiom1d6lw2D21nAAABTK7Q12dg097.png

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

wKioL1d6lrDyyoUNAAB3v_zHWTc241.png

此时这个结果的话,我们还得找到我们页面传递的_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页。

wKioL1d6k1_zdULEAAC8Y3_OHmw826.png

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

wKioL1d6k6WjdMwrAACmHiR005A529.png

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创建,文件删除,共享设置等功能,敬请期待。

结束语

免费学习更多精品课程,登录乐搏学院官网http://h.learnbo.cn/

本文出自 “技术创造价值” 博客,请务必保留此出处http://leelei.blog.51cto.com/856755/1795764

本文转载自:

乐搏学院
粉丝 9
博文 526
码字总数 707467
作品 0
丰台
程序员
私信 提问
Node.js 切近实战(九) 之Excel在线(在线编辑)

之前有一节我给大家讲过文件列表,如下,今天我们要讲的就是Excel在线编辑。 当我们双击文件图标的时候会跳转到一个Excel修改界面,如下。 ok,这里我们使用的依然是Telerik Kendo UI中的Spr...

乐搏学院
2016/10/27
14
0
Node.js 切近实战(六) 之Excel在线(文件列表)

看到了吧,这就是主界面,首先我们来看一下My Document的View部分。在看View之前,我们先看一下Mode的设计。 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...

乐搏学院
2016/10/27
0
0
SpreadJS使用进阶指南 - 使用 NPM 管理你的项目

前言 SpreadJS作为一款性能出众的纯前端电子表格控件,自2015年发布以来,已经被广泛应用于各领域“在线Excel”数据管理项目中。NPM,作为管理Node.js库最有力的手段,解决了很多NodeJS代码部...

葡萄城控件技术团队
2018/06/21
0
0
SpreadJS 在线Excel使用进阶指南 - 利用 NPM 管理你的项目

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/powertoolsteam/article/details/80813491 前言 SpreadJS作为一款性能出众的纯前端电子表格控件,自2015年发布...

powertoolsteam
2018/06/26
0
0
Node.js 切近实战(十) 之Excel在线(共享文件)

本篇文章我就不罗嗦了,主要讲的是共享文件列表,主要功能就是查看别人共享的文件。 打开该界面,用户可以在左侧看到共享文件的人员的信息,点击该人可以查看该人共享了哪些文件。在Grid里面...

乐搏学院
2016/10/27
9
0

没有更多内容

加载失败,请刷新页面

加载更多

Node.js 多进程处理CPU密集任务

Node.js 单线程与多进程 大家都知道 Node.js 性能很高,是以异步事件驱动、非阻塞 I/O 而被广泛使用。但缺点也很明显,由于 Node.js 是单线程程序,如果长时间运算,会导致 CPU 不能及时释放...

Svend
48分钟前
5
0
Django笔记-3-模型-20190526

简介 django为各种数据库提供了很好的支持,django对这些数据库提供了统一的调用API;可以根据不同的也无需求选择不同的数据库; 配置数据库 在setting.py文件中配置数据库 DATABASES = { ...

Frank1126lin
今天
3
0
OSChina 周日乱弹 —— 程序员做噩梦

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @-冰冰棒- :#今日歌曲推荐# 手嶌葵《Kiss The Girl》 《Kiss The Girl》- 手嶌葵 手机党少年们想听歌,请使劲儿戳(这里) @Sharon啊 :今天...

小小编辑
今天
217
11
Another app is currently holding the yum lock; waiting for it to exit...

Another app is currently holding the yum lock; waiting for it to exit... The other application is: PackageKit Memory : 153 M RSS (266 MB VSZ) Started: Thu Jul 12 00:03......

圣洁之子
今天
2
0
FastDateFormat 研究

FastDateFormat 对缓存的利用,其实就是用ConcurrentHashMap 做了一个map类型的缓存 public F getInstance(final String pattern, TimeZone timeZone, Locale locale) { Validate......

暗中观察
今天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部