# 102101337_calculator_frontend **Repository Path**: sxl_code/102101337_calculator_frontend ## Basic Information - **Project Name**: 102101337_calculator_frontend - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2023-10-21 - **Last Updated**: 2023-10-22 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 软件工程第二次作业--前后端交互计算器 [toc] 作业基本信息 | 这个作业属于哪个课程 | < [2301-计算机学院-软件工程](https://bbs.csdn.net/forums/ssynkqtd-05)> | | -------------------- | ------------------------------------------------------------ | | 这个作业要求在哪里 | < [软工实践第二次作业](https://bbs.csdn.net/topics/617377308)> | | 这个作业的目标 | < 实现一个前后端分离的计算器,用数据库储存相关数据 > | | 其他参考文献 | < [python flask](https://www.bilibili.com/video/BV17r4y1y7jJ/?spm_id_from=333.337.search-card.all.click&vd_source=25de2f223623055354598b500af309f3) > < [ajax](https://www.bilibili.com/video/BV18y4y1L73h/?p=2&share_source=copy_web&vd_source=f0187d434b486c29f9bf52c4cf2b3fa5)> | ## Gitcode项目地址 ### [前端]() ### [后端]() ## PSP表格 | PSP | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) | | :-------------------------------------- | :-------------------------------------- | :--------------: | :--------------: | | Planning | 计划 | 60 | 80 | | • Estimate | • 估计这个任务需要多少时间 | 20 | 25 | | Development | 开发 | 700 | 1000 | | • Analysis | • 需求分析 (包括学习新技术) | 800 | 1000 | | • Design Spec | • 生成设计文档 | 60 | 50 | | • Design Review | • 设计复审 | 50 | 60 | | • Coding Standard | • 代码规范 (为目前的开发制定合适的规范) | 30 | 30 | | • Design | • 具体设计 | 100 | 150 | | • Coding | • 具体编码 | 400 | 450 | | • Code Review | • 代码复审 | 60 | 60 | | • Test | • 测试(自我测试,修改代码,提交修改) | 120 | 200 | | Reporting | 报告 | 120 | 100 | | • Test Report | • 测试报告 | 50 | 60 | | • Size Measurement | • 计算工作量 | 30 | 30 | | • Postmortem & Process Improvement Plan | • 事后总结, 并提出过程改进计划 | 80 | 90 | | | 合计 | 2800 | 3385 | ## 设计实现过程 >首页:菜单选择计算器 >子页:1.基本计算器 2.利率计算器 ## 成品展示 ### 界面展示 > 菜单: ### 基础计算器 #### 功能一:加减乘除、取余、括号运算 >完成基础+,-,* ,/,%,()运算,并将输入的字符串和结果存储到后端数据库中 #### 功能二:清零回退 >实现字符串输入的清零和回退功能 #### 功能三:错误提示 >非法输入提示,例如:0不能作为除数,括号不匹配,语法错误等 #### 功能四:读取历史记录 >ans按钮返回上一个计算结果 >查看历史记录按钮,输出对应的计算式及结果 >数据皆从后端的数据库中读取 #### 附加功能一:科学计算器 >计算三角函数、lg、ln #### 附加功能二:页面原型设计 ### 利率计算器功能 #### 界面展示 #### 功能一:计算存款、贷款利息 >数据库中存储利率表(可随时修改利率),对应利率如下图所示 >用两个输入框分别读取前端的输入数据,1.输入存款/贷款金额,2.存/贷时长(单位:年)。 >从后端获取利率表,输出计算后对应的存/贷利息。 #### 功能二:前端修改存贷款利率 >在前端页面输入被修改的信息,数据库中表的数值相应修改 ## 解题思路描述 ### 问题1:实现前端与后端交互 >前端使用html、css、JavaScript,vue设计界面及效果展示;使用ajax进行数据传输 >后端使用python flask jinja2进行数据传输 ### 问题2:实现后端与数据库连接 >后端使用python flask ORM模型的CRUD进行数据库的增删改查 >数据库使用mysq进行数据保存 ### 问题3:Python实现基础计算器 >创建类Calculate,并定义Add(),Result(),Clear(),back()四个函数进行数据处理 >创建类Cal_History,连接数据库 ### 问题4:Python实现利率计算器 >创建类deposit和类loan,连接数据库 ## 关键代码展示 ### html设计界面内容 >以基本计算器显示运算式和计算器第一行为例 >点击每个按键触发一个函数,执行运算操作 ```python
0

.....
``` >利率计算器设计 >采用form结构,提交按钮,绑定函数实现数据传送;重置按钮清空 ```python
存款利率计算

存款金额:

存款时长:



``` ### css设计界面图标样式 >以按钮为例 >button {...}设计初始样式;button:hover {...}设计鼠标触碰样式 ```python ``` ### JavaScript设计图标功能 >在script中调用函数 ```python ``` ### 前端向后端发送请求并接收数据 >利用ajax框架,定义ajax内部属性 >type(请求方式):“POST”; >url(请求地址):"http://127.0.0.1:5000/base_cal" >datatype(返回数据类型):json——json有两种形式,类似与python的字典和列表 >success: function()(请求成功并接收数据执行函数操作) >error: function()(请求失败并在控制台显示错误信息) >以Add()函数为例 ```python function Add(number){ $.ajax({ type: "POST", url: "http://127.0.0.1:5000/base_cal", dataType: "json", data:JSON.stringify({ "type":1, "data":number }), success: function(msg){ console.log(msg['result']); expression = msg['result']; display1.innerHTML = expression; },// 请求成功时执行的回调函数,msg是服务器返回的数据 error: function(xhr, textStatus, errorThrown) { // 请求失败时执行的回调函数,xhr 是 XMLHttpRequest 对象, textStatus 是错误状态文本,errorThrown 是抛出的错误信息 console.log("请求失败,错误信息:", textStatus, errorThrown);} }); } ``` ### 数据库创建 >这个计算器共有三个库:Cal_History库 、Deposit库、 loan库 >以db.Model为父类,创建类 > __tablename__设计数据库名称 > 利用db.Column()创建数据库每列的数据要求 ```python class Cal_History(db.Model): __tablename__="Cal_History" id = db.Column(db.Integer, primary_key=True, autoincrement=True) result = db.Column(db.String(100),nullable=False) class Deposit(db.Model): __tablename__="Deposit" deposit = db.Column(db.String(100), primary_key=True,nullable=False) deposit_duration= db.Column(db.Float,nullable=False) class loan(db.Model): __tablename__="Loan" loan = db.Column(db.String(100), primary_key=True,nullable=False) loan_duration= db.Column(db.Float,nullable=False) ``` ### python后端连接数据库 >数据库采用mysql类型 >app.config(数据库地址) >HOSTNAME(mysql所在主机名) >PORT(mysql监听的端口号,默认3306) >USERNAME(连接mysql的用户名) >PASSWORD(连接mysql的密码) >DATABASE(数据库名称) ```python HOSTNAME="127.0.0.1" PORT=3306 USERNAME="root" PASSWORD="123456" DATABASE="cal_history" app.config["SQLALCHEMY_DATABASE_URI"]=f"mysql+pymysql://{USERNAME}:{PASSWORD}@{HOSTNAME}:{PORT}/{DATABASE}?charset=utf8" ``` >测试是否连接成功——成功返回1 ```python db=SQLAlchemy(app) with app.app_context(): with db.engine.connect() as conn: rs = conn.execute(text("select 1")) print(rs.fetchone()) ``` ### python后端接收请求并向前端返回数据 >app = Flask(__name__):使用flask类创建一个app对象;__name__:代表当前app.py模板 >@app.route()创建一个路由和视图函数的映射 >def base_cal()函数接收前端json数据,并根据前端数据,分析所需功能,返回json数据 ```python app = Flask(__name__) cal = Calculator() @app.route('/base_cal',methods=["GET", "POST"]) def base_cal(): # put application's code here print(request.method) val = request.get_data() val = json.loads(val) res='' history=[] if val['type']==1: res=cal.Add(val['data']) data={ 'result':res } .... return data ``` >解决跨域问题 ```python from flask_cors import CORS CORS(app, resources=r'/*') ``` ### 后端增删改查数据库数据 >功能:增加——为cal_history数据库中增添数据 >通过db.session.add()函数为数据库添加数据 >db.session.commit()提交添加结果,真正完成添加 ```python res=cal.Result() cal_history = Cal_History(result=res) db.session.add(cal_history) db.session.commit() cal.result='=' + cal.result data={ 'equ':cal.screen_equ, 'result': cal.result } return data ``` >功能:查找——获取cal_history数据库中的全部数据并返回前端 >通过query.all()函数获取全部数据 ```python results = Cal_History.query.all() for result in results: history.append((result.result)) data = { 'result': history } print(data) return data ``` >查找存款三个月的存款利率 ```python d=Deposit.query.filter_by(deposit="三个月").first() rate=d.deposit_duration ``` >功能:修改——为deposit数据库数据 >修改功能基于查找功能,对查找到的数据进行修改 ```python d=Deposit.query.filter_by(deposit="三个月").first() d.loan_duration = lrate/100 db.session.commit() ``` ### 基础计算器功能实现 >创建Calculate类,包含Add()添加字符,Result()运算结果,Clear()清空屏幕,back()返回一个字符四个函数 #### Add() >equ变量为python中的运算式,screen_equ变量为屏幕显示的运算式 >例如:2的3次方 ——equ:2**3=8 ;screen_equ:2^3=8 ```python def Add(self, num): temp_equ = self.equ temp_screen_equ = self.screen_equ temp_screen_equ = temp_screen_equ + num if num == '×': temp_equ = temp_equ + '*' elif num == '÷': temp_equ = temp_equ + '/' elif num == '^': temp_equ = temp_equ + '**' elif num == 'lg': temp_equ = temp_equ + 'log10' elif num == 'ln': temp_equ = temp_equ + 'log' elif num == 'π': temp_equ = temp_equ + 'pi' else: temp_equ = temp_equ + num self.equ = temp_equ self.screen_equ = temp_screen_equ print(self.equ) return self.screen_equ ``` #### Result() 利用python自带的eval计算字符串 >通过try...except..,进行错误判断 >运行try,表示运算式正确,返回运算值 >except (ZeroDivisionError): 提示:'Error: 除零错误' >except NameError:提示'Error: 请加上括号' >except SyntaxError:s提示:'Error: 语法错误,请正确输入' ```python def Result(self): temp_equ = self.equ print(self.equ ) try: result = round(float(eval(temp_equ)), 2) self.result = str(result) self.screen_history.append(self.screen_equ + '=' + self.result) return self.screen_equ + '=' + self.result except ZeroDivisionError: # 其他除0错误,或语法错误返回Error self.result = str('Error: 除零错误') except NameError: self.result = str('Error: 请加上括号') except SyntaxError: self.result = str('Error: 语法错误,请正确输入') return self.result ``` #### back() >back()函数与Add()函数相对应 ```python def back(self): temp_equ = self.equ temp_screen_equ = self.screen_equ if temp_equ[-2:] in ['**', 'pi']: # ^ π self.equ = temp_equ[:-2] self.screen_equ = temp_screen_equ[:-1] elif temp_equ[-3:] in ['sin', 'cos', 'tan']: # sin cos tan self.equ = temp_equ[:-3] self.screen_equ = temp_screen_equ[:-3] elif temp_equ[-3:] == 'log': # ln self.equ = temp_equ[:-3] self.screen_equ = temp_screen_equ[:-2] elif temp_equ[-5:] == 'log10': # lg self.equ = temp_equ[:-5] self.screen_equ = temp_screen_equ[:-2] else: self.equ = temp_equ[:-1] self.screen_equ = temp_screen_equ[:-1] return self.screen_equ ``` ## 心得体会 >本次作业学习了解了python-flask框架、ajax框架等,明白了基础的前后端数据传递的方式,能简单实现前后端分离;同时对前端页面设计html、css、javaScript中的各类标签语法等有了更深的理解,能够更好的结合使用。 >同时,我也学习了python中一些基本数据类型如字典、列表的操作方法,学会了python类的写法;对json类型有了初步了解。