
前后端分离计算器系统作业课程软件工程作业要求实现前后端分离计算器后端完成表达式计算持久化保存历史记录支持删除指定历史记录禁止直接使用eval采用安全表达式求值库代码分两个独立GitHub仓库每个仓库附带README与codestyle代码规范文档。目录前后端分离计算器系统作业Git仓库链接和代码规范链接PSP表格成品展示设计与实现过程需求分析整体系统架构前端设计后端设计接口设计关键代码解释后端核心计算接口代码片段前端JS代码片段一些开发经历开发遇到的一些问题学到的一些知识点Git仓库链接和代码规范链接后端仓库https://github.com/haoxihuanvvjiea/832401307_calculator_backend后端代码规范文档https://github.com/haoxihuanvvjiea/832401307_calculator_backend/blob/main/codestyle.md前端仓库https://github.com/haoxihuanvvjiea/832401307_calculator_frontend前端代码规范文档https://github.com/haoxihuanvvjiea/832401307_calculator_frontend/blob/main/codestyle.mdPSP表格PSP阶段预估耗时/min实际耗时/min需求分析6070系统架构设计8085后端代码开发110120表达式计算模块开发7085数据库设计与调试4045前端页面开发9095前端UI美化优化6065前后端接口联调8085功能测试与Bug修复6065GitHub仓库搭建与规范整理4045CSDN博客撰写7060最终自查整改6060总计820880成品展示后端GitHub仓库主页前端GitHub仓库主页计算器主界面基础加法运算示例12括号复合运算(12)*3负数运算-58除零异常弹窗提示非法表达式异常弹窗历史记录列表展示删除历史记录后的页面效果FastAPI自动生成接口文档页面/docs终端启动后端服务截图设计与实现过程需求分析本项目实现前后端分离架构前端只负责UI渲染、按钮交互所有表达式计算逻辑必须放在后端执行。使用SQLite数据库持久存储每一条计算记录支持查询全部历史记录、可删除单条历史。出于安全考虑不能使用Python内置eval函数执行用户输入表达式选用simpleeval安全库进行数学表达式求值。整体系统架构项目采用前后端分离架构前端页面使用 HTMLCSS 原生 JavaScript 写界面通过 HTTP 请求和后端交换 JSON 数据后端用 FastAPI 搭建接口搭配 SQLite 数据库保存计算历史。工作流程点击计算器按钮前端拼接表达式字符串按下等号前端把表达式发给后端接口后端接收表达式使用 simpleeval 库计算捕获各类计算错误计算正常就把这条记录存入数据库并把结果返回前端前端收到结果后展示同时刷新历史列表点击删除按钮前端发送删除请求后端根据 id 删除对应记录。前端设计前端主要负责计算器界面和用户交互。用 CSS Grid 排版按钮增加简单点击效果。JavaScript 使用 fetch 异步请求后端接口拿到返回的数据渲染页面。如果后端返回错误就弹出提示框告诉用户。前端不做任何数学运算只负责把表达式传给后端满足前后端分离的要求。历史记录列表向用户展示表达式与运算结果数据库记录 id 为内部主键不会展示在 UI 界面仅作为参数传递给删除接口用来通知后端定位需要删除的记录。后端设计基于Python FastAPI框架搭建API服务一共提供3个接口POST/api/calc接收表达式执行计算写入数据库返回success标记、表达式与结果GET/api/history查询数据库全部历史记录按id倒序返回DELETE/api/history/{item_id}根据id删除单条历史记录。历史记录区域展示表达式与计算结果记录 ID 作为数据库主键仅用于后端删除接口不在前端 UI 展示数据库采用轻量级SQLite程序启动自动创建数据表history。数据表字段字段名类型说明idINTEGER自增主键expressionTEXT用户输入表达式resultTEXT运算结果create_timeREALUnix时间戳记录计算时间表达式求值模块使用simpleeval库该库仅支持数学运算禁止执行任意Python代码规避原生eval带来的代码注入安全风险。遇到语法错误、除零错误等情况返回HTTP 400错误前端捕获并弹窗提示。接口设计请求方式接口地址作用返回示例POST/api/calc表达式计算并入库{success:true,expression:(12)*3,result:9}GET/api/history获取全部历史{success:true,data:[{id:1,expression:12,result:3,create_time:1759345678.123}]}DELETE/api/history/{id}删除一条记录{success:true,msg:已删除}关键代码解释后端核心计算接口代码片段app.post(/api/calc)asyncdefcalc(req:CalcRequest):try:ressimpleeval.simple_eval(req.expression)exceptExceptionase:raiseHTTPException(status_code400,detailf表达式错误:{str(e)})connsqlite3.connect(calc.db)curconn.cursor()cur.execute(INSERT INTO history(expression, result, create_time) VALUES (?, ?, ?),(req.expression,str(res),time.time()))conn.commit()conn.close()return{success:True,expression:req.expression,result:res}代码说明接收前端传过来的表达式调用 simpleeval 计算。如果表达式写错、除零就弹出错误。计算成功后把表达式和结果存入数据库关闭数据库连接把结果返回前端。前端JS代码片段asyncfunctionloadHistory(){constresawaitfetch(/api/history);constretawaitres.json();constlistret.data;historyList.innerHTML;list.forEach(item{constdivdocument.createElement(div);div.classNameitem;div.innerHTMLspan${item.expression}${item.result}/span span classdel-btn onclickdelItem(${item.id})删除/span;historyList.appendChild(div);})}代码说明向后端请求所有历史记录拿到数据后循环生成每一条历史记录同时绑定删除按钮。一些开发经历开发遇到的一些问题前后端对接的时候 JSON 字段名对不上前端拿不到后端返回的数据反复调试统一字段名。旧的历史数据库文件表结构不对启动报错删除 calc.db 文件重新运行程序自动新建数据表。忘记每次用完数据库关闭连接多次操作后偶尔出现数据库锁报错修复后每次读写都关闭连接。学到的一些知识点理解前后端分离页面展示和计算逻辑分开前端只管界面交互计算交给后端处理。不能直接把用户输入的字符串交给 eval 执行会有代码注入风险。学习接口基础用不同请求方法实现增删查改使用 JSON 传递数据。SQLite 简单使用。学会使用 GitHub 存储和管理项目代码。