2024软工实践

news/2025/1/10 0:39:33/文章来源:https://www.cnblogs.com/fufubufff/p/18522658
作业所属课程 https://edu.cnblogs.com/campus/fzu/SE2024
作业要求 https://edu.cnblogs.com/campus/fzu/SE2024/homework/13302
作业的目标 在三个小时内编写出一个个人记账本,用户可以对自己平时的收入和支出情况进行简单的记录,查看和统计
团队名称 “研途无忧”
团队成员学号-名字 102202101-马鑫、102202141-黄昕怡、102202123-张铭心、102202112-刘莹、102202145-谢含、102202115-孙佳会、102202106-王强、102201317-陈磊、102201439-谢芳菲

一、队员的职责分工
马鑫、王强:负责博客的撰写与协助程序优化
黄昕怡:程序框架的搭建,细分队员的各个工作板块
张铭心:界面设计
孙佳会:bug检查与修复
刘莹、谢含:部分功能开发、界面美化
陈磊、谢芳菲:程序测试与界面美化

二、程序运行环境使用
用JavaScript进行编程,WXML(微信标记语言)和WXSS(微信样式表)来构建界面
使用云函数、云数据库等服务,用于后端开发和数据管理

三、软件运行截图和视频
1.登陆我们的小程序,引入眼帘的就是非常可爱的个人页面

2.如果你有更喜欢的背景图片也可以选择更换

3.接下来的是我们的添加支出界面,这个界面有多种类型供你选择,可以清楚为自己的花销分类

4.选择我们的类别添加具体的消费(想去北京)

5.同时我们不止有记录支出的功能,还有记录收入的功能,这也是一个记账app必不可少的(相中彩票)

6.这是我们的记账详情界面,它可以查看不同年月的具体支出,同时会统计年月的总支出与总收入,非常实用

7.同时为了满足j人需求,我们还推出了计划功能,可以说是相当人性化

8.添加计划后马上在我的计划界面显示,完成每一个功能的实现,绝不画饼(想换手机了)

9.可以在添加账单时选择计划,同时在添加账单的时候也可实时增添计划

10.将每次选择计划的账单金额同步到对应计划里

11.同时我们也提供人性化服务更改账单

四.关键代码

1.基础记账:实现基础的记账功能,记录每笔支出或收入,包括:日期、金额、类别(如饮食、交通、工资等)、备注。

点击查看代码
saveBook(){//保存记账功能let _this = this;let data = this.data;if(data.activeType == -1 || data.amt == 0){return; // 如果未选择类型或金额为0,则不保存}let date = app.getDateInfo(this.data.selectDay); // 获取选择的日期信息let bookType = data.bookTypeList[data.activeType]; // 获取选中的账单类型let params = {amtType: data.activeTab, // 支出或收入类型bookAmt:data.amt-0, // 账单金额bookDate:date.date, // 账单日期bookMonth:date.month, // 账单月份bookYear:date.year, // 账单年份week:date.week, // 账单星期remark:data.remark, // 备注bookTypeName: bookType.name, // 账单类型名称bookTypeIcon: bookType.icon, // 账单类型图标bookTypeId: bookType._id, // 账单类型IDplanId:data.planList[data.planIdx]._id // 计划ID}if (data.remark) {let remarkArr = this.data.remarkArr;if (remarkArr[bookType._id]){if (remarkArr[bookType._id].indexOf(data.remark) == -1) {remarkArr[bookType._id].push(data.remark); // 添加新的备注this.setData({remarkArr:remarkArr});_this.setStorage('remarks', remarkArr); // 更新缓存中的备注}}else{remarkArr[bookType._id] = [data.remark];this.setData({remarkArr: remarkArr});_this.setStorage('remarks', remarkArr); // 更新缓存中的备注}}if(this.data.bookId){params.id = this.data.bookId;app.getAjax({url:'editBook', // 编辑账单params:params,success(res){console.log("editBook:",res);wx.navigateBack(); // 返回上一页}});}else{app.getAjax({url:'addBook', // 添加账单params:params,success(res){console.log("addBook:",res);wx.navigateBack(); // 返回上一页},fail(res){console.log("addBookFail:",res);common.showModal('添加失败,请稍后重试!'); // 显示添加失败提示}});}
}

2.查看数据:用户可以通过小程序查看最近的几笔记录。

点击查看代码
onShow: function () {app.getAjax({url:'login',params:{},success:res=>{console.log('[云函数] [login] user openid: ', res.result.openid)app.globalData.openid = res.result.openid // 获取用户的openid并存储到全局变量}})let dateObj = app.getDateInfo(); // 获取当前日期信息this.initData(dateObj.year, dateObj.month); // 初始化数据
},initData(year, month) {//初始化数据let _this = this;app.getAjax({url:'getUserBookList', // 获取用户账单列表params:{bookYear: year - 0, // 账单年份bookMonth: month - 0 // 账单月份},success(res){console.log("getUserBookList:", res);let sortedBookList = _this.sortBookList(res.result.data); // 对账单列表进行排序和格式化_this.setData({bookList: sortedBookList.sortData, // 设置账单列表数据incomeAmt: sortedBookList.incomeAmt, // 设置收入金额payAmt: sortedBookList.payAmt, // 设置支出金额selectYear: year, // 设置选中的年份selectMonth: month // 设置选中的月份});console.log("bookList:", sortedBookList.sortData)}});
},sortBookList(data) {//格式化账单列表let dateArr = [],sortData = [],incomeAmt = 0,payAmt = 0;for(var key in data){let index = dateArr.indexOf(data[key].bookDate);let amtType = data[key].amtType;if (index == -1){dateArr.push(data[key].bookDate);sortData.push({date: data[key].bookDate,week: ['日', '一', '二', '三', '四', '五', '六'][data[key].week], // 将星期数转换为中文incomeAmt: amtType == '0' ? 0 : data[key].bookAmt, // 如果是收入,设置收入金额payAmt: amtType == '0' ? data[key].bookAmt : 0, // 如果是支出,设置支出金额list: [data[key]] // 初始化账单列表});} else {if(amtType == 0){sortData[index].payAmt = (sortData[index].payAmt * 100 + data[key].bookAmt * 100) / 100; // 累加支出金额} else {sortData[index].incomeAmt = (sortData[index].incomeAmt * 100 + data[key].bookAmt * 100) / 100; // 累加收入金额}sortData[index].list.push(data[key]); // 添加账单记录到列表}if(amtType == 0){payAmt += data[key].bookAmt; // 累加总支出金额} else {incomeAmt += data[key].bookAmt; // 累加总收入金额}}return {sortData: sortData, // 返回格式化后的账单列表incomeAmt: parseInt(incomeAmt * 100) / 100, // 返回总收入金额payAmt: parseInt(payAmt * 100) / 100 // 返回总支出金额}
}

3.收支统计: 用户可以根据日期,类别,金额等查看总支出和收入情况。

点击查看代码
onLoad: function (options) {if(options.id){this.setData({amtType:options.type, // 设置收支类型id:options.id, // 设置类型IDyear:options.year, // 设置年份beginMonth:options.mon1, // 设置开始月份endMonth:options.mon2 // 设置结束月份});this.getChartDetail(); // 获取统计详情}else{let month = new Date().getMonth() + 1;let year = new Date().getFullYear();this.setData({year:year, // 设置当前年份beginMonth:month, // 设置当前月份endMonth:month, // 设置当前月份monthArr:this.data.monthArr.slice(12-month), // 设置月份数组dateTypeIdx:0 // 设置日期类型索引});this.initData(); // 初始化数据}
},initData(){let _this = this;let data = this.data;this.setData({chartList:[] // 清空统计列表});app.getAjax({url:'getChartData', // 获取统计数据params:{amtType:data.amtType, // 收支类型year: data.year-0, // 年份beginMonth: data.beginMonth, // 开始月份endMonth:data.endMonth // 结束月份},success(res){console.log("getChartData:",res);let data = res.result.list;let count = 0;for(var key in data){data[key].count = parseInt(data[key].count*100)/100; // 格式化金额count += data[key].count; // 计算总金额}_this.setData({chartList:data, // 设置统计列表chartListCount:count // 设置总金额});}});
},getChartDetail(){let _this = this;let data = this.data;app.getAjax({url:'getChartDetailData', // 获取统计详情数据params:{id:data.id, // 类型IDyear:data.year, // 年份beginMonth:data.beginMonth, // 开始月份endMonth:data.endMonth // 结束月份},success(res){console.log("getChartDetailData:",res);let data = res.result.data;let count = 0;for(var key in data){count += data[key].bookAmt; // 计算总金额}_this.setData({chartList: data, // 设置统计详情列表chartListCount: count // 设置总金额});}});
}

4.花销管理计划:用户可以根据消费意愿设置计划,查看计划。

设置计划:

点击查看代码
onLoad: function (options) {if(options.pid){this.setData({planId:options.pid, // 设置计划IDplan:app.globalData.plan // 设置全局计划数据});this.initData(); // 初始化数据}
},initData(){let _this = this;app.getAjax({url:'getPlanBookList', // 获取计划账单列表params:{planId:_this.data.planId // 传递计划ID参数},success(res){console.log("getPlanBookList:",res);_this.setData({bookList:res.result.data // 设置账单列表数据});}});
}
查看计划:
点击查看代码
onShow: function () {this.getPlanList(); // 页面显示时获取计划列表
},getPlanList(){//获取计划列表let _this = this;app.getAjax({url: 'getPlanList', // 请求获取计划列表params: {type: _this.data.amtType // 传递收支类型参数},success(res) {console.log("getPlanList:", res);let planList = res.result;for(var key in planList){planList[key].diffAmt = planList[key].planAmt - planList[key].total; // 计算计划剩余金额planList[key].showInfo = false; // 初始化计划详情显示状态}_this.setData({planList: planList // 设置计划列表数据});}});
},setAmtType(e) {//选择收入支出类型this.setData({amtType: e.currentTarget.dataset.type // 设置收支类型});this.getPlanList(); // 重新获取计划列表
},showPlanInfo(e){//显示计划进度let idx = e.currentTarget.dataset.idx;this.setData({[`planList[${idx}].showInfo`]:!this.data.planList[idx].showInfo // 切换计划详情显示状态});
},toPlanDetail(e){//到计划详情页let idx = e.currentTarget.dataset.idx;let plan = this.data.planList[idx];if(plan.total == 0){return; // 如果计划总金额为0,则不跳转}app.globalData.plan = plan; // 设置全局计划数据app.navigate(`/pages/planBookList/planBookList?pid=${plan._id}`); // 跳转到计划详情页
}

五.设计亮点

1. 计划管理功能

  • 计划创建与管理:用户可以创建不同的消费计划,并根据计划进行消费管理。每个计划都有详细的金额记录和剩余金额显示,帮助用户更好地控制支出。
  • 动态显示计划详情:通过 showPlanInfo 方法,用户可以动态展开或收起计划的详细信息,查看每个计划的进度和具体消费记录。
  • 收支类型切换:用户可以通过 setAmtType 方法切换查看支出或收入的计划列表,方便用户分类管理不同类型的计划。
  • 计划删除功能:通过 showDeleteBtn 和 deletePlanList 方法,用户可以方便地删除不需要的计划,保持计划列表的整洁。
  • 计划详情跳转:通过 toPlanDetail 方法,用户可以跳转到具体计划的详情页面,查看该计划下的所有消费记录,帮助用户更详细地了解每个计划的执行情况。

2. 账单管理功能

  • 账单记录与编辑:用户可以记录每一笔支出或收入,并可以随时编辑已记录的账单。
    账单类型与备注管理:用户有多种图标进行选择账单类型,并添加备注。用户可以根据账单类型获取相应的备注提示,方便用户快速输入常用备注。
  • 日期选择与金额输入:用户可以选择账单日期,并通过数字键盘输入金额。通过 bindDateChange 和 setAmt 方法,用户可以方便地选择日期和输入金额。
    这些设计亮点使得计划管理功能更加实用和人性化,帮助用户更好地进行财务规划和管理。

六.过程与收获

1. 计划管理功能的设计与实现

  • 事件描述: 在设计和实现计划管理功能时,团队花费了大量时间讨论如何让用户能够方便地创建、查看和管理消费计划。特别是在计划的创建和编辑界面设计上,如何让用户直观地输入和查看计划的详细信息,以及如何动态显示计划的进度和剩余金额。
  • 收获:
    学会了如何通过用户体验设计提升功能的易用性。
    了解了如何在前端代码中动态更新和显示数据。
    掌握了如何通过接口与后端进行数据交互,确保数据的实时性和准确性。

2. 收支统计功能的优化

  • 事件描述: 在实现收支统计功能时,团队遇到了如何高效地统计和展示大量账单数据的问题。特别是在按日期范围和类型进行统计时,如何确保数据的准确性和展示的流畅性。
  • 收获:
    学会了如何通过算法优化数据的统计和排序,提高性能。
    了解了如何通过图表和数据可视化技术,直观地展示统计结果。
    掌握了如何通过用户交互设计,让用户能够方便地切换和查看不同的统计数据。

3. 数据同步与缓存机制的实现

  • 事件描述: 在实现数据同步与缓存机制时,团队花费了大量时间讨论如何确保数据的实时性和一致性,特别是在网络不稳定或离线状态下,如何通过本地缓存机制保证用户数据的完整性和可用性。
  • 收获:
    学会了如何通过本地缓存技术(如微信小程序的 wx.setStorage 和 wx.getStorageSync)提升应用的性能和用户体验。
    了解了如何通过数据同步机制,确保本地数据与服务器数据的一致性。
    掌握了如何处理网络异常和数据同步失败的情况,确保用户数据的安全和完整。

4. 账单详情页面的设计与实现

  • 事件描述: 在设计和实现账单详情页面时,团队花费了大量时间讨论如何让用户能够方便地查看和编辑账单的详细信息。特别是在账单类型、金额、备注等信息的展示和编辑上,如何确保界面的简洁和易用。
  • 收获:
    学会了如何通过组件化设计提升页面的可维护性和复用性。
    了解了如何通过数据绑定和事件处理,实现账单详情的动态展示和编辑功能。
    掌握了如何通过接口与后端进行数据交互,确保账单数据的实时更新和同步。

5.数据统计与图表展示

  • 事件描述: 在实现数据统计与图表展示功能时,团队花费了大量时间讨论如何让用户能够直观地查看收支统计数据,并通过图表展示数据的变化趋势。特别是在处理大量数据的统计和图表绘制时,如何确保数据的准确性和展示的流畅性。
  • 收获:
    学会了如何通过数据统计算法优化数据的计算和处理,提高性能。
    了解了如何通过图表库(如 ECharts)实现数据的可视化展示,提升用户体验。
    掌握了如何通过用户交互设计,让用户能够方便地切换和查看不同的统计数据和图表。

七、每个组员的团队编程体验

  • 马鑫:在此次随堂编程中,我体会到了速度与激情,在短短的三个小时内制作成了一个功能完整的记账小程序,从设计到编码的过程中再到最后的优化阶段,感受到团队前所未有的凝聚力。在初期,我并不熟悉微信开发小程序的使用,在编码中期我也遇到了许多困难,期间在队友的帮助下,我解决了一个又一个困难,最后我要感谢我们的团队,谢谢大家。
  • 孙佳会:这次团队编程作业时间很紧急,只有三个小时,但是大家分工很明确很完善。每个人负责自己的部分,在写的过程中都非常迅速,最后整合给演示的同学,也在GitHub上上传了代码,我们团队最后的完成程度很不错,基础的功能都实现了。在这次团队作业中,我深刻体会到了团队合作的重要性,自己的代码速度以及与队友配合的能力都得到了很好的锻炼。
  • 谢含:在这次现场编程中,通过快速开发记账小程序,我了解道每个成员之间熟悉的领域,大家集思广益快速分工,在有限的时间push出一个简单的成品,心酸苦楚只有自己知道,但也是这种有压力的感觉,激发出最大的潜力,我主要负责的是前端开发(美工),看见页面成果就会很开心呀呀呀,我爱软件工程(不要现场编程)。
  • 刘莹:在本次记账小程序的团队编程过程中,大家刚开始共同商量小程序的风格并快速领取了自己要完成的代码部分,最后在fu姐的领导和明星姐的整合下完成了最后的展示,最终的效果还是非常令人满意的,很高兴和大家一起完成这次编程任务!
  • 张铭心:和优秀的组员们一起,能在这么短的时间内开发出功能完备的记账小程序使我收获颇丰,关键是每个类型消费收入的统计我们也考虑在内,并且实现了可视化,这点更是让人欣喜。
    非常有趣的小组编程,使我的大脑高速运转。ps:一起扣头也是有趣👍
  • 王强:通过本次项目,我受益匪浅,收获了关于数据同步与缓存机制的实现的相关知识,了解了如何通过图表和数据可视化技术,直观地展示统计结果等技术。我们不仅提升了编程技能,还学会了如何进行团队协作和项目管理。每个成员都在项目中发挥了重要作用,大家共同努力,最终成功实现了项目目标。希望在未来的项目中,我们能够继续保持这种良好的合作精神,不断提升自己的技术水平和项目管理能力。
  • 磊弟:我负责的是项目详情(book detail)页面和部分首页(index) 内容的开发,为保证页面与整体项目风格的一致性,我们团队在开始编码前定义了统一的编码规范、UI风格。在代码编写过程中,我更加注重代码的清晰性、可读性。严格遵守编码规范,包括代码命名、注释、模块划分等,确保团队其他成员能够理解我的代码。由于开发时间仅有三小时,一些复杂的UI细节被暂时放弃,我负责的页面也遵循了简洁、实用的原则。在时间紧迫的情况下,我们团队本次采用了敏捷开发的方式,将整个项目进行了多次迭代,在迭代结束时进行总结,很有效地推进了项目。项目完成后,我对最终开发出来的产品感到十分自豪。我们团队默契配合,每个人的努力都汇聚在一起,才很好地完成了本次任务。。
    谢芳菲:在编程的过程中,感觉非常的吃力,因为对于很多东西都不太理解,但是正是这种吃力也让我学到了很多新的东西。编程的过程就是不断克服困难。

八、PSP

PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 240 270
· Estimate · 估计这个任务需要多少时间 240 270
Development 开发 180 195
· Analysis · 需求分析 (包括学习新技术) 10 5
· Design Spec · 生成设计文档 10 10
· Design Review · 设计复审 (和同事审核设计文档) 5 5
· Coding Standard · 代码规范 (为目前的开发制定合适的规范) 10 5
· Design · 具体设计 25 25
· Coding · 具体编码 100 120
· Code Review · 代码复审 10 15
· Test · 测试(自我测试,修改代码,提交修改) 10 10
Reporting 报告 60 75
· Test Report · 测试报告 30 45
· Size Measurement · 计算工作量 15 10
· Postmortem & Process Improvement Plan · 事后总结, 并提出过程改进计划 15 20
合计 240 270

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/825946.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Winform在主窗体里切换多个窗体

1.点击解决方案资源管理器的项目名称,右键添加用户控件(Windows窗体)。2.在主窗体代码中实例化添加的用户控件(Windows窗体)。3.在主窗体界面中添加pane控件,该控件的大小就是要切换的界面大小,然后在主窗体代码中将实例化的用户控件(Windows窗体)添加到pane控件的集合…

目前遇到过的编码

Base家族 base16 由大写字母(A-Z)和数字(0-9)组成,通常不需要“=”填充 base32 由(A-Z、2-7)32个可见字符构成,“=”符号用作后缀填充 例:NZXV64DBONZXO33SMQ====== KVEEQRSCI5DVKVSXKZEUQS2FJBKE2WKKGI2EKNCWJFCUQNSKIVAVINBTKVKE2TZUKVHUWRZWGRIVSVSNJZJFIQKNIZLDIN…

NOI LINUX 系统终端常用操作

打开终端 我们可以右键空白处 - 在终端中打开(Open in Terminal)/Ctrl+Alt+T 快捷键打开终端。 考试时编译、运行、调试、对拍、测大样例等行为的操作 对于一个 C++ 可执行文件 1.cpp 为例:编译: g++ 1.cpp -o qwq,其中 1.cpp 可替换为任意 C++ 可执行文件,qwq 表示已编译…

[BUUCTF]disk

[BUUCTF]disk[BUUCTF]disk 分析 VMDK:(VMWare Virtual Machine Disk Format)是虚拟机VMware创建的虚拟硬盘格式,文件存在于VMware文件系统中,被称为VMFS(虚拟机文件系统) 解题 凡是先打开010获得ctf{unseCure_quick_form4t_vo1umer 查找另外一半 用7Z打开该vmdk文件,发…

云南5日游

1 总览🦋云南景点合集 💛昆明:石林景区、昆明老街、滇池、斗南花市 💜大理:大理古城、洱海、苍山、喜洲古镇、南诏风情岛、双廊古镇、崇圣寺三塔 💙丽江: 玉龙雪山、蓝月谷、云杉坪、束河古镇、丽江古城、泸沽湖、 💚香格里拉:普达措公园、虎跳峡、独克宗古城、梅…

记录一下自己的优化字符串匹配算法

谁能拒绝一个写法比KMP简单,时间复杂度摸摸KMP(`O(n)` & `O(m+n)`),空间复杂度大概持平KMP的可可爱爱的KeBF呢😘我愿称之KeBF算法Ke的BF(Brute Force,暴力检索)法 关于其他 字符串匹配算法示例源码 #include <stdio.h> #include <string.h>int main() {//…

收集一些好看的图片

收集一些好看的背景和头像背景 游戏像素其它头像

海南话语音识别模型——模型训练(一)

上篇文章已经介绍了语料数据的预处理,对数据集中的音频数据分别做了重采样、静音切除、降噪以及在Fbank和MFCC中特征提取方式中选择了Fbank对音频数据进行特征提取的方法;在经过上面的处理后已经可以将提取出的音频数据Fbank丢到Transformer中进行训练,但还漏了一个比较重要…

2024秋软件工程iman现场编程作业

作业所属课程 班级的链接作业要求 2024秋软件工程现场编程作业 - 作业 - 软件工程2024 - 班级博客 - 博客园作业目标 现场极限编程,制作一个个人记账本程序。团队名称 iman团队成员 102202146 - 蓝敏龙, 102201225 - 陈碧煌, 102202105 - 王梓铭, 102202124 - 阿依娜孜, 10220…

4 Empirical Properties of Limit Order Books

LOB 可以揭露很多有趣的微观信息,近年来也有许多研究。但需要注意:高频交易的进化速度极快,让这些研究很多时候比较过时。 Originally Posted at: https://clouder0.com/zh-cn/posts/lob-empirical-properties/ 总结性的来说,作者发现了这些特点:每日交易量大概占市值的 \…

2024秋软工实践iman原型设计和UML设计

信息类别 内容作业所属课程 软件工程实践 - 秋季班作业要求 第一次团队作业 - 原型设计与概要设计作业目标 根据需求分析和设计,完成项目的原型设计和概要设计,培养团队协作能力,为后续的开发奠定基础。团队名称 iman 🌟团队成员 - 102202146 - 蓝敏龙- 102201225 - 陈碧煌…

CF1658E Gojou and Matrix Game

题意题解 设f[i,j]表示(i,j)先手必胜/必败 则全局max一定必败,因为先手走出去后手走回来,重复无限次后必输 然后全局max外(距离>k)的必胜,因为可以走到全局max 之后可以发现,下一个必败的是全局max范围内的次max,因为次max不能①走出全局max范围 ②走到全局max ③走到…