博客链接
余泓:https://www.cnblogs.com/fishred/
杨文燕:https://www.cnblogs.com/address2019/
作业博客:https://edu.cnblogs.com/campus/fzu/2019FZUSEZ/homework/8736
GitHub项目地址
https://github.com/fishred2941214/031702409-031702411
具体分工
余泓:代码编写、ui设计
杨文燕:jstee使用、测试
PSP表格
PSP2.1 | Personal Software Process Stages | 预计耗时(分钟) | 实际耗时(分钟) |
Planning | 计划(估计这个任务需要多少时间) | 60 | 60 |
Development | 开发 | 1505 | 1295 |
Analysis | 需求分析(包括学习新技术) | 240 | 360 |
Design Spec | 生成设计文档 | 60 | 30 |
Design Review | 设计复审 | 30 | 10 |
Coding Standard | 代码规范(为目前的开发制定合适的规范) | 5 | 5 |
Designt | 具体设计 | 60 | 40 |
Coding | 具体编码 | 1080 | 960 |
Code Review | 代码复审 | 30 | 10 |
Test | 测试(自我测试、修改代码,提交修改) | 200 | 260 |
Reporting | 报告 | 100 | 130 |
Test Repor | 测试报告 | 30 | 30 |
Size Measurement | 计算工作量 | 10 | 10 |
Postmortem&Process Improvement Plan | 事后总结并提出过程改进计划 | 60 | 90 |
合计 | 1765 | 1735 |
解题思路与设计实现
解题思路
- 在文本框中输入数据
- 在analysis函数中对输入的文本进行分解,找出相关节点,建立对应的div、ul、li标签
- 使用jstree插件生成树
- 进行界面的美化
设计实现
JsTree插件
$(function(){$("#tree_"+k+num+"").jstree({ plugins : ["types","contextmenu"], 'core' : { //允许callback,为了后面进行创建、重命名、删除、移动或复制等操作 "check_callback" : true,}, "types": { "default" : { "icon" :false, // 关闭默认图标 }, }, 'contextmenu':{ 'items' : { 'add':{ 'label':'新增分类', 'action':function(obj){ //reference获取当前选中节点的引用 var inst = jQuery.jstree.reference(obj.reference); //通过get_node方法获取节点的信息,类似于实例对象 var clickedNode = inst.get_node(obj.reference); /* inst.create_node 参数1:父节点 参数2:新节点的数据 参数3: 1)first:当前节点下的头部新增节点 2)last:当前节点下的尾部新增节点 3)before:当前节点同级的上部新增节点 4)after:当前节点同级的下部新增节点 参数4:回调函数 参数5:Boolean类型,内部参数,指示父节点是否成功加载 */ var newNode = inst.create_node(clickedNode, { //'id': 'ajson20', //'parent' : 'ajson2', 'icon' : 'jstree-file', 'text':'新节点'},'last',function(node){ //回调返回创建后点节点,给新节点改名 inst.edit(node,node.val); },''); } }, 'rename':{ 'label':'修改分类', 'action':function(obj){ var inst = jQuery.jstree.reference(obj.reference); var clickedNode = inst.get_node(obj.reference); inst.edit(obj.reference,clickedNode.val); } }, 'delete':{ "label": "删除分类", 'action':function(obj){ var inst = jQuery.jstree.reference(obj.reference); var clickedNode = inst.get_node(obj.reference); inst.delete_node(obj.reference); } } } } });});
JsTree是一个jquery的插件,使用首先需要引用jquery
<script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"> </script>//通过 CDN引用jquery <script src="./vakata-jstree-c9d7c14/dist/jstree.min.js"></script> // 引入jstress定义的样式 <link rel="stylesheet" href="./vakata-jstree-c9d7c14/dist/themes/default/style.min.css"/>
更多详细的使用,可以查看官网或是搜索教程。官网地址:https://www.jstree.com
关键代码——对文本的分解以及对应标签的创建
//用正则表达式提取输入内容中的导师和不同届学生的信息 var patt1 = /导师\:[\u4e00-\u9fa5]{2,5}/g; var patt2 = /\d{4}级博士生\:.*/g; var patt3 = /\d{4}级硕士生\:.*/g; var patt4 = /\d{4}级本科生\:.*/g; var patt5 = /\d{4}/; var k=0;//k值用来记录一共进行了几次输入 function empty(){ document.getElementById("original_tree").value = "";//清空输入框 } function analysis(content,num){ var teacher = content.match(patt1);//提取出导师信息 if(teacher == null) { alert("您输入的格式不正确!");//输入为空或输入无关信息或没有导师信息时,提示输入不正确 return; } var t_div = document.createElement('div'); t_div.setAttribute("id","tree_"+k+num); document.getElementById("tree").appendChild(t_div); var r_tree = document.createElement('ul');//创建根节点 r_tree.setAttribute("id","root"+k+num); document.getElementById("tree_"+k+num).appendChild(r_tree); teacher = teacher.join("").split(":");//所有的join和split操作均为了去除输入中的多余符号,提取所需信息,此处为获取导师名 var ele = document.createElement('li'); ele.setAttribute("id","teacher"+k+num);//添加一个名为导师的节点 ele.innerHTML = teacher[1];//内容为导师姓名 document.getElementById("root"+k+num).appendChild(ele); var doctor = content.match(patt2); var master = content.match(patt3); var undergraduate = content.match(patt4); //若该导师名下有至少一名学生,则创建代表学位的节点 if(doctor!=null||master!=null||undergraduate!=null) { var degree = document.createElement("ul"); degree.setAttribute("id","degree"+k+num); document.getElementById("teacher"+k+num).appendChild(degree); } //该导师有博士学生,则为该导师添加博士类节点,并按照入学年份对学生进行分类,以下的硕士类和本科生类相同 if(doctor!=null) { var doctor_degree = document.createElement("li"); doctor_degree.setAttribute("id","doctor_degree"+k+num); doctor_degree.innerHTML = "博士生"; document.getElementById("degree"+k+num).appendChild(doctor_degree); var doctor_grade = document.createElement("ul"); doctor_grade.setAttribute("id","doctor_grade"+k+num); document.getElementById("doctor_degree"+k+num).appendChild(doctor_grade); for(var i = 0;i < doctor.length;i++) { var str = doctor[i]; str = str.split(":");//将入学年份和学位和所有博士学生的姓名分离 var ele1 = document.createElement('li'); ele1.innerHTML = str[0].match(patt5);//得到入学年份 ele1.setAttribute("id","grade"+k+num+i); document.getElementById("doctor_grade"+k+num).appendChild(ele1); var doctor_name = document.createElement("ul"); doctor_name.setAttribute("id","doctor_name"+k+num+i); document.getElementById("grade"+k+num+i).appendChild(doctor_name); var name = str[1].split("、");//得到所有学生姓名 for(var j = 0;j < name.length;j++) { var ele11 = document.createElement('li'); ele11.innerHTML = name[j]; ele11.setAttribute("id","name"+k+num+i+j); document.getElementById("doctor_name"+k+num+i).appendChild(ele11); } } } if(master!=null) { var master_degree = document.createElement("li"); master_degree.setAttribute("id","master_degree"+k+num); master_degree.innerHTML = "硕士生"; document.getElementById("degree"+k+num).appendChild(master_degree); var master_grade = document.createElement("ul"); master_grade.setAttribute("id","master_grade"+k+num); document.getElementById("master_degree"+k+num).appendChild(master_grade); for(var i = 0;i < master.length;i++) { var str1 = master[i]; str1 = str1.split(":"); var ele2 = document.createElement('li'); ele2.innerHTML = str1[0].match(patt5); ele2.setAttribute("id","grade1"+k+num+i); document.getElementById("master_grade"+k+num).appendChild(ele2); var master_name = document.createElement("ul"); master_name.setAttribute("id","master_name"+k+num+i); document.getElementById("grade1"+k+num+i).appendChild(master_name); var name = str1[1].split("、"); for(var j = 0;j < name.length;j++) { var ele22 = document.createElement('li'); ele22.innerHTML = name[j]; ele22.setAttribute("id","name1"+k+num+i+j); document.getElementById("master_name"+k+num+i).appendChild(ele22); } } } if(undergraduate!=null) { var undergraduate_degree = document.createElement("li"); undergraduate_degree.setAttribute("id","undergraduate_degree"+k+num); undergraduate_degree.innerHTML = "本科生"; document.getElementById("degree"+k+num).appendChild(undergraduate_degree); var undergraduate_grade = document.createElement("ul"); undergraduate_grade.setAttribute("id","undergraduate_grade"+k+num); document.getElementById("undergraduate_degree"+k+num).appendChild(undergraduate_grade); for(var i = 0;i < undergraduate.length;i++) { var str2 = undergraduate[i]; str2 = str2.split(":"); var ele3 = document.createElement('li'); ele3.innerHTML = str2[0].match(patt5); ele3.setAttribute("id","grade2"+k+num+i); document.getElementById("undergraduate_grade"+k+num).appendChild(ele3); var undergraduate_name = document.createElement("ul"); undergraduate_name.setAttribute("id","undergraduate_name"+k+num+i); document.getElementById("grade2"+k+num+i).appendChild(undergraduate_name); var name2 = str2[1].split("、"); for(var j = 0;j < name2.length;j++) { var ele33 = document.createElement('li'); ele33.innerHTML = name2[j]; ele33.setAttribute("id","name2"+k+num+i+j); document.getElementById("undergraduate_name"+k+num+i).appendChild(ele33); } } } k++; }
创建的标签实例
<div id = "tree"> <!--- 产生的数据格式如下: <ul> <li>张三 <ul> <li>博士生 <ul> <li>2016 <ul> <li> 王五 </li> <li> 李四 </li> </ul> </li> </ul> </li> </ul> </li> </ul> --> </div>
特点设计与展示
网页支持多组输入、多棵树并存,并且提供在节点处进行修改、删除和增加节点的操作。
界面展示
初始界面
支持多组输入、多棵树并存
在节点处进行修改、删除和增加节点
目录说明与使用说明
目录说明
- 家族树
- vakata-jstree-c9d7c14:Jstree插件文件
- TREE.png:插入的图片
- tree.css:网页的css文件
- tree.html:网页的html文件
- 森林.png:插入的图片
- REAMDE:目录说明与使用说明
使用说明
- 请将家族树文件夹下载或是将上述的文件统一下载并放入同一文件夹中,以防无法完整显示。
- 使用浏览器打开tree.html文件,即可在浏览器中看到页面。
- 在左侧的文本框输入数据,点击确定按钮,将会在右侧生成一棵以导师为根节点的树。
- 点击小三角或是双击节点内容如“张三”可展开或收起节点。
- 在节点处单击右键,可进行修改、删除、添加节点的操作。
- 修改节点:对节点进行重命名。
- 删除节点:删除该节点及其下级节点。
- 添加节点:在该节点处新增一个下级节点。
单元测试
选用工具:Mocha
学习方式:通过学习测试框架Mocha实例教程,自己上手跟着教程操作一次就能大概了解框架的使用
对输入文本进行数据处理函数的测试:
// analysis.test.js var analysis = require('./analysis.js'); var expect = require('chai').expect;//引入断言库“chai”的 expect 断言风格 var message1="李二"; var message2="琪七"; var message3="司四"; var message4="王五"; var message5="刘六"; var message6="许六"; var message7="张三"; var message8="刘一"; var message9="天一"; var message10="吴五"; describe('文本分割测试', function() { it('学生节点测试', function() {//测试实例 expect(analysis()).to.include(message1);//expect断言:analysis函数返回的数组中包含学生姓名“李二” }); it('学生节点测试', function() { expect(analysis()).to.include(message2); }); it('学生节点测试', function() { expect(analysis()).to.include(message3); }); it('学生节点测试', function() { expect(analysis()).to.include(message4); }); it('学生节点测试', function() { expect(analysis()).to.include(message5); }); it('学生节点测试', function() { expect(analysis()).to.include(message6); }); it('导师节点测试', function() {//expect断言:analysis函数返回的数组中包含导师姓名“张三” expect(analysis()).to.include(message7); }); it('学生节点测试', function() {//expect断言:analysis函数返回的数组中包含时间信息“201” expect(analysis()).to.include(message8); }); it('学生节点测试', function() { expect(analysis()).to.include(message9); }); it('学生节点测试', function() { expect(analysis()).to.include(message10); }); });
界面测试
生成的树默认为收起状态
无输入(显示提示语)
单组输入(显示一棵树)
多组输入(多棵树并存)
2组输入
4组输入
无导师节点(显示提示语)
一组有导师节点,一组无导师节点的输入(显示一棵树及提示语)
多次输入,一次一组输入(每一次多显示一棵树)
多次输入,一次多组输入(每一次多显示二棵树)
签入记录
代码模块异常
问题描述:如何使用动态的id号生成jstree
尝试:搜索、浏览有关jstree使用的相关内容
是否解决:已解决
评价
我的搭档是一个行动力很强的人