1 Star 0 Fork 1

HelenYang/HealthSystem

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README

高校健康上报系统设计与实现

学号 :20184131031 姓名 :李飞龙 班级 :18机器人4班

学号 :201841302153 姓名 :杨海林 班级 :18智能制造4班

指导老师:黎志雄

分工:杨海林:后端代码编写,前后端数据交互

​ 李飞龙:前端,docker部署 ,实验报告编写

一、项目简介

在全国人民共同抗击新型冠状病毒疫情的严峻形势下,为了让高校师生健康信息上报,方便地了解高校师生身体健康情况,做好高校内部的疫情防控工作与管理,很多高校都自建了健康上报系统

本实验项目作为课程的期末大作业,要求学生组队自主设计与实现一个健康上报系统,并可以Saas(软件即服务)架构实现云原生系统。

二、需求分析

本实验项目要求学生团队设计实现的高校健康上报系统可以解决如下需求:

1、前端界面功能模块

a) 要求界面美观、简约,主题统一;

b) 调研国内相关系统界面的输入信息,设计前端各信息录入项目;

c) 有防止用户重复提交的功能;

d) 有加速渲染前端界面的设计。

2、后台管理端功能模块

a) 可以使用vue或其他前端框架构建,实现管理后台各个功能界面;

b) 要求界面简洁精美,主题统一;

c) 后台登陆逻辑需要接入腾讯防水墙,https://007.qq.com/

d) 管理员账号管理模块;

e) 账号管理模块;

f) 有解决系统高并发问题的设计;

g) 提供大数据报表并导出Excel表格,相关管理人员通过报表可一目了然地查看相关信息;

h) 所有列表可以进行综合查询;

i) 所有列表可以导出excel文件或pdf文件。

三、具体设计

1、项目架构

输入图片说明

输入图片说明

2、普通用户登录、注册

@RequestMapping("/login")
    public String login(@ModelAttribute person per, Model model){
        person person2 = perService.selectPerson(per.getPersonId());
        String personId = per.getPersonId();
        String password = per.getPassword();
        if(person2 != null){
            if(per.getPassword().equals(person2.getPassword())){
                return "redirect:"+ personId + "/inputInfo";
            }
            else {
                String str= "密码错误,请重新输入!";
                model.addAttribute("personId", personId);
                model.addAttribute("password", password);
                model.addAttribute("passwordError", str);
                return "index";
            }
        }
        else {
            String str= "该账号尚未注册,请先注册";
            model.addAttribute("personId", personId);
            model.addAttribute("password", password);
            model.addAttribute("passwordError", str);
            model.addAttribute("userError", str);
            return "index";
        }
    }

    @RequestMapping("/register")
    public String register(){
        return "register";
    }

    @RequestMapping("/insertPerson")
    public String insertPerson(@ModelAttribute person per, Model model){
        int flag = perService.insertPerson(per);
        if (flag == 1){
            String name = per.getName();
            model.addAttribute("name", name);
            return "registerSuccess";
        }
        else {
            String name = per.getName();
            String personId = per.getPersonId();
            String password = per.getPassword();
            model.addAttribute("name", name);
            model.addAttribute("personId", personId);
            model.addAttribute("password", password);
            model.addAttribute("userExists","该用户已存在");
            return "register";
        }
    }

前端显示效果:

输入图片说明 输入图片说明

3、管理员登录模块

    @RequestMapping("/login")
    public String login(@ModelAttribute person per, Model model){
        person person2 = perService.selectPerson(per.getPersonId());
        String personId = per.getPersonId();
        String password = per.getPassword();
        if(person2 != null){
            if(per.getPassword().equals(person2.getPassword())){
                if(person2.getFlag()==1)
                    return "redirect:/admin/personList";
                else {
                    model.addAttribute("NotAdmin", "您不是管理员");
                    return "AdminLogin";
                }
            }
            else {
                String str= "密码错误,请重新输入!";
                model.addAttribute("personId", personId);
                model.addAttribute("password", password);
                model.addAttribute("passwordError", str);
                return "AdminLogin";
            }
        }
        else {
            String str= "该账号尚未注册,请先注册";
            model.addAttribute("personId", personId);
            model.addAttribute("password", password);
            model.addAttribute("passwordError", str);
            model.addAttribute("userError", str);
            return "AdminLogin";
        }
    }

前端显示:

输入图片说明

4、防止用户重复提交

private boolean isRepeatSubmit(HttpServletRequest request) {
        String client_token = request.getParameter("token");
        //1、如果用户提交的表单数据中没有token,则用户是重复提交了表单
        if(client_token==null){
            return true;
        }
        //取出存储在Session中的token
        String server_token = (String) request.getSession().getAttribute("token");
        //2、如果当前用户的Session中不存在Token(令牌),则用户是重复提交了表单
        if(server_token==null){
            return true;
        }
        //3、存储在Session中的Token(令牌)与表单提交的Token(令牌)不同,则用户是重复提交了表单
        if(!client_token.equals(server_token)){
            return true;
        }
        return false;
    }
@RequestMapping("/insertInformation/{personId}")
    public String insertInformation(@ModelAttribute information info,
                                    @PathVariable String personId,
                                    HttpServletRequest request,
                                    Model model){

        boolean b = isRepeatSubmit(request);//判断用户是否是重复提交
        if(b==true){
            System.out.println("请不要重复提交");
        }else {
            request.getSession().removeAttribute("token");//移除session中的token
            System.out.println("处理用户提交请求!!");
            perService.InsertInfo(info, personId);
        }
        model.addAttribute("information", info);
        person person = perService.selectPerson(personId);
        model.addAttribute("name", person.getName());
        model.addAttribute("personId", person.getPersonId());
        model.addAttribute("message", "您今天已打卡成功!");
        model.addAttribute("flag", 1);
        return "inputInformation";
    }

5、接入腾讯防水墙

<form id="form1" modelattribute="person" action="/userPage/login" method="post">
                    <div class="line"><span>账号:</span>
                        <input class="bt_input" type="text" name="personId" th:value="${personId}" required="">
                    </div>
                    <div class="line"><span>密码:</span>
                        <input class="bt_input" type="password" name="password" th:value="${password}" required="">
                    </div>
                    <!--点击此元素会自动激活验证码-->
                    <!--id : 元素的id(必须)-->
                    <!--data-appid : AppID(必须)-->
                    <!--data-cbfn : 回调函数名(必须)-->
                    <!--data-biz-state : 业务自定义透传参数(可选)-->
                    <input id="ticket" name="ticket" type="hidden" value="">
                    <input id="randStr" name="randStr" type="hidden" value="">
                    <button class="logingBut"
                            id="TencentCaptcha"
                            data-appid="1306253469"
                            data-cbfn="callback"
                            type="button"
                            onclick='submitFormWithCaptcha()'
                    >验证并登录</button>
                </form>
function submitFormWithCaptcha() {
    // 直接生成一个验证码对象
    var captcha = new TencentCaptcha('1306253469', function (res) {
        console.log(res)
        // res(未通过验证)= {ret: 1, ticket: null}
        // res(验证成功) = {ret: 0, ticket: "String", randstr: "String"}
        if (res.ret === 0) {
            console.log("get form")
            var form = document.getElementById('form1');
            console.log("get ticket")
            var ticketInput = document.getElementById("ticket");
            console.log("get rnadstr")
            var randstrInput = document.getElementById("randStr");
            console.log(res.ticket)
            ticketInput.value = res.ticket;
            console.log("input randstr")
            randstrInput.value = res.randstr;
            console.log("submit")
            form.submit();

        }
        else
        {
            console.log("验证失败")
            alert("验证失败");
        }
    });
    // 显示验证码
    captcha.show();
}

输入图片说明

6、打卡模块

//打卡
public void InsertInfo(information info, String personId){
        QueryWrapper<person> wrapper = new QueryWrapper<>();
        wrapper.eq("person_id", personId);
        person per = perMapper.selectOne(wrapper);
        info.setName(per.getName());
        info.setPersonId(per.getPersonId());
        info.setTime(LocalDateTime.now());
        System.out.println(LocalDateTime.now());
        infoMapper.insert(info);
    }
//判断当前账号今天是否打卡过
    public boolean is_clock_in(String personId){
        QueryWrapper<information> wrapper = new QueryWrapper<>();

        Date date = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String dateFormat = sdf.format(date);
        //使用time进行模糊查询判断今天是否打卡过
        wrapper.eq("person_id", personId);
        wrapper.like("time", dateFormat);
        information information = infoMapper.selectOne(wrapper);
        if(information == null)
            return false;
        else return true;
    }
@RequestMapping("/{personId}/inputInfo")
    public String inputInfo(@PathVariable("personId") String personId,
                            HttpServletRequest request, Model model){
        person person = perService.selectPerson(personId);
        boolean flag = perService.is_clock_in(personId);
        if(flag == true)
            return "redirect:/userPage/insertInformation/" + personId;

        model.addAttribute("name",person.getName());
        model.addAttribute("personId",person.getPersonId());
        model.addAttribute("information", new information());
        model.addAttribute("flag",0);

        String token = TokenProcessor.getInstance().makeToken();//创建令牌
        request.getSession().setAttribute("token", token);  //在服务器使用session保存token(令牌)

        return "inputInformation";
    }

    private boolean isRepeatSubmit(HttpServletRequest request) {
        String client_token = request.getParameter("token");
        //1、如果用户提交的表单数据中没有token,则用户是重复提交了表单
        if(client_token==null){
            return true;
        }
        //取出存储在Session中的token
        String server_token = (String) request.getSession().getAttribute("token");
        //2、如果当前用户的Session中不存在Token(令牌),则用户是重复提交了表单
        if(server_token==null){
            return true;
        }
        //3、存储在Session中的Token(令牌)与表单提交的Token(令牌)不同,则用户是重复提交了表单
        if(!client_token.equals(server_token)){
            return true;
        }
        return false;
    }

    @RequestMapping("/insertInformation/{personId}")
    public String insertInformation(@ModelAttribute information info,
                                    @PathVariable String personId,
                                    HttpServletRequest request,
                                    Model model){

        boolean b = isRepeatSubmit(request);//判断用户是否是重复提交
        if(b==true){
            System.out.println("请不要重复提交");
        }else {
            request.getSession().removeAttribute("token");//移除session中的token
            System.out.println("处理用户提交请求!!");
            perService.InsertInfo(info, personId);
        }
        model.addAttribute("information", info);
        person person = perService.selectPerson(personId);
        model.addAttribute("name", person.getName());
        model.addAttribute("personId", person.getPersonId());
        model.addAttribute("message", "您今天已打卡成功!");
        model.addAttribute("flag", 1);
        return "inputInformation";
    }

输入图片说明 输入图片说明

7、账号管理

1)显示所有账号:

@RequestMapping("/personList")
    public String personList(Model model){
        List<person> list =adminService.getAllPerson();
        model.addAttribute("personList", list);
        return "person";
    }

输入图片说明

2)编辑修改账号信息:

@RequestMapping("/editPerson/{personId}")
    public String editPerson(@PathVariable String personId, Model model){
        final person person = perService.selectPerson(personId);
        model.addAttribute("person", person);
        return "editPerson";
    }

输入图片说明

3)删除账号
@RequestMapping("/deletePerson/{personId}")
    public String deletePerson(@PathVariable String personId){
        adminService.deletePerson(personId);
        return "redirect:/admin/personList";
    }
4)新增管管理员:
@RequestMapping("/addAdmin")
    public String addAdmin(@ModelAttribute person per, Model model){
        int i = adminService.addAdmin(per);
        if(i == 1){
            return "redirect:/admin/personList";
        }
        else {
            model.addAttribute("name",per.getName());
            model.addAttribute("personId",per.getPersonId());
            model.addAttribute("password",per.getPassword());
            if(perService.selectPerson(per.getPersonId()).getFlag() == 0)
                model.addAttribute("userExists",per.getPersonId() + "为普通用户\n可在列表编辑升级为管理员用户!");
            else
                model.addAttribute("userExists", per.getPersonId() + "用户已存在,并且是管理员用户");
            return "inputAdmin";
        }
    }

输入图片说明

8、数据查询

 1)动态sql变量实体类
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class DynamicSql {
    private String name;
    private String personId;
    private String  latestTime;
    private String  laterTime;
    private String identity;
    private String health;
    private String keyArea;
    private String keyPeople;
    private float temperature;
}
2)sql语句拼接
public List<information> selectByCondition(DynamicSql dynamicSql){
        QueryWrapper<information> wrapper = new QueryWrapper<>();
        if(dynamicSql.getName() != "")
            wrapper.eq("name",dynamicSql.getName());
        if (dynamicSql.getPersonId() != "")
            wrapper.eq("person_id", dynamicSql.getPersonId());
        if(dynamicSql.getLatestTime() != "" && dynamicSql.getLaterTime() !="")
            wrapper.between("time", dynamicSql.getLatestTime(), dynamicSql.getLaterTime() + " 23:59:59");
        if(dynamicSql.getIdentity() != "")
            wrapper.eq("identity", dynamicSql.getIdentity());
        if(dynamicSql.getHealth() != "")
            wrapper.eq("health", dynamicSql.getHealth());
        if(dynamicSql.getKeyArea() != "")
            wrapper.eq("key_area", dynamicSql.getKeyArea());
        if(dynamicSql.getKeyPeople() != "")
            wrapper.eq("key_people", dynamicSql.getKeyPeople());
        if (dynamicSql.getTemperature() != 0.0)
            wrapper.ge("temperature", dynamicSql.getTemperature());
        wrapper.orderByDesc("time");
        List<information> lists = infoMapper.selectList(wrapper);
        return lists;
    }
@RequestMapping("/selectByCondition")
    public String selectByCondition(@ModelAttribute DynamicSql dynamicSql, Model model){
        List<information> informationList = adminService.selectByCondition(dynamicSql);
        model.addAttribute("informationList", informationList);
        model.addAttribute("dynamicSql", dynamicSql);
        return "collection";

    }

查出姓名为杨海林的6月15号到6月21号的打卡数据: 输入图片说明

查出大一的打卡数据: 输入图片说明

查出有咳嗽、发热症状的同学的打卡数据 输入图片说明 等等,可进行多条件查询...

9、把数据导出Excel表格

@RequestMapping("/downloadInformation")
    public String downloadInformation(@ModelAttribute DynamicSql dynamicSql, HttpServletResponse response, Model model) throws IOException {
        HSSFWorkbook workbook = new HSSFWorkbook();
        HSSFSheet sheet = workbook.createSheet("打卡信息表");
        List<information> informationExcelDownloads = adminService.selectByCondition(dynamicSql);
        String fileName = "information" + ".xls";
        int rowNum = 1;
        String [] headers = {"name", "person_id", "birthday", "CD_type", "CD_card", "identity",
                "phone", "native_city", "home_address", "now_address", "health", "key_area", "key_people",
                "temperature", "time"};
        HSSFRow row = sheet.createRow(0);
        for (int i = 0;i<headers.length;i++){
            HSSFCell cell = row.createCell((short) i);
            HSSFRichTextString text = new HSSFRichTextString(headers[i]);
            cell.setCellValue(text);
        }
        for (information info : informationExcelDownloads){
            HSSFRow row1 = sheet.createRow(rowNum);
            row1.createCell((short) 0).setCellValue(new HSSFRichTextString(info.getName()));
            row1.createCell((short) 1).setCellValue(new HSSFRichTextString(info.getPersonId()));
            row1.createCell((short) 2).setCellValue(new HSSFRichTextString(info.getBirthday().toString()));
            row1.createCell((short) 3).setCellValue(new HSSFRichTextString(info.getCdType()));
            row1.createCell((short) 4).setCellValue(new HSSFRichTextString(info.getCdCard()));
            row1.createCell((short) 5).setCellValue(new HSSFRichTextString(info.getIdentity()));
            row1.createCell((short) 6).setCellValue(new HSSFRichTextString(info.getPhone()));
            row1.createCell((short) 7).setCellValue(new HSSFRichTextString(info.getNativeCity()));
            row1.createCell((short) 8).setCellValue(new HSSFRichTextString(info.getHomeAddress()));
            row1.createCell((short) 9).setCellValue(new HSSFRichTextString(info.getNowAddress()));
            row1.createCell((short) 10).setCellValue(new HSSFRichTextString(info.getHealth()));
            row1.createCell((short) 11).setCellValue(new HSSFRichTextString(info.getKeyArea()));
            row1.createCell((short) 12).setCellValue(new HSSFRichTextString(info.getKeyPeople()));
            row1.createCell((short) 13).setCellValue(new HSSFRichTextString(String.valueOf(info.getTemperature())));
            row1.createCell((short) 14).setCellValue(new HSSFRichTextString(String.valueOf(info.getTime()).replace('T', ' ')));
            rowNum++;

        }
        response.setContentType("application/octet-stream");
        response.setHeader("Content-disposition", "attachment;filename=" + fileName);
        response.flushBuffer();
        workbook.write(response.getOutputStream());
        return "redirect:/admin/personList";
    }

查出姓名为HelenYang的数据并导出excel表: 输入图片说明

输入图片说明

输入图片说明

五、数据库设计

输入图片说明

相对应实体类:

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class person {
    @TableId
    private String personId; //学号、职工号
    private String name;  //姓名
    private String password; //密码
    private int flag;//标记为是否为管理员, 1为管理员, 0不是管理员
}
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class information {
    private String name;         //姓名
    private String personId;     //学号,职工号
    private Date birthday;       //出生日期
    private String cdType;       //证件类型
    private String cdCard;       //证件号码
    private String phone;        //联系电话
    private String identity;     //职业
    private String nativeCity;   //籍贯
    private String homeAddress;  //户口所在地
    private String nowAddress;   //现在居住地址
    private String health;       //健康状况
    private String keyArea;      //近14天是否到达过重点地区
    private String keyPeople;    //近14天是否接触过重点人群
    private float temperature;   //今日体温
    private LocalDateTime time;  //打卡时间

}

六、Docker部署

Dockerfile

输入图片说明

将jar包和Dockerfile放到同一个目录下

输入图片说明

Docker相关命令

docker build -t healthsystem .  //构建healthsystem镜像
docker run -d -P --name healthsystem-test healthsystem //生成容器并后台运行
curl localhost:49153  //本机地址访问

Docker内部访问

构架镜像

输入图片说明

后台启动服务

输入图片说明

访问测试--测试成功

输入图片说明

空文件

简介

取消

发行版

暂无发行版

贡献者

全部

近期动态

不能加载更多了
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/helen_yang/health-system.git
git@gitee.com:helen_yang/health-system.git
helen_yang
health-system
HealthSystem
master

搜索帮助