首页 前端知识 基于Html, Css与Java Sctipt, Python的前后端计算器(附源码链接)

基于Html, Css与Java Sctipt, Python的前后端计算器(附源码链接)

2024-03-20 11:03:43 前端知识 前端哥 913 891 我要收藏

I.  文章概览

在这篇博文中,我将详细介绍前端和后端交互式Web计算器的实现,并展示最终产品。

我制作的这个计算器可以实现加、减、乘、除、清零、幂函数、三角函数、指数函数、反三角函数和ans运算。

Link to the finished project code: Assignment2 codes in github 

II. 作者与作品的基本信息

Course for This Assignment2301-MUSE社区-CSDN社区云
Assignment RequirementsSecond assignment-- Back-end separation calculator programming-CSDN社区
The Aim of This AssignmentImprove the function of calculator and realize front-end interaction
MU STU ID and FZU21126259_832101125

目录

I.  文章概览

II. 作者与作品的基本信息

III. PSP表格

IV. 成品界面展示

①网页调试图

② 基础运算

③三角函数计算

④ 反三角函数计算

 ④ 对数函数计算

⑤ 历史记录存储

 V. 项目设计思路

①前端设计思路:

②后端设计思路:

 VII. 代码解释

①前端代码解释

a. Java Script

b. HTML

c. Css

 ②Back-end Programming Implementation (Python)

VII. 项目未来规划

VIII. 设计参考文献


III. PSP表格

PSP Table
PSPEstimated time (minutes)Actual time (minutes)
Planning
• Estimate:4040
Development
• Analysis3030
• Design Spec2020
• Design Review1010
• Coding Standard:2020
• Design3030
• Coding300500
• Code Review100100
• Test2030
Reporting
• Test Report:55
• Size Measurement1010
• Postmortem & Process Improvement Plan1010
TOTAL TIME595805

IV. 成品界面展示

①网页调试图

② 基础运算

③三角函数计算

sin(x):

cos(x):

tan(x):

④ 反三角函数计算

 asin(x):

acos(x):

atan(x):

 ④ 对数函数计算

⑤ 历史记录存储


 V. 项目设计思路

①前端设计思路:

a. HTML 结构:创建一个 HTML 文件来定义网页的结构。添加输入字段、按钮和其他元素,使用户能够输入数学表达式并进行计算。

b. CSS 样式:使用 CSS 美化网页,使其看起来吸引人并易于使用。

c. JavaScript 交互:使用 JavaScript 编写前端逻辑,实现以下功能:

     监听按钮点击事件以捕获用户输入。

     动态显示用户输入的数学表达式在输入框中。

     处理用户点击等号按钮时的表达式求值。

     在网页上显示计算结果。

d. 用户体验(UX):确保用户界面友好且易于使用。添加错误处理,如除零错误、反三角函数超过阈值错误等,以提高用户体验。

②后端设计思路:

a. Python 后端:使用 Python 编写后端代码,使用 PyCharm 进行开发。后端的主要作用是处理来自前端的请求,执行计算操作,并将结果返回给前端。

b. API 设计:设计两个 API,分别用于存储和读取。

c. 数据库连接:使用 PyMySQL 连接数据库并执行必要的数据库操作,以存储计算历史或其他数据。

d. 结果返回:将存储的表达式及其对应的计算结果以 JSON 格式发送回前端。务必处理任何潜在的错误或异常,以提供友好的错误消息。

e. 部署:将 Python 后端部署到本地服务器,确保它能够响应前端的请求。


 VII. 代码解释

①前端代码解释

a. Java Script

// 这个函数用于将输入添加到显示框中
function display(input) {
const str = document.getElementById("text");
str.value += input;
}
// 这个异步函数执行计算,处理数学表达式
async function equals() {
const str = document.getElementById("text");
let input = str.value;
let lastExpression = input;
// 如果输入包含 'Ans',尝试获取答案并替换 'Ans' 为答案的值
if (input.includes('Ans')) {
try {
const ansValue = await getAns();
input = input.replace(/Ans/g, ansValue);
} catch (error) {
console.error('获取答案出错: ' + error);
}
}
// 处理三角函数和反三角函数
if (input.includes('asin') || input.includes('acos')) {
const asinMatch = input.match(/asin\(([^)]+)\)/);
const acosMatch = input.match(/acos\(([^)]+)\)/);
if (asinMatch) {
const x = parseFloat(asinMatch[1]);
if (x < -1 || x > 1) {
str.value = "Error: Invalid input for asin(x). x must be in the range [-1, 1].";
return;
}
}
if (acosMatch) {
const x = parseFloat(acosMatch[1]);
if (x < -1 || x > 1) {
str.value = "Error: Invalid input for acos(x). x must be in the range [-1, 1].";
return;
}
}
}
// 替换 '^' 运算符为 '**'
if (input.includes('^')) {
input = input.replace(/\^/g, '**');
}
// 替换三角函数和反三角函数为 Math 对象的方法
if (input.includes('asin') || input.includes('acos') || input.includes('atan')) {
input = input.replace(/(\b(asin|acos|atan))\(/g, 'Math.$2(');
}
// 替换 sin, cos, tan 为 Math.sin, Math.cos, Math.tan
if (input.includes('sin') || input.includes('cos') || input.includes('tan')) {
input = input.replace(/(\b(sin|cos|tan))\(/g, 'Math.$2(');
}
// 替换 'e' 为 Math.E,'π' 为 Math.PI
if (input.includes('e')) {
input = input.replace(/e/g, 'Math.E');
}
if (input.includes('π')) {
input = input.replace(/π/g, 'Math.PI');
}
// 处理对数函数
if (input.includes('log')) {
input = input.replace(/log\(([^)]+)\)\(([^)]+)\)/g, 'Math.log($2) / Math.log($1)');
}
// 替换 'ln' 为 Math.log
if (input.includes('ln')) {
input = input.replace(/ln/g, 'Math.log');
}
// 替换 'Ans' 为上次计算的结果
if (input.includes('Ans')) {
let ansValue = getAns();
input = input.replace(/Ans/g, ansValue);
}
// 处理除以 0 的情况
if (input.includes('/0')) {
str.value = "Error: Division by zero is not allowed";
return;
}
try {
// 使用 eval 函数计算表达式
const result = eval(input);
str.value = result;
// 创建一个 XMLHttpRequest 对象并发送 POST 请求
const xhr = new XMLHttpRequest();
xhr.open('POST', 'http://localhost:5000/post', true);
xhr.setRequestHeader('Content-type', 'application/json');
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
const response = xhr.responseText;
console.log(response);
} else {
console.error('请求失败,状态码:' + xhr.status);
}
}
};
const data = {
expression: lastExpression,
result: result
};
xhr.send(JSON.stringify(data));
} catch (error) {
str.value = "Error";
}
}
// 删除最后一个字符
function back() {
const str = document.getElementById("text");
str.value = str.value.substring(0, str.value.length - 1);
}
// 重置显示框
function reset() {
const str = document.getElementById("text");
str.value = "";
}
// 将常数 Math.E 插入到显示框
function insertE() {
const str = document.getElementById("text");
str.value += Math.E;
}
// 在 getAns 函数中返回 Promise,用于获取答案
function getAns() {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open('GET', 'http://localhost:5000/get', true);
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
const Data = JSON.parse(xhr.responseText);
const array = Data["data"];
console.log(array);
resolve(array[0][1]);
} else {
console.error('获取数据出错: ' + xhr.status);
reject(xhr.status);
}
}
};
xhr.send();
});
}
// 获取历史记录
function getHistory() {
const xhr = new XMLHttpRequest();
xhr.open('GET', 'http://localhost:5000/get', true);
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
Data = JSON.parse(xhr.responseText);
array = Data["data"];
console.log(array);
let string = "";
for (let i = 0; i < array.length; i++) {
string += array[i][0] + " = " + array[i][1];
string += '\n';
}
} else {
console.error('获取数据出错: ' + xhr.status);
}
}
};
xhr.send();
}
复制

b. HTML

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Simple Calculator in Web</title>
<link href="css/PageSetting.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="js/CalculatorFunction.js"></script>
<!-- <script type="text/javascript" src="js/history.js"></script> -->
<!-- <script type="text/javascript" src="js/localServer.js"></script> -->
</head>
<body>
<div id="calculator">
<div id="head"><h3>Simple Calculator in Web</h3></div>
<div id="show" align="center"><input type="text" id="text" ></div>
<div id="cuttom">
<table align="center">
<tr>
<td><input type="button" value="e" onclick="display('e')"></td>
<td><input type="button" value="π" onclick="display('π')"></td>
<td><input type="button" value="(" onclick="display('(')"></td>
<td><input type="button" value=")" onclick="display(')')"></td>
<td><input type="button" value="^" onclick="display('^')"></td>
<td><input type="button" value="history" onclick="getHistory()"></td>
</tr>
<tr>
<td><input type="button" value="log" onclick="display('log(')"></td>
<td><input type="button" value="ln" onclick="display('ln(')"></td>
<td><input type="button" value="ans" onclick="display('Ans')"></td>
<td><input type="button" value="asin" onclick="display('asin(')"></td>
<td colspan="2"><input type="button" value="←" onclick="back()"></td>
</tr>
<tr>
<td><input type="button" value="." onclick="display('.')"></td>
<td><input type="button" value="0" onclick="display(0)"></td>
<td><input type="button" value="acos" onclick="display('acos(')"></td>
<td><input type="button" value="atan" onclick="display('atan(')"></td>
<td colspan="2"><input type="button" value="c" onclick="reset()"></td>
</tr>
<tr>
<td><input type="button" value="7" onclick="display(7)"></td>
<td><input type="button" value="8" onclick="display(8)"></td>
<td><input type="button" value="9" onclick="display(9)"></td>
<td><input type="button" value="+" onclick="display('+')"></td>
<td><input type="button" value="-" onclick="display('-')"></td>
<td><input type="button" value="tan" onclick="display('tan(')"></td>
</tr>
<tr>
<td><input type="button" value="4" onclick="display(4)"></td>
<td><input type="button" value="5" onclick="display(5)"></td>
<td><input type="button" value="6" onclick="display(6)"></td>
<td><input type="button" value="*" onclick="display('*')"></td>
<td><input type="button" value="/" onclick="display('/')"></td>
<td><input type="button" value="sin" onclick="display('sin(')"></td>
</tr>
<tr>
<td><input type="button" value="1" onclick="display(1)"></td>
<td><input type="button" value="2" onclick="display(2)"></td>
<td><input type="button" value="3" onclick="display(3)"></td>
<td colspan="2"><input type="button" value="=" onclick="equals()"></td>
<td><input type="button" value="cos" onclick="display('cos(')"></td>
</tr>
</table>
</div>
</div>
</body>
</html>
复制

c. Css

body {
background: #f0f0f0;
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
}
#calculator {
width: 600px;
margin: 50px auto;
border: 1px solid #ccc;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
background-color: #fff;
border-radius: 10px; /* 添加圆角 */
padding: 20px; /* 增加内边距 */
}
#head {
background-color: #333;
color: #fff;
text-align: center;
padding: 10px 0;
border-radius: 10px; /* 添加圆角 */
}
#head h3 {
margin: 0;
font-size: 24px;
}
#show input {
width: 100%;
height: 60px;
font-size: 30px;
text-align: right;
border: 2px solid black;
padding: 10px;
outline: none;
box-sizing: border-box;
border-radius: 10px; /* 添加圆角边框 */
}
#custom {
padding: 20px;
}
table {
width: 100%;
table-layout: fixed;
margin-top: 15px; /* 上方间隔 */
margin-bottom: 15px; /* 下方间隔 */
}
table td {
width: 25%;
margin: 10px; /* 左右间隔 */
}
table input {
width: 100%;
height: 50px;
font-size: 20px;
text-align: center;
border: none;
outline: none;
cursor: pointer;
background: #f0f0f0;
border-radius: 10px;
box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.2); /* 添加阴影效果 */
transition: transform 0.2s, box-shadow 0.2s; /* 添加过渡效果 */
}
/* 鼠标悬停时应用立体效果和放大效果 */
table input:hover {
background: #ccc;
transform: scale(1.1); /* 放大效果 */
box-shadow: 5px 5px 10px rgba(0, 0, 0, 0.2), 0 0 0 2px #000; /* 增加阴影深度和黑色边框 */
}
复制

 ②Back-end Programming Implementation (Python)

/post API

  • 用于存储操作表达式和值。 客户端可以向该接口发送一个 POST 请求,传递一个包含表达式和计算结果的 JSON 数据。
  • 该接口将接收到的数据插入数据库,并确保保留最新的 10 条记录,删除多余的记录。
  • 返回一个 JSON 响应,包括消息 "ok" 表示操作成功,或错误消息和状态码 500 表示操作失败。
@app.route('/post', methods=['POST'])
def post_history(): # 存储运算表达式和值
try:
data = request.get_json() # 获取POST请求的JSON数据
expression = data.get('expression')
result = data.get('result')
time = datetime.datetime.now()
# 插入新数据
data = (time, expression, result)
insert = "INSERT INTO history (time, expression, result) VALUES (%s, %s, %s)"
cursor.execute(insert, data)
# 获取当前记录数量
cursor.execute("SELECT COUNT(*) FROM history")
record_count = cursor.fetchone()[0]
# 如果记录数量超过十条,删除最旧的记录
if record_count > 10:
delete_old_records = "DELETE FROM history ORDER BY time LIMIT %s"
cursor.execute(delete_old_records, (record_count - 10,))
conn.commit()
response_message = "ok"
return jsonify({"message": response_message})
except Exception as e:
error_message = str(e)
return jsonify({"error": error_message}), 500
#用于存储运算表达式和值。
#客户端可以向此接口发送 POST 请求,传递一个 JSON 数据包括表达式和计算结果。
#该接口会将接收到的数据插入数据库中,并确保保留最新的 10 条记录,删除多余的记录。
#返回一个 JSON 响应,包括消息 "ok" 表示操作成功,或者包括错误消息和状态码 500 表示操作失败。
复制

/get API

  • 用于获取历史操作表达式和结果。 客户端可以向该接口发送一个 GET 请求,以获取最新的 10 条历史记录。
  • 该接口在数据库中查询历史记录,并返回一个包含表达式和结果数据的 JSON 响应。
  • 如果查询失败,将返回一个错误消息和状态码 500。
@app.route('/get', methods=['GET'])
def get_calculation_data(): # 得到历史值
try:
cursor.execute("SELECT expression, result FROM history ORDER BY time DESC LIMIT 10")
data = cursor.fetchall()
return jsonify({"data": data})
except Exception as e:
error_message = str(e)
return jsonify({"error": error_message}), 500
#用于获取历史运算表达式和结果。
#客户端可以向此接口发送 GET 请求,以获取最新的 10 条历史记录。
#该接口会查询数据库中的历史记录,并返回一个 JSON 响应,其中包括表达式和结果的数据。
#如果查询失败,将返回错误消息和状态码 500。
复制

VII. 项目未来规划

通过设置新的交互栏和新的计算逻辑对用户进行分类,使特定用户可以直接使用与预期用途相关的计算键,如税收计算、游戏装备损坏计算等功能。


VIII. 设计参考文献

  • 【精选】2023 年 MySQL 8.0 安装配置 最简易(保姆级)_mysql8.0安装配置教程_mobeicanyue的博客-CSDN博客
  • web 技术中的前端和后端是如何交互的 - 知乎 (zhihu.com)
  • MySQL 管理 | 菜鸟教程 (runoob.com)
转载请注明出处或者链接地址:https://www.qianduange.cn//article/3968.html
标签
评论
还可以输入200
共0条数据,当前/页
发布的文章

JQuery操作DOM

2024-04-13 23:04:28

jQuery库

2024-04-13 23:04:28

【无标题】

2024-04-13 23:04:51

大家推荐的文章
会员中心 联系我 留言建议 回顶部
复制成功!