这个作业属于哪个课程 | 2301-计算机学院-软件工程 |
---|---|
这个作业要求在哪里 | 第二次作业–前后端交互计算器 |
这个作业的目标 | wanc前后端交互计算器 |
其他参考文献 | Javascript文档、gin 中文文档、gorm中文文档 |
文章目录
1、GitCode项目地址以及代码规范链接
Google 开源项目风格指南——中文版
Google Style Guides
2、PSP表格
PSP | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 60 | 50 |
• Estimate | • 估计这个任务需要多少时间 | 15 | 15 |
Development | 开发 | 1000 | 1000 |
• Analysis | • 需求分析 (包括学习新技术) | 100 | 100 |
• Design Spec | • 生成设计文档 | 15 | 15 |
• Design Review | • 设计复审 | 30 | 30 |
• Coding Standard | • 代码规范 (为目前的开发制定合适的规范) | 30 | 30 |
• Design | • 具体设计 | 15 | 15 |
• Coding | • 具体编码 | 500 | 500 |
• Code Review | • 代码复审 | 45 | 45 |
• Test | • 测试(自我测试,修改代码,提交修改) | 65 | 65 |
Reporting | 报告 | 90 | 90 |
•Test Repor t | • 测试报告 | 30 | 30 |
• Size Measurement | • 计算工作量 | 15 | 15 |
• Postmortem & Process Improvement Plan | • 事后总结, 并提出过程改进计划 | 45 | 45 |
合计 | 1150 | 1140 |
3、科学计算器及利率计算器功能展示
普通计算器:
功能一、四则运算、取余、括号:
功能二、清零回退:
功能三、错误提示:
功能四、历史记录:
附加功能:科学计算器:
利率计算器:
基本功能展示:
附加功能、前端修改存贷款利息:
4、设计以及实现的过程:
功能结构图:
实现:
-
数据库:
在MySQL中创建命名为calculator、current、regular、loans表。利用了workbench这一可视化工具,为各表添加相应的属性,确保能够存储历史记录、活期存款利率、定期存款利率以及贷款利率。
后端:
使用Gin框架建立一个后端服务,定义路由和处理函数,利用Gorm连接数据库进行交互,通过数据库操作函数实现对历史记录的增加和查询,以及对两类存款利率和贷款利率的获取和修改。
前端:
使用HTML以及CSS设计布局并添加相应的控件来构建用户交互界面,以及使用JavaScript来定义各类事件,并且利用Fetch API发送请求给后端,实现前后端的交互。
5、关键代码展示
前端:
计算出结果之后,发送请求给后端:
//普通计算器
function clearDisplay() {
document.getElementById('display').value = '';
}// 清除display中的内容,即清空
function back() {
let now_result = document.getElementById("display");
document.getElementById("display").value = now_result.value.substring(0, now_result.value.length - 1);
}//回退键
async function calculate() {
const calculation = document.getElementById('display').value;
let result ;
try {
result = eval(calculation);
document.getElementById('display').value = " ";
document.getElementById('display').value += result;
} catch (error) {
// 计算出现的错误直接catch并在显示框中显示错误,提示用户
document.getElementById('display').value = 'ERROR';
}
try {
let obj ={
calculation: calculation,
result: result,
}
let res =await fetch('http://localhost:8080/postdata',{
method:'post',
headers:{
'Content-Type':'application/json'
},
body:JSON.stringify(obj)
})//向后端发送存储计算表达式的请求
} catch (error) {
console.log(error);
}
}
async function getAns() {
let url = 'http://localhost:8080/getdata';
try {
let response = await fetch(url);
let res= await response.json();
console.log(res);
document.getElementById('record').innerText += (res.calculation+"="+res.result + "\n");
} catch (error) {
console.log('Request Failed', error);
}
}//获取历史记录
//利率计算器
async function getloans(){
loansflag=1;
loanflag=1;
let now;
alert('贷款');
let url = 'http://localhost:8080/loansdata';
try {
let response = await fetch(url);
now= await response.json();
} catch (error) {
console.log('Request Failed', error);
}
let timeValue=document.getElementById('time').value;
if(timeValue==="6"){
rate=now.six_months;
}else if(timeValue==="12"){
rate=now.a_year;
}else if(parseFloat(timeValue)>12&&parseFloat(timeValue)<=30){
rate=now.one_three_years;
}else if(parseFloat(timeValue)>30&&parseFloat(timeValue)<60){
rate=now.three_five_years;
}else if(timeValue==="60"){
rate=now.five_years;
}else{
rate=0;
}
}//获取贷款的利率
function jumpToElse() {
if(curflag===1&®flag!=1&&loanflag!=1){
window.location.href = "current.html";
}else if(curflag!=1&®flag===1&&loanflag!=1){
window.location.href = "regular.html";
}else if(curflag!=1&®flag!=1&&loanflag===1){
window.location.href = "loans.html";
}else{
alert('请明确要修改的对象');
}
}//跳转到修改利率的界面
async function changeloans(){
let temp=parseFloat(document.getElementById('rate').value);
let month=parseFloat(document.getElementById('Month').value);
if(month>12&&month<=36){
month=13;
}else if(month>36&&month<60){
month=35;
}
try {
let obj ={
type:month,
rate:temp,
}
let res =await fetch('http://localhost:8080/postloans',{
method:'post',
headers:{
'Content-Type':'application/json'
},
body:JSON.stringify(obj)
})
} catch (error) {
console.log(error);
}
document.getElementById('rate').value='';
document.getElementById('Month').value1='';
alert('修改成功');
}//修改贷款的利率
后端:
import (
"net/http"
"github.com/gin-contrib/cors"
"github.com/gin-gonic/gin"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
router.Use(cors.Default())
config := cors.DefaultConfig()
config.AllowOrigins = []string{"*"}
router.Use(cors.New(config))
//解决跨域问题
func initMysql() {
dsn := "root:123456@tcp(127.0.0.1:3306)/calculator_database?charset=utf8mb4&parseTime=True&loc=Local"
SqlSession, _ = gorm.Open(mysql.Open(dsn), &gorm.Config{})
}//连接到数据库
router.GET("/getdata", func(c *gin.Context) {
SqlSession.Where("number > ?", 0).Order("number DESC").Limit(10).Find(&user)
c.JSON(http.StatusOK, user)
}) //获取计算器历史记录
router.POST("/postdata", func(ctx *gin.Context) {
if err := ctx.ShouldBindJSON(&user); err != nil {
// 返回错误信息
ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
ctx.JSON(http.StatusOK, gin.H{
"calculatiion": user.Calculation,
"result": user.Result,
})
SqlSession.Create(Record{Calculation: user.Calculation, Result: user.Result})
}) //向数据库存储历史记录
6、心得体会
上次利用的是C#来开发计算器,但是实现不了前后端分离这一要求,不能在原有的基础上进行改造。于是就从零开始学习前后端的相关知识,比较难的地方其实在于编写代码的部分,遇到比较折磨的是事件逻辑的实现,因为不大熟悉前后端的交互,导致bug频出,比如后端定义的是float类型的字段,前端发送的却是字符串;又或者像是很基础的获取元素,最开始是使用getElementsByClassName() ,后面发现不会使用它进行元素更改,然后就把class选择器换成id选择器以及很多的一些小问题。最终造成了一个屎山,只能说继续努力,精简代码。