基于React和Express的接待工作管理系统的设计与实现

    柳海燕 郑健

    

    

    

    摘要:每年来学校参观交流的院校、企业等单位众多,接待工作涉及接待方案确定、领导审批等多个环节。目前该类应用开发成本高,且功能不能完全满足学校个性化需求。针对这些问题,自主采用React和Express技术,设计并实现了IVT接待工作管理系统。前端页面基于React用Material-UI和Recharts构建,有效解决了客户端多端访问问题和刷新页面带来的性能问题。后端采用轻量框架Express进行开发,极大地提高了开发效率。项目同时对接了CAS服务、企业微信和阿里云短信服务,在方便用户登录的同时,也有效避免了信息孤岛问题。

    关键词:React;Recharts;Express;企业微信

    中图分类号:TP311.5? ? ? 文献标识码:A

    文章编号:1009-3044(2021)17-0010-04

    开放科学(资源服务)标识码(OSID):

    1 背景

    React是Facebook于2013年开源的Web框架, React将DOM抽象为虚拟DOM的特性,使我们在开发接待工作管理系统时,无须担心性能问题可以根据需要随时刷新整个页面。张根[1]、秦子实[2]等用React构建网站前端开发,郝骏[3]、沈超[4]等用React Native 开发原生移动应用,SUBRAMANIAN V[5]为使用React构建现代应用提供了完整技术栈解决方案,从而形成对React技术的完美补充。本文使用Material-UI和Recharts框架完成系统UI显示和统计图表显示,不仅系统风格统一,也极大地提高了开发效率。后端我们采用基于Node.js的轻量框架Express进行开发,可以快速创建健壮、友好的API,由于全栈使用React解决方案,在提高开发效率的同时也降低运维成本。

    企业微信是腾讯公司推出的一款与微信有一致沟通体验的企业通讯与办公工具。张蓓蕾[6]、高月宏[7]、解攀科[8]等都基于企业微信进行了管理平台的设计与开发。由于目前企业微信是我校常用办公工具之一,所以我们将基于React框架开发的接待工作管理系统接入企业微信,使得内部员工可以通过企业微信授权登录,无须输入用户名、密码,进而简化用户操作。为打通与原有系统数据的连接,我们还将本系统对接CAS单点登录系统,有效避免了信息孤岛问题。对于外部申请访问人员,我们通过接入阿里云短信业务,使用户通过手机号、验证码进行登录,免去了用户记忆账号、 密码的麻烦。

    2 需求分析

    2.1 功能性需求分析

    我们经过分析整理,将系统角色划分为访问申请人员、培训申请人员、审核人员、审批人员和管理员五种,所有角色人员能够看到学校开设的培训课程。

    访问申请人员的功能需求包括:访问申请的提交、修改、删除、查询操作。访问申请人员还能够查看已提交申请的审核进度,当审批结束后能够下载接待方案,访问结束后能够填写满意度问卷对本次接待进行评价。

    培训申请人员的功能需求包括:培训申请的提交、修改、删除、查询操作。培训申请人员还能查看审核结果。

    审核人员负责访问申请的审核、培训申请的审核、培训课程的增加、删除、修改、查询。当拒绝申请时,需选择拒绝理由;当同意访问申请时,应制作并上传接待方案,供上级领导审批;当同意培训申请时,应及时与申请人员取得联系商讨培训计划。

    审批人员负责接待方案审批。当审批人员不满意接待方案时,可退回给审核人员进行修改。当审批人员同意接待方案时,系统会自动发送短信到申请人手机,申请人可登录系统下载接待方案,按照接待方案来访。审批人员还可以用图形化方式查看不同进度的访问申请、培训申请,查看完成访问人员的满意度分布情况。

    系统管理员拥有系统最高权限,能够完成系统用户、培训课程、访问申请和培训申请的增加、删除修改、查找等维护操作。

    2.2 非功能性需求分析

    1)易用性。在考虑用户使用习惯的基础上,我们要进一步简化用户操作。通过手机号、验证码登录,可以免去用户记忆密码的烦恼。对于内部员工通过企业微信授權登录,既不用单独记忆网址,也无须输入用户名、密码。在线审批的各个环节通过短信提醒到申请人,可以方便用户及时知道下一步该如何操作。

    2)可靠性。充分考虑到应用运行的数据异常等情况,进行异常处理。

    3 系统设计

    我们从系统架构、系统模块、系统数据库几个方面,对系统进行了全方位的设计,方便后期实施和维护。

    3.1 系统架构设计

    为免去外部用户记忆账号、密码的不便,我们设计使其通过阿里云短信登录应用服务器。为避免信息孤岛的出现,我们设计内部员工通过阿里云短信、企业微信授权登录或CAS服务器登录三种方式之一登录应用进行数据访问。

    考虑到接待工作管理系统涉及的CAS对接、企业微信对接、阿里云短信登录等模块,我们根据本校实际,设计了接待工作管理系统应用服务器与数据库服务器。系统相关的整体架构示意图如图1所示。

    用户通过PC、笔记本、手机、Pad等终端设备访问应用系统。系统页面采用HTML5响应式设计,用户在多种设备上有一致的使用体验。

    3.2 系统模块设计

    根据之前确认的用户需求,我们进一步分角色绘制了系统模块图,如图2所示。

    对于整个接待工作管理系统而言,参观访问的接待工作是重中之重。我们对参观访问模块绘制的数据流程图如下图3所示。对于用户上传的访问申请,先由审核人员根据学校实际情况做出初步筛查,如果双方条件无法匹配以致不能接待,由审核人员给出拒绝理由并拒绝申请,申请人员除可在系统查看通知外,也会收到相应的短信提醒。对于可以接待的访问申请,审核人员需撰写接待方案,提交审批领导进行方案审批。待领导审批同意后,访问申请人员可收到短信提醒,到系统下载接待方案后,即可按照接待方案来校访问。访问结束后,访问申请者需到系统完成接待满意度调查问卷,方可结束本次访问。审批人员和管理员,可在系统中查看访问申请、用户满意度的图形化统计显示结果,以便对工作更好的管理和部署。

    3.3 数据库设计

    根据图2所示的系统模块,我们先画出该接待工作管理系统的E-R图,根据ER模型转换为关系数据库的一般原则,我们设计了7张表用于存储接待工作管理系统的数据。其中user表用来存储所有用户的信息,包括企业微信ID、手机号、验证码等相关属性,我们用字段power区分用户的级别,并用这张表和其他六张表建立联系。visit_apply为访问申请表,记录了用户填写的各项访问申请记录,包括单位名称、来访人数、到达时间、离开时间、是否需要安排住宿、交流目的等内容。visit_verify为访问审核表,记录了用户访问申请的审核情况,包括申请表ID、审核人、审核时间、审核意见、审批人、审批人意见、接待方案等字段。visit_satisfy为访问满意度记录表,记录了已经完成参观访问人员对我校接待情况的满意度评价,包括申请表ID、满意度评分、意见建议等字段。course为培训课程记录表,用于展示学校已经开设的培训课程的信息,主要包括课程名称、课程学时、任课教师、教师简介、课程简介等信息。train_apply为培训申请表,记录了用户填写的各项培训需求记录,包括申请单位、需培训人数、培训地点、培训方向等内容。train_verify为培训审核表,记录了对用户培训申请的审核情况,包括申请表ID、审核人、审核时间、审核意见等字段。

    4 系统实现

    4.1 前端实现与关键技术

    本文前端采用React+Redux+Material-UI+Recharts进行搭建。Material-UI是基于React的界面框架,还支持Node.js V6以上的服务端渲染。本系统前端开发实现需要的关键技术主要有如下几点。

    1)中间件Redux-thunk

    单纯的Redux工作流如图4所示,用户在View中通过store.dispatch()發出Action,当然它可以接受一个由Action Creator函数生成的Action作为参数。对于每一个Action对象,用type属性来表示其名称。Store通过纯函数Reducer返回一个全新的对象State。由于View对应的State是一个不变的对象,所以一旦State发生变化,Store允许设置监听函数,实现View的重新渲染。

    然而问题是,Action发出后,Reducer如何在异步操作结束后自动执行计算出新的State。为了解决这一难题,我们采用了中间件技术redux-thunk。这样我们只需首先编写返回函数而不仅仅是对象的action creator。然后用redux-thunk改造store.dispatch,使其可接受函数作为参数即可。

    对于本项目而言,

    const store = createStore(

    rootReducer,

    applyMiddleware(thunk, async),

    );

    我们在index.js中引入两个中间件来完成所需操作。

    2)React-Redux

    本项目涉及页面、模块较多,在本文中我们采用了Redux专门封装的React-Redux库。这样每一个功能页面我们都可以拆分成UI组件与容器组件两大类。UI组件依靠Material-UI实现,容器组件使用Redux的API管理数据和业务逻辑。

    首先我们将store作为参数放入Provider组件,这样顶层组件被包裹在Provider组件中,使得所有组件能够访问到Redux的数据。其代码为:

    render(

    

    

    ,

    document.getElementById('app'),

    );

    接下来,我们通过React-Redux提供的connect方法,从UI组件生成容器组件。connect方法接受两个参数:mapStateToProps、mapDispatchToProps。mapStateToProps负责将state映射到UI组件的参数,mapDispatchToProps负责将用户对UI组件的操作映射成Action。由于本项目模块众多,仅以Visit为例,其绑定的核心代码为:

    const mapStateToProps = state => ({

    visit: state.visit,

    user: state.user,

    });

    const mapDispatchToProps = dispatch => ({

    visitAction: bindActionCreators(VisitAction, dispatch),

    });

    @connect(mapStateToProps, mapDispatchToProps)。

    3)Recharts

    Recharts是阿里巴巴前端团队开发的一款可视化组件库,它用React进行设计。当前Recharts提供的图表有PieChart、RadarChart、SankeyChart等多种类型。

    我们通过npm或yarn安装后,可以通过import添加所需要的组件。比如,我们想用PieChart组件来展示数据,就可以通过语句import { PieChart, Pie, } from 'recharts'; 来引入。这里Pie是PieChart的子组件。

    在用PieChart进行数据显示时,我们根据应用需要,设计并实现了自定义标签进行数据显示,以达到个性化显示的目的。

    我们通过Pie组件的label属性来展示图形上的文本标签,只不过这个label的值我们写成一个函数,具体代码为:

    renderLabel = ({

    cx, cy, midAngle, innerRadius, outerRadius, percent, payload,

    }) => {

    const radius = innerRadius + (outerRadius - innerRadius) * 0.5;

    const x = cx + radius * Math.cos(-midAngle * RADIAN);

    const y = cy + radius * Math.sin(-midAngle * RADIAN);

    return (

     cx ? 'start' : 'end'} dominantBaseline="central">

    {`${payload.label}:${(percent * 100).toFixed(0)}%`}

    

    );

    };

    我们用这个函数来渲染自定义的文本标签,并将其作为Pie的label属性,从而达到个性化图形显示的目的。

    4.2 后端实现与关键技术

    本项目后端采用Node+Express+MariaDB实现。由于Node.js不需要额外的HTTP服务器,因此减少了一层抽象,可以很好地提升系统性能。Express作为目前最稳定最流行的开发框架之一,除了其极简的内核,还因其可提供缓存、路由控制、错误控制器、CSRF保护等功能而备受开发者青睐。 MariaDB是由Mysql之父Widenius开发的Mysql分支产品,但它不仅仅是Mysql的替代品,它更好地提高了Mysql技术,MariaDB社区发布的MariaDB Connector是非阻塞客户端,可提供对插入流、管道传输和批处理的支持,还通过多节点配置支持故障转移和负载平衡,不仅减少了网络流量还有效避免网络延迟。

    在本项目中,除了应用express内置中间件express.static进行应用中静态资源托管外,根据系统需要,我们重点进行了路由级中间件、应用级中间件的设计与实现。

    1)工具库utils设计

    我们在utils中设计并实现了阿里云短信的发送、Cookies的读写、企业微信注册、CAS注册等独立模块内容,以供后面路由调用。以发送阿里云短信为例,在utils中核心代码为:

    function sendSms(phone, template, code) {

    const params = {

    PhoneNumbers: phone,

    SignName: '苏州工业园区职业技术学院',

    TemplateCode: template,

    TemplateParam: JSON.stringify({code}),

    };

    return client.request('SendSms', params, {method: 'POST'});

    }

    其中phone参数,用于接收要发送到的手机号码,template用于接收要發送的短信内容模板,code用于接收程序根据应用需要生成的参数。这样,在后面的中间件中就可以作为工具进行调用,从而更好地实现代码复用,提升开发效率。

    2)路由级中间件设计

    我们将系统用到的增、删、改、查相关函数,挂载到指定路径句柄,这不仅可以用来处理用户发起的GET、POST请求,还可以为路径定义多个路由。

    根据应用需要,我们只需对不同的表进行类似的操作即可。所以这里仅以访问课程列表为例,其路由句柄的核心代码为:

    router.post('/api/courseList', (req, res) => {

    const {limit} = req.body;

    const sql = `select * from course ${limit ? 'limit ?' : ''}`;

    db.query(sql, [limit], (error, list) => {

    if (error) {

    …

    } else {

    …

    }

    });

    });

    5 系统测试

    为发现系统潜在问题,我们设计了120多个测试用例,包含了正常数据和异常数据。我们分别采用笔记本、台式机、Android手机、iOS手机,对系统进行了功能测试和可靠性测试。我们通过模拟在内存使用率、CPU使用率达到80%情况下,进行压力测试,系统能够稳定运行并未出现错误。因为由于施工或某些特殊原因,机房偶有停电发生,我们进行了基于错误的策略对系统进行健壮性测试,系统适应性良好。

    6 系统测试

    本接待工作管理系统在实际使用中节约了工作人员的沟通成本,提升了沟通效率,也为每年接待工作的统计提供方便。本文重点从需求分析、系统架构设计、数据库设计、系统设计与实现等多个方面,讨论了其设计与实现。React、Express框架不仅在多端访问、页面渲染、开发效率等方面具有优势,还可以为我们节约开发的时间成本和经济成本,本文涉及的基于React和Express框架的搭建工具和使用方法,对于同类需求系统的开发具有一定的借鉴意义。

    参考文献:

    [1] 张根,蔡永香,高静文.基于React组件快速构建网站前端[J].电脑知识与技术,2019,15(15):119-121.

    [2] 秦子实.基于Redux数据状态管理的前端应用实践[J].电脑知识与技术,2020,16(8):254-255,258.

    [3] 郝骏,郑紫微,段欢.基于React20Native图像隐写的研究和实现[J].无线通信技术,2019,28(1):36-41.

    [4] 沈超,曹婷婷,王一萌,等.基于React20Native的农业气象自动化观测系统国家级平台移动应用APP设计[J].农业与技术,2019,39(18):132-135,138.

    [5] Subramanian V. Pro MERN Stack:Full Stack Web App Development with Mongo, Express,React,and Node[M].Berkeley:Apress,2017.

    [6] 张蓓蕾,彭骁,董君磊,等.基于企业微信的宁波市地震应急工作助手的设计与实现[J].地震地磁观测与研究,2020,41(4):251-263.

    [7] 高月宏,顾敏,夏丹丹,等.基于企业微信的掌上医护管系统的设计与实现[J].中国数字医学,2020,15(10):53-55.

    [8] 解攀科,郭伟秀,许婷,等.基于企业微信的信息化需求采集管理平台[J].计算机系统应用,2020,29(11):92-96.

    【通联编辑:谢媛媛】