前言
我们小组抽到的题目是计划管理模块,这个模块分为两大部分,分别是计划管理模块和计划新增模块,我负责其中计划管理模块的后台搭建以及相关数据库的建立。这个项目中我使用的语言是Java,相关的技术栈有spring boot,mybatis-plus,mysql等,编辑器为idea。
题目
计划管理模块
项目在开始前一般都会制定相应计划,计划管理模块包含计划模板管理、计划制定等功能。同时允许项目经理每个月更新计划的状态。
计划模板:
- 计划模板支持动态的管理维护
- 每个模板支持多个版本,但是一个模板最多只允许一个在用的版本(历史项目使用老版本,不受版本变更的影响)。
- 每个版本对应一个计划数据,如上图所示。
- 计划分为里程碑和关键活动两类。
- 计划的进度会汇总到里程碑节点;所有的进度不能超过100%。
- 计划可以调整顺序,可以设置每个活动的负责人等信息。
需求分析及数据库设计
通过题目可以看出,我们主页面中显示的内容是由里程碑和活动所组成的,并且给了我们新增里程碑和新增活动的相关弹窗,那么我们很自然的想到建立两个对象,一个是里程碑stone,一个是活动activity,由这两个组成一个视图,就是我们最终的展示界面。这样的设计方法也是符合我们最终的项目需求的。同时我们应该注意到里程碑和活动之间存在1对n的关系,即一个里程碑对应多个活动。
之后我们注意到了左边的模型和版本,并且这两者之间还存在依赖关系,一个模型对应多个版本,而且一个模型下的一个版本对应只属于这个版本的里程碑和活动。至此我们得到了这四者之间的依赖关系:
至此,我们大致知道我们需要为他们设置除了他们自带的属性之外的属性了。
对于模型来说,他不依赖任何对象,所以有本身的name属性以及id属性即可。
对于版本来说,他依赖于模型,所以除了本身的id和name属性之外还要添加tid,标识他所属的模型号。
对于里程碑而言,他依赖于模型,版本,所以除了本身的属性之外,还要有mid,tid,指定他所对应版本和模型。
对于活动而言,上述的三个他都有依赖,所以要加入sid(里程碑号),mid,tid这三个属性。
同时我们要从下到上建立外键连接,防止出现类似只存在模型号为1的模型,却出现一个模型号为2的活动的问题。
主要功能实现
里程碑活动展示
我们通过上面的分析可知,每一个展示界面所展示的内容其实是由模型号和版本号控制的,即给我们后端一个模型号和版本号,我们需要返回相应的里程碑以及活动。我们在上面已经建立好了视图,所以现在只需要将相应的数据从数据库取出来返回到controller层即可。
具体dao层代码:
1. @Select("SELECT * FROM t_show WHERE asid=sid && smid=#{mid} && stid=#{tid}") 2. List<show> getAllById1( int mid,int tid);
在返回数据的过程中我们还需要注意一个问题,就是我们的视图是一整行一整行的,我们用select取数返回的数据也都是一行一行的,即里程碑的名字和相关活动在同一行,而观察我们的显示界面,我们发现这二者明显要分行。
为了解决这个问题,我在service层写了一个相关算法,通过嵌套循环将数据转化为我们想要的格式。
代码:
1. public List<show> getALLbyID1(int mid,int tid){ 2. //得到show展示视图的所有数据 3. List<com.zood.domain.show> users = show.getAllById1(mid,tid); 4. //得到所有里程碑的数据 5. List<com.zood.domain.stone> stones= stone.getAll1(); 6. //我们要返回的数组 7. List<show> users1 = new ArrayList<>(); 8. 9. for(int i=0;i<stones.size();i++){ 10. show myshow=new show(); 11. String stoneName2=stones.get(i).getSname(); 12. myshow.setSname(stoneName2); 13. myshow.setSid(stones.get(i).getId()); 14. users1.add(myshow); 15. for (int j=0;j<users.size();j++){ 16. if(users.get(j).getSname().equals(stones.get(i).getSname())){ 17. show myshow1=new show(); 18. myshow1.setAchievement(users.get(j).getAchievement()); 19. myshow1.setAname(users.get(j).getAname()); 20. myshow1.setBonus(users.get(j).getBonus()); 21. myshow1.setFront(users.get(j).getBonus()); 22. myshow1.setIscrop(users.get(j).isIscrop()); 23. myshow1.setQuota(users.get(j).getQuota()); 24. myshow1.setProcess(users.get(j).getProcess()); 25. myshow1.setType(users.get(j).getType()); 26. 27. myshow1.setAid(users.get(j).getAid()); 28. myshow1.setMid(users.get(j).getMid()); 29. myshow1.setSid(users.get(j).getSid()); 30. myshow1.setTid(users.get(j).getTid()); 31. myshow1.setSmid(users.get(j).getSmid()); 32. myshow1.setMtid(users.get(j).getMtid()); 33. myshow1.setAsid(users.get(j).getAsid()); 34. 35. users1.add(myshow1); 36. } 37. } 38. } 39. 40. return users1; 41. }
这样,我们就得到了期望的数据格式:
版本模型展示
我们再来看页面左边的版本以及模型的模块。由于我们前端使用了一个树形结构的组件,导致对后端传来的数据有了如下的特殊形式:
1. "data": [ 2. { 3. "id": 1, 4. "label": "云网项目管理模型", 5. "url": "/RealHome", 6. "children": [ 7. { 8. "id": 1, 9. "parentID": 1, 10. "label": "合同升级项目(迭代型)", 11. "url": "/HomeView" 12. }, 13. { 14. "id": 2, 15. "parentID": 1, 16. "label": "合同项目", 17. "url": "/HomeView" 18. }, 19. { 20. "id": 3, 21. "parentID": 1, 22. "label": "合同新项目", 23. "url": "/HomeView" 24. } 25. ] 26. }, 27. { 28. "id": 2, 29. "label": "测试数据233", 30. "url": "/RealHome", 31. "children": [ 32. { 33. "id": 4, 34. "parentID": 2, 35. "label": "最新项目", 36. "url": "/HomeView" 37. } 38. ] 39. }, 40. { 41. "id": 3, 42. "label": "尚艺", 43. "url": "/RealHome", 44. "children": [] 45. }, 46. { 47. "id": 46, 48. "label": "合同新项目阿松大", 49. "url": "/RealHome", 50. "children": [] 51. } 52. ],
观察这些数据,我们发现是一个父类包含了除了自身属性之外其他小类,小类只有自己的属性,于是我创建了两个类,一个父类以及一个子类,将他们组合在一起,返回给前端,这样就得到了我们需要的数据格式。
父类:
1. @Data 2. public class mtshow { 3. private Integer id; 4. private String label; 5. private String url; 6. private List<mtshow1> children; 7. }
子类:
1. @Data 2. public class mtshow1 { 3. private Integer id; 4. private Integer parentID; 5. private String label; 6. private String url; 7. }
相关算法:
1. @Override 2. public List<mtshow> mtshow() { 3. List<mtshow> params= new ArrayList<>(); 4. List<template> template = templates.getAllById(); 5. List<model> models1 = models.selectList(); 6. 7. for(int i=0;i<template.size();i++){ 8. mtshow s= new mtshow(); 9. s.setLabel(template.get(i).getName()); 10. s.setId(template.get(i).getId()); 11. String url="/RealHome"; 12. String url1="/HomeView"; 13. s.setUrl(url); 14. 15. List<mtshow1> s2=new ArrayList<>(); 16. for(int j=0;j<models1.size();j++){ 17. mtshow1 s1=new mtshow1(); 18. if(template.get(i).getId().equals(models1.get(j).getTid())){ 19. s1.setId(models1.get(j).getMid()); 20. s1.setParentID(models1.get(j).getTid()); 21. s1.setLabel(models1.get(j).getName()); 22. s1.setUrl(url1); 23. s2.add(s1); 24. } 25. } 26. s.setChildren(s2); 27. params.add(s); 28. } 29. 30. return params; 31. }
新增功能
新增功能可以直接调用mybits-plus的内置函数,不需要自己写代码就可以轻松调用
示例代码
1. @Autowired 2. private StoneDao bookDao; 3. 4. @Override 5. public boolean saveBook(stone book) { 6. return bookDao.insert(book) > 0; 7. }
删除功能
在删除功能的实现过程中,我设置数据库中对象的id为自增,并在自己yml文件中配置了一下,保证了每一个对象的id属性不同。而这个属性又传给了前端,这样前端就可以通过id来删除数据了。dao层的实现我依旧是使用的mybits-plus自带的函数。
其实在删除功能中我最先设计的是接收一个类,再通过这个类中的属性与数据库对比进行删除,这个接口我在postman中测试成功了,但是因为前端穿不回来我需要的类,所以最终改为由id删除。
更新功能
更新对象的功能同增加一样,直接调用他内置的函数即可,也可以像我一样自己写一个dao层的更新函数。
1. @Update("UPDATE t_stone SET sname=#{sname},sort=#{sort},sdescription=#{sdescription}, WHERE mid=#{mid} && tid=#{tid} && id=#{id}") 2. boolean update(stone stones);
总结
通过这个实训作业,了解了springboot的许多特性,实在比原生的javaweb好用太多了,也了解了mybits-plus的具体使用方法。感觉收获蛮多的,希望以后可以在这条路上越走越远吧。
资源地址
百度网盘:
也可以支持一下博主