2026秋软工实践编程作业 个人记账本
| 作业所属课程 | 202601软件工程 - 福州大学 |
|---|---|
| 作业要求 | 2026秋软件工程现场编程作业 |
| 作业的目标 | 在3小时内以团队协作方式完成一个个人记账本Web应用,实践GitHub多人协作、模块化开发。 |
| 团队名称 | 迟到组 |
| 团队成员名字-学号 | 张志强-102101627、刘弘毅-102401423、华恺-102101215、叶佳旺-102201103、hyw-1526704790、lhAsh-839912338、丿-3174686731 |
1. 组员职责分工
| 成员 | 负责模块 | 实现的内容 |
|---|---|---|
| 张志强-102101627 | stats.py |
收支金额汇总、分类统计以及余额计算功能。 |
| 刘弘毅-102401423 | server.py |
后端路由分配、API接口编写、异常错误捕获以及并发锁控制。 |
| 华恺-102101215 | storage.py |
基于本地 JSON 的数据持久化,采用原子替换机制防止数据损坏。 |
| 叶佳旺-102201103 | static/ |
前端页面布局、交互逻辑及分类图表展示。 |
| hyw-1526704790 | ai_analysis.py 及脚本 |
对接 DeepSeek API 实现智能分析;并完成了 launch.py 启动器及跨平台启动脚本配置。 |
| 丿-3174686731 | records.py |
收支记录的严格校验及多条件的高级筛选功能。 |
2. 程序运行环境
- 操作系统:Windows 10/11 或 macOS
- 开发语言:Python 3.9 或以上版本(无需第三方依赖包),前端使用原生 HTML/CSS/JavaScript。
- 运行方式:在 Windows 下双击
启动记账本.bat,或在 macOS 终端运行python3 launch.py。服务会自动在本地8877端口启动并使用浏览器打开页面。
3. 软件运行截图和视频
4. 关键代码
(1)storage.py - 数据原子替换持久化
在存储模块中使用了临时文件配合 os.replace,实现原子写入,防止程序崩溃导致原本的 JSON 文件损坏。
def write(records):
PATH.parent.mkdir(exist_ok=True)
fd, name = tempfile.mkstemp(dir=PATH.parent)
try:
with os.fdopen(fd, 'w', encoding='utf-8') as f:
json.dump(records, f, ensure_ascii=False, indent=2)
# 采用临时文件+原子替换,避免写入中断损坏原文件
os.replace(name, PATH)
(2)records.py - 金额精度校验与类型转换
为了保证金额计算的精度,在记录校验时,强制将用户输入的金额转换为整数分(cents)进行存储。
def validate(data):
try:
amount = Decimal(str(data['amount']))
if not amount.is_finite() or amount <= 0 or amount > 999999999 or amount.as_tuple().exponent < -2:
raise ValueError('金额须大于零,最多两位小数')
except InvalidOperation:
raise ValueError('金额格式错误')
# 转换为整数分存储,避免浮点误差
return dict(id=str(uuid.uuid4()), date=data['date'], type=data['type'], category=data['category'], cents=int(amount*100), note=note)
(3)server.py - 并发请求控制
在处理多端同时提交记账数据时,使用全局锁(Lock)防止文件读写冲突。
LOCK = threading.Lock()
# ...
def do_POST(self):
try:
data = json.loads(self.rfile.read(int(self.headers.get('Content-Length', 0))))
row = records.validate(data)
with LOCK: # 增加并发锁,防止多端同时写入导致数据错乱
rows = storage.read(); rows.append(row); storage.write(rows)
self.reply(row, 201)
5. 软件亮点
- 金额按整数分保存:团队在架构设计时,决定借助
records.py里的逻辑,将所有金额转换为整数分处理,彻底避免了浮点数累计带来的精度误差问题。 - 多模块范围一致性:所有的筛选结果、统计卡片、分类图表以及 AI 分析,都严格使用同一个筛选范围的数据,保证展现给用户的数据一致性。
- 安全与原子性:本地存储采用了 JSON 原子替换机制防止数据损坏;AI 模块的密钥只在服务端环境变量中读取,绝不泄露到前端,且只发送汇总数据,不泄露个人隐私备注。
6. 耗时较长或收获较大的事件
- 编码时的并发冲突解决:在整合多模块时发现,如果多个端同时提交记录,会导致
records.json写入冲突甚至内容被覆盖。团队经过讨论,最终在server.py中引入了threading.Lock全局锁,配合原子写入,彻底解决了这个问题。 - 争论并统一金额计算标准:初期前端直接传浮点数,后端简单相加,导致测试时出现了几分钱的偏差。团队内部经过激烈争论,最终拍板定下规范:前端只负责展示,后端必须用
Decimal校验并转成整数分,再由stats.py统一汇总。 - 复审与异常处理:在代码复审阶段,大家发现如果 AI API 网络超时,整个页面会卡死。于是
ai_analysis.py中补充了urllib.error的捕获,并在server.py中对所有的接口请求进行了严密的try-except封装,提升了健壮性。
7. 每个组员的团队编程体验
- 张志强:这次实战让我明白了数据处理不仅要算对,还要考虑展示时的性能,团队协作让接口设计变得更清晰。
- 刘弘毅:作为后端集成的负责人,深刻体会到了全局锁和异常捕获在并发服务中的重要性。
- 华恺:在写存储模块时,为了防崩溃引入了原子替换,让我对文件系统的安全读写有了全新的认识。
- 叶佳旺:前端不仅要把页面画出来,还要考虑不同屏幕的兼容性和动画的流畅度,与后端联调的过程收获很大。
- hyw:接入大模型 API 不仅仅是发请求,还要考虑超时处理;兼顾写启动器脚本,让我对跨平台运行有了了解。
- 丿:负责记录校验,体会到了前后端数据验证的严格要求。只要多加一行
if判断,就能避免很多脏数据入库。
8. SP参考
9. GitHub 仓库地址和 commit 记录
- GitHub 仓库地址:https://github.com/jing-shu491/Account-Book
- Commit 记录截图:
![image]()
(注:lhAsh-839912338请假未参与)




浙公网安备 33010602011771号