Back-end separation calculator

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


Introduction

This blog is written to show the process of how to make a calculator based on JavaScript and CSS and HTML.


Information table

The Link Your Classhttps://bbs.csdn.net/forums/ssynkqtd-04
Link of Requirement of This Assignmenthttps://bbs.csdn.net/topics/617378696
Aim of This Assignmentcalculator with a visual interface
MU STU ID and FZU STU ID21124663_832101103

Link to the finished project code:
front:
https://github.com/Iwtbs27/EE308-Assigment2-frontend/tree/main
backend:
https://github.com/Iwtbs27/EE308-Assigment2-backend/tree/main

PSP form

Personal Software Process StagesEstimated Time(minutes)Actual Time(minutes)
Planning3030
• Estimate3030
Development3030
• Analysis3030
• Design Spec3030
• Design Review3050
• Coding Standard3030
• Design3030
• Coding3040
• Code Review3030
• Test3030
Reporting3050
• Test Repor3030
• Size Measurement3030
• Postmortem & Process Improvement Plan3030
Sum450500

Basic calculator functions

Function 1: addition, subtraction, multiplication, division, remainder

请添加图片描述

Function 2: Read history

请添加图片描述


Extended function: Scientific calculator

Calculate radical sign, trigonometric function, log, scientific notation

请添加图片描述

Implement bracket computation

请添加图片描述

Better looking UI interface

请添加图片描述


Coding

HTML

The HTML document is responsible for creating the user interface of the electronic calculator. It defines the layout, buttons, display screen, theme toggle button, and other elements of the calculator, allowing users to interact with the calculator through a web browser.

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8"> <!-- 设置字符编码 -->
    <meta http-equiv="X-UA-Compatible" content="IE=edge"> <!-- 指定IE浏览器使用最新的渲染引擎 -->
    <meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- 定义视口宽度和初始缩放比例 -->
    <title>Huihuang's Calculator</title> <!-- 设置网页标题 -->
    <link rel="stylesheet" href="./style.css"> <!-- 引入样式表 -->
</head>
<body>
    <div class="container">
        <div class="calculator dark"> <!-- 创建计算器容器,使用暗色主题 -->
            <div class="theme-toggler active"> <!-- 切换主题按钮,初始化为激活状态 -->
                <i class="toggler-icon"></i> <!-- 切换按钮图标 -->
            </div>
            <div class="display-screen"> <!-- 显示屏容器 -->
                <div id="display"></div> <!-- 显示屏元素 -->
            </div>
            <div class="hisplay"> <!-- 历史显示框容器 -->
                <div id="hisplay"></div> <!-- 历史显示框元素 -->
            </div>
            <div class="buttons"> <!-- 按钮容器 -->
                <table>
                    <tr>
                        <td><button class="btn-operator" id="clear">C</button></td> <!-- 清除按钮 -->
                        <td><button class="btn-operator" id="/">&divide;</button></td> <!-- 除法按钮 -->
                        <td><button class="btn-operator" id="*">&times;</button></td> <!-- 乘法按钮 -->
                        <td><button class="btn-operator" id="sin">sin</button></td> <!-- 正弦按钮 -->
                        <td><button class="btn-operator" id="backspace"><</button></td> <!-- 退格按钮 -->
                    </tr>
                    <tr>
                        <td><button class="btn-number" id="7">7</button></td> <!-- 数字按钮 7 -->
                        <td><button class="btn-number" id="8">8</button></td> <!-- 数字按钮 8 -->
                        <td><button class="btn-number" id="9">9</button></td> <!-- 数字按钮 9 -->
                        <td><button class="btn-operator" id="cos">cos</button></td> <!-- 余弦按钮 -->
                        <td><button class="btn-operator" id="-">-</button></td> <!-- 减法按钮 -->
                    </tr>
                    <tr>
                        <td><button class="btn-number" id="4">4</button></td> <!-- 数字按钮 4 -->
                        <td><button class="btn-number" id="5">5</button></td> <!-- 数字按钮 5 -->
                        <td><button class="btn-number" id="6">6</button></td> <!-- 数字按钮 6 -->
                        <td><button class="btn-operator" id="tan">tan</button></td> <!-- 正切按钮 -->
                        <td><button class="btn-operator" id="+">+</button></td> <!-- 加法按钮 -->
                    </tr>
                    <tr>
                        <td><button class="btn-number" id="1">1</button></td> <!-- 数字按钮 1 -->
                        <td><button class="btn-number" id="2">2</button></td> <!-- 数字按钮 2 -->
                        <td><button class="btn-number" id="3">3</button></td> <!-- 数字按钮 3 -->
                        <td><button class="btn-operator" id="^">^</button></td> <!-- 指数按钮 -->
                        <td rowspan="2"><button class="btn-equal" id="equal">=</button></td> <!-- 等于按钮 -->
                    </tr>
                    <tr>
                        <td><button class="btn-operator" id="(">(</button></td> <!-- 左括号按钮 -->
                        <td><button class="btn-number" id="0">0</button></td> <!-- 数字按钮 0 -->
                        <td><button class="btn-operator" id=")">)</button></td> <!-- 右括号按钮 -->
                        <td><button class="btn-operator" id="ln">ln</button></td> <!-- 指数按钮 -->
                    </tr>
                    <tr>
                        <td><button class="btn-operator" id="History">Ans</button></td> <!-- 历史记录按钮 -->
                        <td><button class="btn-operator" id="%">%</button></td> <!-- 百分比按钮 -->
                    </tr>
                </table>
            </div>
        </div>
    </div>
    <script src="./script.js"></script> <!-- 引入JavaScript文件 -->
</body>
</html>

</html>

CSS

The CSS stylesheet defines the appearance and style of the calculator, including the look, colors, sizes, fonts, and more of the buttons. It ensures that the calculator maintains a consistent appearance across various screen sizes and devices, providing visual aesthetics and user-friendliness.

/* 通用样式重置 */
* {
    margin: 0; /* 重置外边距 */
    padding: 0; /* 重置内边距 */
    box-sizing: border-box; /* 设置盒模型为边框盒 */
    outline: 0; /* 去除外边框 */
    transition: all 0.5s ease; /* 添加过渡效果,用于所有属性变化 */
}

/* 设置全局字体样式 */
body {
    font-family: sans-serif; /* 设置全局字体样式为无衬线字体 */
}

/* 设置全局链接样式 */
a {
    text-decoration: none; /* 去除链接下划线 */
    color: #fff; /* 设置链接颜色为白色 */
}

/* 设置全局背景图像,创建渐变背景 */
body {
    background-image: linear-gradient(to bottom right, rgba(79, 51, 176, 1), rgb(228, 59, 181));
    /* 创建渐变背景色,从紫色到粉红色 */
}

/* 定义包含计算器的容器,居中显示 */
.container {
    height: 100vh; /* 高度占据整个视口高度 */
    width: 100vw; /* 宽度占据整个视口宽度 */
    display: grid; /* 使用网格布局 */
    place-items: center; /* 将内容垂直水平居中显示 */
}

/* 计算器样式 */
.calculator {
    position: relative; /* 设置相对定位,用于定位内部元素 */
    height: auto; /* 自适应高度 */
    width: auto; /* 自适应宽度 */
    padding: 20px; /* 内边距 */
    border-radius: 10px; /* 设置边框圆角 */
    box-shadow: 0 0 30px #000; /* 添加阴影效果 */
}

/* 主题切换按钮样式 */
.theme-toggler {
    position: absolute; /* 设置绝对定位,相对于父容器定位 */
    top: 30px; /* 距离顶部30px */
    right: 30px; /* 距离右侧30px */
    color: #fff; /* 文字颜色为白色 */
    cursor: pointer; /* 鼠标指针样式为手型 */
    z-index: 1; /* 设置层级为1,放在上面 */
}

/* 主题切换按钮激活状态样式 */
.theme-toggler.active {
    color: #333; /* 文字颜色为深灰色 */
}

/* 主题切换按钮伪元素样式 */
.theme-toggler.active::before {
    background-color: #fff; /* 伪元素背景颜色为白色 */
}

.theme-toggler::before {
    content: ''; /* 伪元素内容为空 */
    height: 30px; /* 伪元素高度为30px */
    width: 30px; /* 伪元素宽度为30px */
    position: absolute; /* 设置伪元素绝对定位 */
    top: 50%; /* 距离顶部50% */
    transform: translate(-50%, -50%); /* 平移至水平垂直居中 */
    border-radius: 50%; /* 设置伪元素圆角 */
    background-color: #333; /* 伪元素背景颜色为深灰色 */
    z-index: -1; /* 设置层级为-1,位于按钮后面 */
}

/* 显示屏样式 */
#display {
    margin: 0 10px; /* 外边距,水平方向为0,垂直方向为10px */
    height: 150px; /* 高度为150px */
    width: auto; /* 自适应宽度 */
    max-width: 270px; /* 最大宽度为270px */
    display: flex; /* 使用弹性布局 */
    align-items: flex-end; /* 垂直底部对齐 */
    justify-content: flex-end; /* 水平右对齐 */
    font-size: 30px; /* 文字字号为30px */
    overflow-x: scroll; /* 如果内容溢出则显示水平滚动条 */
}

/* 滚动条样式 */
#display::-webkit-scrollbar {
    display: block; /* 显示滚动条 */
    height: 3px; /* 滚动条高度为3px */
}

/* 按钮样式 */
button {
    height: 60px; /* 按钮高度为60px */
    width: 60px; /* 按钮宽度为60px */
    border: 0; /* 去除边框 */
    border-radius: 30px; /* 设置按钮圆角为30px */
    margin: 5px; /* 外边距为5px */
    font-size: 20px; /* 文字字号为20px */
    cursor: pointer; /* 鼠标指针样式为手型 */
    transition: all 200ms ease; /* 添加所有属性变化过渡效果,持续200毫秒 */
}

/* 鼠标悬停按钮放大效果 */
button:hover {
    transform: scale(1.1); /* 鼠标悬停时放大1.1倍 */
}

/* 等号按钮样式 */
button#equal {
    height: 130px; /* 等号按钮高度为130px */
}

/* 白天主题样式 */
.calculator {
    background-color: #fff; /* 背景颜色为白色 */
}

.calculator #display {
    color: #0a1e23; /* 显示屏文字颜色为深灰色 */
}

.calculator button#clear {
    background-color: #ffd5d8; /* 清除按钮背景颜色为淡红色 */
    color: #fc4552; /* 清除按钮文字颜色为深红色 */
}

.calculator button.btn-number {
    background-color: #c3eaff; /* 数字按钮背景颜色为浅蓝色 */
    color: #000; /* 数字按钮文字颜色为黑色 */
}

.calculator button.btn-operator {
    background-color: #ffd0fd; /* 运算符按钮背景颜色为浅粉色 */
    color: #f967f3; /* 运算符按钮文字颜色为粉红色 */
}

.calculator button.btn-equal {
    background-color: #adf9e7; /* 等号按钮背景颜色为淡绿色 */
    color: #000; /* 等号按钮文字颜色为黑色 */
}

/* 夜间主题样式 */
.calculator.dark {
    background-color: #071115; /* 背景颜色为深蓝色 */
}

.calculator.dark #display {
    color: #f8fafd; /* 显示屏文字颜色为白色 */
}

.calculator.dark button#clear {
    background-color: #2d191e; /* 清除按钮背景颜色为深红色 */
    color: #bd3740; /* 清除按钮文字颜色为深红色 */
}

.calculator.dark button.btn-number {
    background-color: #1b2f38; /* 数字按钮背景颜色为深蓝色 */
    color: #f8fafb; /* 数字按钮文字颜色为白色 */
}

.calculator.dark button.btn-operator {
    background-color: #2e1f39; /* 运算符按钮背景颜色为深紫色 */
    color: #aa00a4; /* 运算符按钮文字颜色为紫色 */
}

.calculator.dark button.btn-equal {
    background-color: #223323; /* 等号按钮背景颜色为深绿色 */
    color: #fff; /* 等号按钮文字颜色为白色 */
}

/* 历史显示框样式 */
#hisplay {
    background-color: #8e58d9; /* 历史显示框背景颜色为紫色 */
    border: 2px solid #dac5c5; /* 设置2px的边框,颜色为灰色 */
    margin: 20px; /* 外边距为20px */
    padding: 30px; /* 内边距为30px */
    z-index: 2; /* 增加z-index属性,设置层级为2 */
}

JavaScript

The JavaScript script adds interactivity and functionality to the calculator. It initializes the buttons and display screen elements, listens for user click events, and performs mathematical calculations and special functions based on user input. JavaScript also handles error cases, such as division by zero or expression format errors, as well as clearing and deleting operations. Additionally, it allows users to toggle the calculator’s theme, changing its appearance.

Process
在这里插入图片描述

// 获取显示屏和所有按钮元素
const display = document.querySelector('#display');
const buttons = document.querySelectorAll('button');

// 遍历每个按钮
buttons.forEach((item) => {
    item.onclick = () => {
        if (item.id == 'clear') {
            display.innerText = ''; // 清空显示屏
        } else if (item.id == 'backspace') {
            let string = display.innerText.toString();
            display.innerText = string.substr(0, string.length - 1); // 删除最后一个字符
        } else if (item.id == 'equal') {
            // 获取显示屏内容并处理数学表达式
            let expression = display.innerText;
            exp = expression
                .replace(/sin\(([^)]+)\)/g, (match, angle) => {
                    return `Math.sin(${angle * Math.PI / 180})`; // 替换sin函数
                })
                .replace(/cos\(([^)]+)\)/g, (match, angle) => {
                    return `Math.cos(${angle * Math.PI / 180})`; // 替换cos函数
                })
                .replace(/tan\(([^)]+)\)/g, (match, angle) => {
                    return `Math.tan(${angle * Math.PI / 180})`; // 替换tan函数
                })
                .replace(/lg/g, 'Math.log10') // 替换lg为Math.log10
                .replace(/ln/g, 'Math.log') // 替换ln为Math.log
                .replace(/sqrt/g, 'Math.sqrt') // 替换sqrt为Math.sqrt
                .replace(/\^/g, '**') // 替换^为**
                .replace(/e/g, 'Math.E') // 替换e为Math.E
                .replace(/pi/g, 'Math.PI') // 替换pi为Math.PI
                .replace(/abs/g, 'Math.abs'); // 替换abs为Math.abs

            // 处理包含特殊函数的表达式
            try {
                // 计算表达式结果
                let result = eval(exp).toFixed(3);

                // 创建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);
                        }
                    }
                };

                // 构建POST数据
                const data = {
                    expression: expression,
                    result: result
                };
                xhr.send(JSON.stringify(data));
                display.innerText = result; // 在显示屏上显示结果
            } catch (error) {
                display.innerText = `Error: ${error.message}`; // 处理错误情况
            }
        } else if (item.id == 'exp') {
            display.innerText += '^'; // 添加指数运算符
        } else if (item.id == 'sin') {
            display.innerText += 'sin('; // 添加sin函数
        } else if (item.id == 'cos') {
            display.innerText += 'cos('; // 添加cos函数
        } else if (item.id == 'tan') {
            display.innerText += 'tan('; // 添加tan函数
        } else if (item.id == 'History') {
            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);
                        hisplay.innerText = ""; // 清空历史显示框
                        for (i = 0; i < array.length; i++) {
                            hisplay.innerText += array[i] + '\n'; // 在历史显示框中显示历史记录
                        }
                    } else {
                        console.error('获取数据出错: ' + xhr.status); // 请求错误处理
                    }
                }
            };
            xhr.send();
        } else {
            display.innerText += item.id; // 添加按钮文本到显示屏
        }
    }
});

// 获取主题切换按钮及相关元素
const themeToggleBtn = document.querySelector('.theme-toggler');
const calculator = document.querySelector('.calculator');
const toggleIcon = document.querySelector('.toggler-icon');
let isDark = true;

// 监听主题切换按钮点击事件
themeToggleBtn.onclick = () => {
    calculator.classList.toggle('dark'); // 切换暗色主题
    themeToggleBtn.classList.toggle('active'); // 切换按钮样式
    isDark = !isDark; // 切换主题标志
}


Backend

History Data

在这里插入图片描述

Import the necessary libraries:

  • ‘Flask’: A micro-framework for creating web applications.
  • ‘request’: Used for handling HTTP requests in Flask.
  • ‘jsonify’: Used for returning JSON responses in Flask.
  • ‘flask_cors’: A Flask plugin for handling cross-origin requests.

Code

# 导入所需的Flask库
from flask import Flask, request, jsonify
from flask_cors import CORS
import pymysql
import datetime

# 创建一个Flask应用实例
app = Flask(__name)

# 允许跨域请求
CORS(app)

# 连接到MySQL数据库,请替换以下信息为实际数据库连接信息
db = pymysql.connect(
    host="your_host",       # 数据库主机地址
    user="your_user",       # 数据库用户名
    password="your_password",  # 数据库密码
    database="your_database"  # 数据库名称
)

# 定义处理POST请求的路由
@app.route('/post', methods=['POST'])
def hello_world():
    try:
        data = request.get_json()
        expression = data.get('expression')
        result = data.get('result')
        print(str(expression) + "=" + str(result))

        # 创建数据库游标
        cursor = db.cursor()

        # 执行插入数据的SQL语句
        sql = "INSERT INTO calculations (expression, result) VALUES (%s, %s)"
        values = (expression, result)
        cursor.execute(sql, values)

        # 提交更改到数据库
        db.commit()

        # 关闭游标
        cursor.close()
    except Exception as e:
        print("Error:", e)
    return 'Hello, World!'

# 定义处理GET请求的路由
@app.route('/get', methods=['GET'])
def get_calculation_data():
    try:
        # 创建数据库游标
        cursor = db.cursor()

        # 执行查询SQL语句,获取最近10个历史记录
        sql = "SELECT expression, result FROM calculations ORDER BY id DESC LIMIT 10"
        cursor.execute(sql)
        data = cursor.fetchall()

        # 关闭游标
        cursor.close()

        # 将查询结果转换为JSON格式并返回
        history_data = [{"expression": item[0], "result": item[1]} for item in data]
        return jsonify({"data": history_data})
    except Exception as e:
        print("Error:", e)

# 启动Flask应用
if __name__ == '__main__':
    app.run(host='localhost', port=5000)


Project Summary: Building a Calculator and History Recorder with Flask and MySQL

This project involves the development of a web application using Flask and MySQL to create a simple calculator and a history recorder. The application is designed to allow users to perform mathematical calculations and maintain a record of their computation history. Here are the main components and functions of the project:

Front-end

The front-end of the project is constructed using HTML, CSS, and JavaScript. It creates a user interface that enables users to input mathematical expressions and execute calculations.

  • HTML File: The HTML file defines the structure and content of the web page. It includes a calculator interface with areas for displaying user input and results, along with various buttons for mathematical operations.

  • CSS File: The CSS file defines the styling and appearance of the web page. This includes both a light and dark theme, button styles, and the styling for the history records.

  • JavaScript File: The JavaScript file contains the code responsible for handling user interactions, performing actual calculations, and making AJAX requests to send calculation results to the back-end server and retrieve the calculation history.

Back-end

The back-end employs the Flask framework to create a basic web server. It receives calculation requests from the front-end, computes the results, stores the results in a MySQL database, and provides the front-end with access to the history records.

  • Flask Framework: Flask is a lightweight Python web framework used for handling HTTP requests and constructing web applications.

  • MySQL Database: MySQL is a relational database management system used for storing the history of calculations.

  • CORS: Flask-CORS is a Flask extension utilized to manage Cross-Origin Resource Sharing, enabling communication between the front-end application and the back-end server.

The primary workflow of the project is as follows:

  1. Users input a mathematical expression in the front-end and click the “=” button.
  2. The JavaScript code in the front-end processes the expression, sends a calculation request to the back-end, and performs the calculation.
  3. The back-end receives the calculation request, computes the result, and stores the expression and result in a MySQL database.
  4. The back-end uses a GET request to retrieve the most recent ten calculation records and sends them to the front-end to be displayed on the history screen.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值