第二次作业(计算器的注册计算功能和简单的网页登录界面)

发布时间 2023-11-24 21:16:23作者: 田纪元

一、实验目的

       1.掌握软件开发的基本流程

       2.掌握常用的软件开发方式和工具。

二、实验内容

        设计一个包含登录界面的计算器软件,该软件可以实现第一次作业中的全部功能,同时使用数据库可以保存用户的历史计算记录和时间。

三、项目流程和功能

     1.计算器的实现

     2.登录网页版计算器

     3.界面的注册登录功能

     4.对使用者的账号密码信息进行保存

     5.进行加减乘除开方运算并用数据库对这些数据进行精确地时间性保存

四、项目所需要的工具与环境

     1.visio绘图工具

     2.2021版Idea

     3.MySQL5.5版本编写数据库

     4.Navicat来连接MySQL

    5.JDK.8.0_121

五、流程图

    1.注册流程图

                                             

                                

     2.登录流程图 

                    

                                 

六、功能界面展示

      1.登录界面

                            

  2.注册用户

                                 

 

 3.登录计算

                             

 4.数据库展示

                              

                             

七、代码展示

  1.用户的登录过程

 1 package org.calculator.controller;
 2 
 3 import org.calculator.entity.History;
 4 import org.calculator.service.UserService;
 5 import org.springframework.stereotype.Controller;
 6 import org.springframework.web.bind.annotation.*;
 7 
 8 import javax.annotation.Resource;
 9 import javax.servlet.http.HttpServletRequest;
10 import java.util.HashMap;
11 import java.util.List;
12 import java.util.Map;
13 
14 /**
15  * 用户控制器
16  *
17  * @author TianJiyuan
18  * @date 2023/11/20
19  */
20 @Controller
21 @RestController
22 @ResponseBody
23 public class UserController {
24     @Resource
25     private UserService userService;
26 
27     @PostMapping("login")
28     public Map<String, Object> login(HttpServletRequest request, @RequestParam("username") String username, @RequestParam("password") String password) {
29         Map<String, Object> result = new HashMap<String, Object>();
30         result.put("code", 0);
31         String status = userService.login(request.getSession(), username, password);
32         if ("success".equals(status)) {
33             result.put("msg", "登录成功");
34         } else {
35             result.put("code", 1);
36             result.put("msg", "用户名或密码错误");
37         }
38         return result;
39     }
40 
41     @PostMapping("signIn")
42     public Map<String, Object> signIn(@RequestParam("username") String username, @RequestParam("password") String password) {
43         Map<String, Object> result = new HashMap<String, Object>();
44         result.put("code", 0);
45 
46         String status = userService.signIn(username, password);
47         if ("success".equals(status)) {
48             result.put("msg", "登录成功");
49         } else {
50             result.put("code", 1);
51             result.put("msg", "账号已存在");
52         }
53 
54         return result;
55     }
56 
57     @PostMapping("saveHis")
58     public Map<String, Object> saveHis(HttpServletRequest request, @RequestParam("content") String content, @RequestParam("time") String time) {
59         Map<String, Object> result = new HashMap<String, Object>();
60         result.put("code", 0);
61         String status = userService.saveHis(request.getSession(), content, time);
62         if ("success".equals(status)) {
63             result.put("msg", "保存成功");
64         } else {
65             result.put("code", 1);
66             result.put("msg", "保存失败");
67         }
68         return result;
69     }
70 
71     @GetMapping("getHis")
72     public Map<String, Object> getHis(HttpServletRequest request) {
73         Map<String, Object> result = new HashMap<String, Object>();
74         List<History> historyList = userService.getHis(request.getSession());
75         result.put("code", 0);
76         result.put("data", historyList);
77         return result;
78     }
79 
80     @GetMapping("logOut")
81     public String logOut(HttpServletRequest request) {
82         request.getSession().removeAttribute("login");
83         return "success";
84     }
85 }
2.用户账号的历史信息
 1 package org.calculator.entity;
 2 
 3 import com.baomidou.mybatisplus.annotation.TableId;
 4 import com.baomidou.mybatisplus.annotation.TableName;
 5 import lombok.Getter;
 6 import lombok.Setter;
 7 
 8 /**
 9  * 历史
10  *
11  * @author TianJiyuan
12  * @date 2023/11/21
13  */
14 @Getter
15 @Setter
16 @TableName
17 public class History {
18     @TableId
19     private String id;
20 
21     private String username;
22     
23     private String title;
24 
25     private String time;
26 }
3.用户表
 1 package org.calculator.entity;
 2 
 3 import com.baomidou.mybatisplus.annotation.TableId;
 4 import lombok.Getter;
 5 import lombok.Setter;
 6 
 7 import java.sql.Timestamp;
 8 
 9 /**
10  * 用户表
11  *
12  * @author TianJiyuan
13  * @date 2023/11/20
14  */
15 @Getter
16 @Setter
17 public class User {
18     @TableId
19     private String username;
20 
21     private String password;
22 }
4.历史记录mapper
 1 package org.calculator.mapper;
 2 
 3 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 4 import org.calculator.entity.History;
 5 
 6 /**
 7  * 历史记录mapper
 8  *
 9  * @author TianJiyuan
10  * @date 2023/11/21
11  */
12 public interface HistoryMapper extends BaseMapper<History> {
13 }
5.用户Mapper
 1 package org.calculator.mapper;
 2 
 3 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 4 import org.calculator.entity.User;
 5 
 6 /**
 7  * 用户Mapper
 8  *
 9  * @author TianJiyuan
10  * @date 2023/11/20
11  */
12 public interface UserMapper extends BaseMapper<User> {
13 }
6.用户相关服务
  1 package org.calculator.service;
  2 
  3 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  4 import org.calculator.entity.History;
  5 import org.calculator.entity.User;
  6 import org.calculator.mapper.HistoryMapper;
  7 import org.calculator.mapper.UserMapper;
  8 import org.springframework.stereotype.Service;
  9 
 10 import javax.annotation.Resource;
 11 import javax.servlet.http.HttpSession;
 12 import java.util.ArrayList;
 13 import java.util.List;
 14 
 15 /**
 16  * 用户相关服务
 17  *
 18  * @author TianJiyuan
 19  * @date 2023/11/20
 20  */
 21 @Service
 22 public class UserService {
 23     @Resource
 24     private UserMapper userMapper;
 25 
 26     @Resource
 27     private HistoryMapper historyMapper;
 28 
 29     /**
 30      * 注册
 31      *
 32      * @param username 用户名
 33      * @param password 密码
 34      * @return success | error
 35      */
 36     public String signIn(String username, String password) {
 37         User existUser = userMapper.selectById(username);
 38         if (existUser != null) {
 39             return "error";
 40         }
 41 
 42         User user = new User();
 43         user.setUsername(username);
 44         user.setPassword(password);
 45 
 46         userMapper.insert(user);
 47 
 48         return "success";
 49     }
 50 
 51     /**
 52      * 登录
 53      *
 54      * @param username 用户名
 55      * @param password 密码
 56      * @return success | error
 57      */
 58     public String login(HttpSession session, String username, String password) {
 59         User user = userMapper.selectById(username);
 60         if (user == null) {
 61             return "error";
 62         }
 63         if (!user.getPassword().equals(password)) {
 64             return "error";
 65         }
 66         session.setAttribute("login", user);
 67 
 68         return "success";
 69     }
 70 
 71     /**
 72      * 保存历史记录
 73      *
 74      * @param content 保存的内容
 75      * @return success | error
 76      */
 77     public String saveHis(HttpSession session, String content, String time) {
 78         User user = (User) session.getAttribute("login");
 79         History history = new History();
 80         history.setTitle(content);
 81         history.setTime(time);
 82         history.setUsername(user.getUsername());
 83         historyMapper.insert(history);
 84         return "success";
 85     }
 86 
 87     /**
 88      * 获取历史记录
 89      *
 90      * @param session session
 91      * @return 历史记录列表
 92      */
 93     public List<History> getHis(HttpSession session) {
 94         User user = (User) session.getAttribute("login");
 95         List<History> historyList = historyMapper.selectList(new QueryWrapper<History>().eq("username", user.getUsername()));
 96         if (historyList == null) {
 97             return new ArrayList<History>();
 98         }
 99         return historyList;
100     }
101 }
7.主函数
 1 package org.calculator;
 2 
 3 import org.mybatis.spring.annotation.MapperScan;
 4 import org.springframework.boot.SpringApplication;
 5 import org.springframework.boot.autoconfigure.SpringBootApplication;
 6 
 7 @SpringBootApplication
 8 @MapperScan("org.calculator.mapper")
 9 public class CalculatorApplication {
10 
11     public static void main(String[] args) {
12         SpringApplication.run(CalculatorApplication.class, args);
13     }
14 
15 }
8.MySQL数据库对历史数据进行处理
 1 /*
 2  Navicat Premium Data Transfer
 3 
 4  Source Server         : localhost
 5  Source Server Type    : MySQL
 6  Source Server Version : 50717
 7  Source Host           : localhost:3306
 8  Source Schema         : calculator
 9 
10  Target Server Type    : MySQL
11  Target Server Version : 50717
12  File Encoding         : 65001
13 
14  Date: 21/11/2023 11:22:54
15 */
16 
17 SET NAMES utf8mb4;
18 SET FOREIGN_KEY_CHECKS = 0;
19 
20 -- ----------------------------
21 -- Table structure for history
22 -- ----------------------------
23 DROP TABLE IF EXISTS `history`;
24 CREATE TABLE `history`  (
25   `id` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
26   `username` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
27   `title` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
28   `time` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
29   PRIMARY KEY (`id`) USING BTREE
30 ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
31 
32 -- ----------------------------
33 -- Records of history
34 -- ----------------------------
35 INSERT INTO `history` VALUES ('1726800603630477313', 'admin', '6-3 = 3', '2023/11/21 11:12:00');
36 INSERT INTO `history` VALUES ('1726801184491290626', 'admin', '9*5 = 45', '2023/11/21 11:14:19');
37 INSERT INTO `history` VALUES ('1726801234583863298', 'admin', '9*8 = 72', '2023/11/21 11:14:31');
38 INSERT INTO `history` VALUES ('1726801318641909762', 'admin', '6+6+3 = 15', '2023/11/21 11:14:51');
39 
40 -- ----------------------------
41 -- Table structure for user
42 -- ----------------------------
43 DROP TABLE IF EXISTS `user`;
44 CREATE TABLE `user`  (
45   `username` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
46   `password` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
47   PRIMARY KEY (`username`) USING BTREE
48 ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
49 
50 -- ----------------------------
51 -- Records of user
52 -- ----------------------------
53 INSERT INTO `user` VALUES ('admin', '123456');
54 
55 SET FOREIGN_KEY_CHECKS = 1;
9.计算器的登录界面和对相关处理数据进行保存
  1 <!DOCTYPE html>
  2 <html lang="en">
  3 <head>
  4     <meta charset="UTF-8">
  5     <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6     <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
  7     <title>计算器</title>
  8     <style>
  9         * {
 10             margin: 0;
 11             padding: 0;
 12         }
 13 
 14         body {
 15             width: 100%;
 16         }
 17 
 18         /* 登录部分 */
 19 
 20         .login {
 21             position: absolute;
 22             top: 50%;
 23             left: 50%;
 24             margin: -150px 0 0 -150px;
 25             width: 300px;
 26             height: 300px;
 27         }
 28 
 29         .login h1 {
 30             color: #333;
 31             letter-spacing: 2px;
 32             text-align: center;
 33             margin-bottom: 20px;
 34         }
 35 
 36         input {
 37             line-height: 36px;
 38             width: 100%;
 39             margin-bottom: 10px;
 40             border: 1px solid black;
 41             border-radius: 5px;
 42             letter-spacing: 2px;
 43             padding: 0 10px;
 44             box-sizing: border-box;
 45         }
 46 
 47         .form_b {
 48             width: 100%;
 49             display: flex;
 50             justify-content: space-between;
 51         }
 52 
 53         .btn {
 54             width: 46%;
 55             padding: 10px;
 56             background-color: #000;
 57             color: #fff;
 58             border: 1px solid black;
 59             border-radius: 25px;
 60             cursor: pointer;
 61             margin-top: 10px;
 62         }
 63 
 64         /* 内容部分 */
 65 
 66         .content {
 67             width: 100%;
 68             display: flex;
 69         }
 70 
 71         .his_content {
 72             width: 800px;
 73             padding: 50px;
 74             max-height: 100vh;
 75             box-sizing: border-box;
 76         }
 77 
 78         .history {
 79             height: 100%;
 80             overflow-y: auto;
 81             font-size: 30px;
 82         }
 83 
 84         .history_item {
 85             display: flex;
 86             justify-content: space-between;
 87             padding: 10px;
 88             color: #333;
 89             border-bottom: 1px solid #f1f1f1;
 90         }
 91 
 92         .item_right {
 93             font-size: 24px;
 94             color: #666;
 95         }
 96 
 97         /*table部分*/
 98 
 99         table {
100             width: 460px;
101             height: 470px;
102             margin: 100px 180px;
103         }
104 
105         table tr {
106             width: 100%;
107             height: 20%;
108         }
109 
110         table tr td {
111             box-sizing: border-box;
112             width: 16.66%;
113             font-size: 20px;
114             color: #333;
115             text-align: center;
116             cursor: pointer;
117             box-shadow: 0px 0px 4px #666 inset;
118         }
119 
120         table tr button {
121             width: 100%;
122             height: 100%;
123             outline: none;
124             background-color: transparent;
125             border: none;
126             font-size: 20px;
127             color: #333;
128             cursor: pointer;
129         }
130 
131         table tr button:hover {
132             background: #ccc;
133         }
134 
135         table td input {
136             width: 100%;
137             height: 100%;
138             background-color: transparent;
139             border: none;
140             outline: none;
141             cursor: pointer;
142             font-size: 20px;
143             color: #333;
144             text-align: right;
145         }
146 
147         .login_out {
148             position: absolute;
149             top: 20px;
150             right: 50px;
151             cursor: pointer;
152         }
153 
154     </style>
155 </head>
156 
157 <body>
158 
159 <div class="login_out" onclick="loginOut()">
160     退出登录
161 </div>
162 
163 <div class="login">
164     <h1>计算器</h1>
165     <input id="userName" type="text" placeholder="请输入用户名">
166     <input id="password" type="password" placeholder="请输入密码">
167     <div class="form_b">
168         <button class="btn" onclick="check(1)">注册</button>
169         <button class="btn" onclick="check(2)">登录</button>
170     </div>
171 </div>
172 
173 <div class="content">
174     <table id="calculator" onclick="result(event)">
175         <tr>
176             <td colspan="6">
177                 <input type="text" class="contentValue">
178             </td>
179         </tr>
180         <tr>
181             <td>
182                 <button class="numb" value="1">1</button>
183             </td>
184             <td>
185                 <button class="numb" value="2">2</button>
186             </td>
187             <td>
188                 <button class="numb" value="3">3</button>
189             </td>
190             <td>
191                 <button class="numb" value="+">+</button>
192             </td>
193             <td>
194                 <button class="numb" value="C">C</button>
195             </td>
196         </tr>
197         <tr>
198             <td>
199                 <button class="numb" svalue="4">4</button>
200             </td>
201             <td>
202                 <button class="numb" value="5">5</button>
203             </td>
204             <td>
205                 <button class="numb" value="6">6</button>
206             </td>
207             <td>
208                 <button class="numb" value="-">-</button>
209             </td>
210             <td>
211                 <button class="numb" value="Back">Back</button>
212             </td>
213         </tr>
214 
215         <td>
216             <button class="numb" value="7">7</button>
217         </td>
218         <td>
219             <button class="numb" value="8">8</button>
220         </td>
221         <td>
222             <button class="numb" value="9">9</button>
223         </td>
224         <td>
225             <button class="numb" value="*">*</button>
226         </td>
227         <td rowspan="2">
228             <button class="numb" value="=">=</button>
229         </td>
230         </tr>
231         <tr>
232             <td>
233                 <button class="numb" value=".">.</button>
234             </td>
235             <td>
236                 <button class="numb" value="0">0</button>
237             </td>
238             <td>
239                 <button class="numb" value="/">/</button>
240             </td>
241             <td>
242                 <button class="numb">&radic;x</button>
243             </td>
244         </tr>
245     </table>
246 
247     <div class="his_content">
248         <h1>历史记录</h1>
249         <div class="history">
250 
251         </div>
252     </div>
253 </div>
254 
255 <script>
256     let record = [];
257 
258     function getRecord() {
259         $.ajax({
260             url: 'getHis',
261             type: 'GET',
262             dataType: 'json',
263             success: function (response) {
264                 if (response.code === 0) {
265                     // 接口成功后
266                     record = response.data;
267                     historyShow()
268                 } else {
269                     alert(response.msg);
270                 }
271             }
272         });
273     }
274 
275     window.onload = function () {
276         let login = localStorage.getItem("login");
277         document.querySelector('.contentValue').value = ''
278         document.querySelector('#userName').value = ''
279         document.querySelector('#password').value = ''
280         if (login == 'true') {
281             document.querySelector('.login').style.display = 'none';
282             getRecord()
283         } else {
284             document.querySelector('.content').style.display = 'none'
285             document.querySelector('.login_out').style.display = 'none'
286         }
287     }
288 
289     // 校验信息
290     function check(type) {
291         let userName = document.querySelector('#userName').value
292         let password = document.querySelector('#password').value
293         if (userName && password) {
294             let params = {
295                 userName,
296                 password
297             }
298             if (type == 1) {
299                 // 注册接口
300                 register(params)
301             } else {
302                 // 登录接口
303                 login(params)
304             }
305         } else {
306             alert('请输入完整');
307             return;
308         }
309     }
310 
311     // 登录
312     function login(params) {
313         $.ajax({
314             url: '/login',
315             type: 'POST',
316             dataType: 'json',
317             data: {
318                 username: params.userName,
319                 password: params.password,
320             },
321             success: function (response) {
322                 if (response.code === 0) {
323                     // 接口成功后
324                     localStorage.setItem("login", true)
325                     localStorage.setItem("username", params.userName)
326                     document.querySelector('.login').style.display = 'none'
327                     document.querySelector('.content').style.display = 'flex'
328                     document.querySelector('.login_out').style.display = 'block'
329                     document.querySelector('#userName').value = ''
330                     document.querySelector('#password').value = ''
331                     getRecord();
332                     historyShow();
333                 } else {
334                     alert(response.msg);
335                 }
336             }
337         });
338     }
339 
340     // register
341     function register(params) {
342         $.ajax({
343             url: 'signIn',
344             type: 'POST',
345             dataType: 'json',
346             data: {
347                 username: params.userName,
348                 password: params.password,
349             },
350             success: function (response) {
351                 if (response.code === 0) {
352                     alert("注册成功");
353                     // 接口成功后
354                     document.querySelector('#userName').value = ''
355                     document.querySelector('#password').value = ''
356                 } else {
357                     alert(response.msg);
358                 }
359             }
360         });
361 
362     }
363 
364     // 添加到数据库
365     function addRecord(obj) {
366         let params = {
367             content: obj.title,
368             time: obj.time
369         }
370         $.ajax({
371             url: '/saveHis',
372             type: 'POST',
373             dataType: 'json',
374             data: params,
375             success: function (response) {
376                 if (response.code !== 0) {
377                     alert(response.msg);
378                 }
379             }
380         });
381     }
382 
383     // 计算功能
384     function result(e) {
385         //获取触发事件的元素
386         //利用e.target||e.srcElement,获取到触发事件的元素,||连接两个语法是为了解决不同浏览器的兼容性问题。
387         var obj = e.target || e.srcElement;
388         if (obj.nodeName != "BUTTON") {
389             return;
390         }
391         var v = obj.innerHTML;
392         var content = document.querySelector('.contentValue');
393         if (v === "C") {
394             content.value = 0;
395         } else if (v === "=") {
396             //获取到输入框的值
397             var exp = content.value;
398             //这里用try catch抛出异常,针对运算错误的情况
399             try {
400                 let timer = new Date()
401                 let obj = {
402                     title: exp,
403                     time: timer.toLocaleString()
404                 }
405                 var result = eval("(" + exp + ")");
406                 //将计算结果赋值给输入框
407                 content.value = result;
408 
409                 // 更新历史数据
410                 obj.title = obj.title + ' = ' + result
411                 record.push(obj)
412                 addRecord(obj)
413                 historyShow()
414             } catch (e) {
415                 console.log(e);
416                 content.value = "error";
417             }
418         } else if (v === "√x") {
419             let timer = new Date()
420             let obj = {
421                 title: '√' + content.value,
422                 time: timer.toLocaleString()
423             }
424             var result = mysqrt(content.value);
425             content.value = result;
426 
427             // 更新历史数据
428             obj.title = obj.title + ' = ' + result
429             record.push(obj)
430             addRecord(obj)
431             historyShow()
432 
433         } else if (v === "Back") {
434             var str = content.value;
435             var result = str.substring(0, str.length - 1);
436             content.value = result;
437         } else {
438             if (content.value === "0")
439                 content.value = " ";
440             content.value += v;
441         }
442     }
443 
444     // 开方
445     function mysqrt(x) {
446         r = x;
447         while (r * r > x) {
448             r = (r + x / r) / 2
449         }
450         return r
451     }
452 
453     // 历史数据渲染
454     function historyShow() {
455         let listStr = ''
456 
457         record.forEach(item => {
458             listStr += `
459                 <div class="history_item">
460                     <div class="item_left">
461                         ${item.title}
462                     </div>
463                     <div class="item_right">
464                         ${item.time}
465                     </div>
466                 </div>
467                 `
468         })
469         document.querySelector('.history').innerHTML = listStr
470     }
471 
472     function loginOut() {
473         localStorage.setItem("login", false)
474         location.reload();
475     }
476 </script>
477 </body>
478 
479 </html>
10.连接本地数据库进行网页登录
 1 server:
 2   port: 8081
 3 spring:
 4   application:
 5     name: calculator
 6   datasource:
 7     url: jdbc:mysql://localhost:3306/calculator?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=false
 8     type: com.zaxxer.hikari.HikariDataSource
 9     driver-class-name: com.mysql.cj.jdbc.Driver
10     username: root
11     password: 123456
12     hikari:
13       connection-test-query: SELECT 1
14       connection-timeout: 30000
15       validation-timeout: 10000
16       idle-timeout: 600000
17       max-lifetime: 120000
18       maximum-pool-size: 50
19       minimum-idle: 10