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. 软件运行截图和视频

  • HL65BEF@HW2L%MQ4(RNT@7
  • EGI@6GX(2}A{63JXEID_Y

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. 软件亮点

  1. 金额按整数分保存:团队在架构设计时,决定借助 records.py 里的逻辑,将所有金额转换为整数分处理,彻底避免了浮点数累计带来的精度误差问题。
  2. 多模块范围一致性:所有的筛选结果、统计卡片、分类图表以及 AI 分析,都严格使用同一个筛选范围的数据,保证展现给用户的数据一致性。
  3. 安全与原子性:本地存储采用了 JSON 原子替换机制防止数据损坏;AI 模块的密钥只在服务端环境变量中读取,绝不泄露到前端,且只发送汇总数据,不泄露个人隐私备注。

6. 耗时较长或收获较大的事件

  1. 编码时的并发冲突解决:在整合多模块时发现,如果多个端同时提交记录,会导致 records.json 写入冲突甚至内容被覆盖。团队经过讨论,最终在 server.py 中引入了 threading.Lock 全局锁,配合原子写入,彻底解决了这个问题。
  2. 争论并统一金额计算标准:初期前端直接传浮点数,后端简单相加,导致测试时出现了几分钱的偏差。团队内部经过激烈争论,最终拍板定下规范:前端只负责展示,后端必须用 Decimal 校验并转成整数分,再由 stats.py 统一汇总。
  3. 复审与异常处理:在代码复审阶段,大家发现如果 AI API 网络超时,整个页面会卡死。于是 ai_analysis.py 中补充了 urllib.error 的捕获,并在 server.py 中对所有的接口请求进行了严密的 try-except 封装,提升了健壮性。

7. 每个组员的团队编程体验

  • 张志强:这次实战让我明白了数据处理不仅要算对,还要考虑展示时的性能,团队协作让接口设计变得更清晰。
  • 刘弘毅:作为后端集成的负责人,深刻体会到了全局锁和异常捕获在并发服务中的重要性。
  • 华恺:在写存储模块时,为了防崩溃引入了原子替换,让我对文件系统的安全读写有了全新的认识。
  • 叶佳旺:前端不仅要把页面画出来,还要考虑不同屏幕的兼容性和动画的流畅度,与后端联调的过程收获很大。
  • hyw:接入大模型 API 不仅仅是发请求,还要考虑超时处理;兼顾写启动器脚本,让我对跨平台运行有了了解。
  • 丿:负责记录校验,体会到了前后端数据验证的严格要求。只要多加一行 if 判断,就能避免很多脏数据入库。

8. SP参考

点击查看SP参考

9. GitHub 仓库地址和 commit 记录

posted @ 2026-11-07 22:29  Mhosse  阅读(2)  评论(0)    收藏  举报