Node.js 切近实战(八) 之Excel在线(文件权限)

今天我们来看一下文件权限管理,这个其实是对共享出去的文件的一个简单的权限管理demo。在上节我写过的界面中,可以查询自己共享出去的文件。

wKiom1d_uvjwLs_IAABtoZkX9S0247.png

勾选Shared,我们查出自己共享出去的文件。或者我们可以通过点击ToolBar上面的SHARE按钮,实现共享文件。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

$(".k-grid-share""#file_list").bind("click"function (ev) {

    var selIds = [];

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

        var chkElement = $(this).children("td:first").find("input[type='checkbox']").first();

        if (chkElement.prop('checked')) {

            selIds.push(chkElement.val());

        }

    });

     

    if (selIds.length == 0) {

        showMsg('info''Please select at least one file to share!');

        return;

    }

     

    sharedUpdate(selIds, true);

});

首先是找到选中的文件的_id,然后调用shareUpdate方法去共享。

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

function sharedUpdate(selIds, shared) {

    msg = Messenger().post({

        message: "Do you want to " + (shared? 'share':'unshare') + " these file?",

        actions: {

            delete: {

                label: 'Yes',

                delay: 10,

                action: function () {

                    var postData = {

                        ids: selIds,

                        isShared: shared

                    };

                     

                    $.ajax({

                        url: '/file/share'

                        type: 'PUT'

                        dataType: 'json',

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

                        success: function (res) {

                            if (!res.isSuc) {

                                showMsg('error', res.msg);

                                return;

                            }

                             

                            getFilelist(selGroupId);

                        }

                    });

                    msg.hide();

                }

            },

            cancel: {

                label: "No",

                action: function () {

                    msg.hide();

                }

            }

        }

    });

}

发送一个ajax请求,去修改传入文件的共享属性,看一下效果

wKiom1d_vNvTamX7AAASDfy2Q4A040.png

先会弹出确认,点击Yes,调用api file/share去修改共享属性,看一下后台。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

router.put('/file/share', fileRoutes.fileShare);

exports.fileShare = function (req, res) {

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

    var idArray = data.ids;

     

    if (!idArray || idArray == 0) {

        res.status(403).json(commonMsgRes.buildJsonErrorRes('NoRecord'));

        return;

    }

     

    fileModel.update({ _id: { $in: idArray } }, { $set: { isshared: data.isShared } }, { multi: true }

function (error, result) {

        if (error) {

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

        }

        else {

            res.json({ isSuc: true });

        }

    });

}

在后台,先把json字符串转化成js对象,然后用mongoose提供的update方法去批量更新数据。注意这里的$in,其实是和sqlServer中的in一个意思,$set意思是需要修改的属性,你可以在这里写多个属性进行修改,并不一定只是一个isshared属性,然后最后的multi:true,意思是更新多个doc。所以整个修改的意思就是找到_id在idArray中的file docs,然后将其isshared属性全部修改为传入的值。当然在这里你也可以使用mongoose中的findAndUpdate方法去做批量更新。

 

文件share好之后,我们看一下共享文件权限设置界面。

wKioL1d_wjHQRRJAAACeCc0GwYw849.png

 

查询出数据后,每个文件都可以设置权限,这里很简单的三个,要真做权限,还是买吉日嘎啦的走火入魔权限管理系统好了,自己不要瞎折腾。OK,那么这三个权限使我们mongodb数据库中配置的。

wKiom1d_wtPiluekAABhd0NeFyQ395.png

 

我们在界面可以选择一个或者多个。

wKioL1d_wwayubJzAABALF21hNg124.png

选择完成后,点击Save,如果不想修改了,点击cancel,可以回到初始状态,我们来看一下js代码。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

$("#file_list").kendoGrid({

    scrollable: true,

    allowCopy: true,

    resizable: false,

    sortable: true,

    height: 800,

    pageable: {

        refresh: true,

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

        buttonCount: 5,

    }, 

    toolbar: [{ name: 'authSet', text: "Batch Setup" , imageClass: 'k-icon k-i-lock' }],

    columns: [{

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

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

                + "<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: 45,

            sortable: false

        },

        {

            field: "fullname", 

            title: "File Name"

        },

        {

            field: "isshared", 

            title: "Shared" ,

            template: '<select id="ddl_auth#=_id#" name="auth" multiple="multiple"></select>',

            sortable: false

        }, {

            command: [

                {

                    name: "authUpdate",

                    text: "Save",

                    imageClass: "k-icon k-i-tick",

                    click: updateFileAuth

                }, {

                    name: "authCancel",

                    text: "Cancel",

                    imageClass: "k-icon k-i-undo",

                    click: cancelUpdateFileAuth

                }

            ], 

            width: 230,

            title: "Operation"

        }], dataBound: function (rowBoundEvent) {

        $("#file_list select[name='auth']").each(function (index, element) {

            $(element).kendoMultiSelect({

                valuePrimitive: true,

                placeholder: "---Please Select---",

                ignoreCase: true,

                dataSource: authArray.length > 0? authArray:dataSource,

                dataTextField: "name",

                dataValueField: "_id",

                headerTemplate: '<div class="multi-select-header">' 

                            + 'Choose File Auth Below:</div>',

                dataBound: function (e) {

                    var dataItem = $("#file_list").data('kendoGrid').dataItem($(element).closest("tr"));

                    if (dataItem.auth && dataItem.auth.length > 0) {

                        var authArray = [];

                        dataItem.auth.forEach(function (v) {

                            authArray.push(v._id);

                        });

                         

                        this.value(authArray);

                    }

                     

                }

            });

        });

    }

});

大家注意isShared这一列,是个下拉列表,支持多选,然后在数据绑定完成以后,循环里面的下拉列表,将其渲染成kendoMultiSelect,注意这里的dataSource参数,如果authArray已经取到了,则使用,否则调用后台api获取。

1

2

3

4

5

6

7

8

var dataSource = new kendo.data.DataSource({

    transport: {

        read: {

            url: "/file/auth",

            dataType: "json"

        }

    }

});

如果在这里直接使用每次请求的话,会存在很多问题,性能问题,界面渲染也会出现一些重复渲染的问题。因为大家的auth都是一样的,所以我们先取到再说。

1

2

3

4

var authArray = [];

$.get('/file/auth'function (result) {

    authArray = result;

});

OK,接下来我们看一下Save功能,在grid的定义中,我们可以看到save调用的是updateFileAuth方法。

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

function updateFileAuth(e) {

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

    var fileId = dataItem._id;

    var authArray = $("#ddl_auth" + dataItem._id).data("kendoMultiSelect").value()

     

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

        showMsg('info''Please select at least one auth!');

        return;

    }

     

    var postData = {

        fileId: dataItem._id,

        fileAuth: authArray

    };

     

    $.post('/file/auth', postData, function (res) {

        if (!res.isSuc) {

            showMsg('error', res.msg);

            return;

        }

         

        showMsg('success''Saved successfully!');

        $("#btn_searchShared").click();

    });

}

根据当前行拿到id,再根据id拿到下拉选中的值,kendoMultiSelect的value方法返回的就是一个数组。

最后我们将得到的数组传递到api去修改权限,看一下后台。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

router.post('/file/auth', fileAuthRoutes.updateFileAuth);

exports.updateFileAuth = function (req, res) {

    var fileId = req.body.fileId;

    var fileAuth = req.body.fileAuth;

    var fileAuths = [];

     

    fileAuth.forEach(function (v) {

        fileAuths.push(mongoose.Types.ObjectId(v));

    });

     

    fileModel.findByIdAndUpdate(fileId, { '$set': { auth: fileAuths } }

        function (error, doc) {

        console.log(error);

        if (error) {

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

        }

        else {

            res.json({ isSuc: true });

        }

    });

}

在这里我们先将权限的id转化成ObjectId,再根据传入的文件id进行修改,ok,save就说完了。

再看一下cancel,其实就是将该行的权限id再赋给下拉列表。

1

2

3

4

5

6

7

8

9

10

11

function cancelUpdateFileAuth(e) {

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

    var fileId = dataItem._id;

    var authArray = [];

    if (dataItem != null && dataItem.auth.length > 0) {

        dataItem.auth.forEach(function (v) {

            authArray.push(v._id);

        });

    }

    $("#ddl_auth" + dataItem._id).data("kendoMultiSelect").value(authArray);

}

ok,最后就是batch批量设置,勾选数据,点击ToolBar上的BATCH SETUP,我们先看页面的代码。

wKiom1d_yLTx06NTAACSmsMSEe0041.png

这里的fileAuth_Window就是批量设置界面,在这里大家发现了一个循环的写法,不错,这就是jade模板中的语法,类似于razor视图引擎一样。看到这样的循环,我们在后台必须有代码要给页面这些值,类似于asp.NET mvc中页面绑定的Model。

1

2

3

fileAuthSchemas.authModel.find({}, function (error, doc) {

    res.render('authorization/docauth', { authArray: doc });

});

看到了吧,在向客户端输出页面时,同时传了一个对象,对象中的authArray的值为doc。这样的话,我们就可以在页面直接使用这个变量authArray。

wKioL1d_yk7SDrZWAAAZgiCtUAQ554.png

我们选择三个,点击SETUP,AJAX调用后台api批量设置。

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

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

    var selAuthIdArray = getSelAuthId();

    if (selAuthIdArray.length == 0) {

        showMsg('info''Please select at least one auth!');

        return;

    }

     

    var selIds = getSelFileId();

    if (selIds.length == 0) {

        showMsg('info''Please select at least one file to setup!');

        return;

    }

     

    showConfirm(updateFileAuthBatch);

});

 

function updateFileAuthBatch() {

    var selIds = getSelFileId();

    if (selIds.length == 0) {

        showMsg('info''Please select at least one file to setup!');

        return;

    }

     

    var postBody = {

        fileIdArray: selIds,

        fileAuth: getSelAuthId()

    };

     

    $.post('/file/auth/batch', postBody, function (result) {

        if (!result.isSuc) {

            showMsg('error', result.msg);

            return;

        }

 

        fileAuthWindow.data("kendoWindow").close();

        $("#btn_searchShared").click();

    });

}

 

function showConfirm(action) {

    msg = Messenger().post({

        message: "Do you want to setup?",

        actions: {

            save: {

                label: 'Yes',

                delay: 10,

                action: function () {

                    action();

                    msg.hide();

                }

            },

            cancel: {

                label: "No",

                action: function () {

                    msg.hide();

                }

            }

        }

    });

}

上面这段代码有没有很像C#中的委托呢?有点。最后我们看一下后台的批量设置api代码。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

exports.batchUpdateFileAuth = function (req, res) {

    var fileIdArray = req.body.fileIdArray;

    var fileAuth = req.body.fileAuth;

    var fileAuths = [];

     

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

        res.json(commonMsgRes.buildJsonErrorRes('NoRecord'));

        return;

    }

     

    fileAuth.forEach(function (v) {

        fileAuths.push(mongoose.Types.ObjectId(v));

    });

     

    fileModel.update({ _id: { $in: fileIdArray } }, { $set: { auth: fileAuths } }, { multi: true }

        function (error, doc) {

        if (error) {

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

        }

        else {

            res.json({ isSuc: true });

        }

    });

}

这样就设置成功了,我们来看一下效果。

wKioL1d_y36AsYJMAACdV_6SYNc024.png

 

好了,下节进入我们的关键点,Excel在线保存,编辑。

原文转自:乐搏学院http://www.learnbo.com/front/article/cmsIndex

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
数据库原理课程设计安排计划 课程设计的目的与意义 《数据库课程设计》是实践性教学环节之一,是《数据库原理及应用》课程的辅助教学课程。通过课程设计,培养学生严谨务实的工作态度,并在老师的精心指导下,提高分析问题和解决问题的能力,促进理论联系实际学风养成;巩固和加深对关系型数据库系统的基本概念、基本理论和实现技术的理解;掌握关系型数据库标准语言SQL的使用方法;弄清数据库设计的基本方法和步骤,并能针对实际问题灵活应用;熟练掌握某DBMS的使用方法;通过撰写课程设计论文,规范学生科技论文写作能力。 任务与要求: 课程设计题目以选用学生相对比较熟悉的业务模型为宜,要求通过本实践性教学环节,能较好地巩固数据库的基本概念、基本原理、关系数据库的设计理论、设计方法等主要相关知识点,针对实际问题设计概念模型,最终完成小型数据库的设计与实现。具体要求: (1)选题应切近生活,以便需求分析; (2)题目不应太大,事务处理过程简单; (3)以数据库设计为主,处理功能模块实现为辅; (4)系统设计过程应充分体现需求分析、概念设计、逻辑设计、物理设计等阶段。要求做到各阶段方法正确,目标明确,文档合理规范;前后阶段衔接紧密; (5)能正确使用开发工具连接和使用数据库,写出满足要求的SQL语句; (6)处理功能模块主要完成对数据库查询、数据更新和简单统计; 时间安排 本次课程设计为一周,计划在第16周,16课时。具体时间见实验安排。 1. 16周以前必须完成完成选题、审题。 2. 第一天完成需求分析;概念设计、逻辑设计、物理设计阶段,各阶段大致时间为一天;第五天数据库实施,检查任务完成情况。 3. 检查完成后,及时提交设计报告。 考核方式 1、同学平时表现占总成绩20%,若迟到扣5分,无故旷课每次扣10 分,二次不到者总成绩以0分计。 2、检查情况占总成绩40%,按各同学完成情况、讲解给分,如果发现有抄袭程序者,其总成绩以0分计。 数据库原理课程设计计划全文共5页,当前为第1页。3、课程设计报告占总成绩40%,用A4纸打印并在规定时间内上交,不得抄袭,否则总成绩按0分计。 数据库原理课程设计计划全文共5页,当前为第1页。 设计内容 可自选题目,但须经过指导教师审查。 题目一:人事管理系统 1、系统功能的基本要求: 员工各种信息的输入,包括员工的基本信息、学历信息、婚姻状况信息、职称等。 员工各种信息的修改; 对于转出、辞职、辞退、退休员工信息的删除; 按照一定的条件,查询、统计符合条件的员工信息;至少应该包括每个员工详细信息的查询、按婚姻状况查询、按学历查询、按工作岗位查询等,至少应该包括按学历、婚姻状况、岗位、参加工作时间等统计各自的员工信息; 对查询、统计的结果打印输出。 2、数据库要求:在数据库中至少应该包含下列数据表: 员工基本信息表; 员工婚姻情况表,反映员工的配偶信息; 员工学历信息表,反映员工的学历、专业、毕业时间、学校、外语情况等; 企业工作岗位表; 企业部门信息表。 题目二:工资管理系统 1、系统功能的基本要求: 员工每个工种基本工资的设定 加班津贴管理,根据加班时间和类型给予不同的加班津贴; 按照不同工种的基本工资情况、员工的考勤情况产生员工的每月的月工资; 员工年终奖金的生成,员工的年终奖金计算公式=(员工本年度的工资总和+津贴的总和)/12; 企业工资报表。能够查询单个员工的工资情况、每个部门的工资情况、按月的工资统计,并能够打印; 2、数据库要求:在数据库中至少应该包含下列数据表: 员工考勤情况表; 员工工种情况表,反映员工的工种、等级,基本工资等信息; 员工津贴信息表,反映员工的加班时间,加班类别、加班天数、津贴情况等; 员工基本信息表 员工月工资表。 题目三:能源管理收费系统 1、系统功能的基本要求: 用户基本信息的录入:包括用户的单位、部门、姓名、联系电话、住址 用户水、电、气数据的录入(每个月的数据的录入); 水、电、气价格的管理 工号的管理 查询、统计的结果打印输出。 2、数据库要求:在数据库中至少应该包含下列数据表: 用户基本信息表; 水、电、气单价表及历史记录表等 工号及权限表 数据库原理课程设计计划全文共5页,当前为第2页。题目四:实验选课系统 数据库原理课程设计计划全文共5页,当前为第2页。 1、系统功能的基本要求: 实验选课系统分为教师,学生及系统管理员三类用户,学生的功能包括选课,查寻实验信息等,教师的功能包括考勤,学生实验成绩录入,查寻实验信息等。管理员的功能包括新建教师,学生账户,设定实验课程信息(设定实验时间,地点,任课教师)。 管理员可对教师,学生及实验课程信息进行修改;教师可对任课的考勤,成绩进行修改;学生可以对自己选修的课程重选,退选。 管理员可删除教师,学生及实验课程信息。 教师可查询所任课程
### 回答1: Verilogatan是一个基于Verilog硬件描述语言实现的反正切函数。Verilogatan用于计算反正切函数的值,其输入为一对正弦和余弦值,输出为对应的反正切值。 Verilogatan的实现过程包括以下几个步骤: 1. 输入信号:Verilogatan接受来自正弦和余弦功能模块的输入信号。这些信号代表输入的正弦和余弦值。 2. 查找表:Verilogatan使用查找表的方式来实现反正切函数。查找表中存储了一些预计算的反正切值,根据输入信号的值查找对应的反正切值。 3. 插值:由于查找表中存储的反正切值有限,因此Verilogatan使用插值技术,根据输入信号的值与查找表中的最近两个值进行线性插值,来计算出精确的反正切值。 4. 输出信号:Verilogatan将计算得到的反正切值输出给其他功能模块进行进一步的处理和使用。 Verilogatan的实现可以根据具体的需求进行优化和改进。例如,可以增加更多的预计算值来提高查找表的精度,或者使用更高级的插值算法来提高计算的准确性和效率。 总的来说,Verilogatan是通过基于Verilog的硬件描述语言实现的反正切函数,它能够根据输入的正弦和余弦值计算出相应的反正切值。这个函数在数字信号处理和其他需要浮点数运算的硬件设计中起到了重要的作用。 ### 回答2: verilog atan是一种用于计算反正切函数的Verilog语言的函数或模块。 反正切函数(atan)是一个数学函数,返回给定参数的反正切值,在某些计算机语言和硬件描述语言中,可以使用该函数来进行角度和弧度之间的转换以及旋转计算等。 在Verilog中,实现atan函数可以通过使用级数展开法或者使用查找表的方法来实现。通过级数展开法,我们可以使用泰勒级数或Maclaurin级数对反正切函数进行逼近。而另一种更为高效的方法则是使用查找表来实现。 大致的实现步骤如下: 1. 确定输入和输出的数据位宽,以及所需的精度。 2. 根据所选的实现方法,编写相应的Verilog代码。 3. (泰勒级数法)使用循环结构,在每一次迭代中,计算当前项的系数并将其累加到结果中,并更新迭代次数。 (Maclaurin级数法)类似于泰勒级数法,差异在于,这里是从较低次数开始累加。 (查找表法)根据输入的角度或弧度,通过查找具有预定义值的表格来返回相应的反正切值。 4. 在Verilog模块中实例化该函数,并根据需求连接输入和输出端口。 5. 运行模拟仿真或进行硬件逻辑综合,以验证和优化Verilog atan函数的性能和功能。 需要注意的是,使用Verilog实现atan函数可能需要更复杂的数学运算和编程技巧。因此,对于初学者来说,可能需要参考更多的资料和示例代码,理解高级数学和Verilog编程的知识以及相关的数据结构和算法。 ### 回答3: Verilog是硬件描述语言(HDL),主要应用于数字电路的设计。atan(反正切)是一种数学函数,用于计算给定比值的角度。我们可以使用Verilog来实现反正切函数。 实现atan函数的一种常见方法是使用泰勒级数展开。泰勒级数能够近似表示一个函数,并且可以根据所需的精度进行展开。我们可以使用Taylor展开来实现atan函数。 在Verilog中,我们可以使用循环和条件语句来实现Taylor展开。首先,我们需要将输入比值缩小到特定的范围内,通常选择[-1, 1]之间。然后,使用Taylor展开计算反正切的近似值,并对每一项进行求和。最后,根据需要的精度返回计算结果。 以下是一个简化的Verilog代码示例,用于实现反正切函数的近似计算: ```verilog module atan_approximation( input [7:0] ratio, output [7:0] atan_value ); reg [7:0] sum; reg [7:0] term; reg [7:0] ratio_squared; reg [7:0] x; always @ (ratio) begin ratio_squared = ratio * ratio; x = ratio / (1 + sqrt(1 + ratio_squared)); sum = 0; term = x; for (int i = 1; i <= 5; i = i + 1) begin term = term * (-1) * ratio_squared; term = term / ((2 * i + 1) * (2 * i + 1)); sum = sum + term; end atan_value = sum; end endmodule ``` 这个简化的Verilog代码示例将给定的比值作为输入,并使用Taylor展开来计算它的反正切近似值。代码使用循环变量i来控制展开的项数,并通过乘法和除法运算来计算每一项的值。最终结果以8位宽度的数表示输出。 需要注意的是,这只是一个简单的近似计算,并不是标准的反正切功能。在实际应用中,如果需要更高精度的结果,可能需要调整计算的范围和Taylor展开的项数。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值