软件工程第二次结对作业
这个作业属于哪个课程 | https://edu.cnblogs.com/campus/fzu/SE2024 |
---|---|
这个作业要求在哪里 | https://edu.cnblogs.com/campus/fzu/SE2024/homework/13281 |
这个作业的目标 | 小组结对合作进行项目完成 |
学号 | 102201335 |
1. 项目地址
https://github.com/apppp0701/102201335-102201342
2. 具体分工
姓名 | 分工 |
---|---|
潘宇晴 | 编写前端代码,实现初步项目 |
董雯莉 | 编写后端代码,实现数据库连接 |
3. PSP表格
PSP2.1 | Personal Software Process Stages | 预估耗时(小时) | 实际耗时(小时) |
---|---|---|---|
Planning | 计划 | 0.5 | 1 |
Estimate | 估计这个任务需要多少时间 | 0.5 | 0.5 |
Development | 开发 | 20 | 35 |
Analysis | 需求分析 (包括学习新技术) | 5 | 7.5 |
Test | 测试(自我测试,修改代码,提交修改) | 2 | 3.5 |
Test Repor | 测试报告 | 2.5 | 3 |
Postmortem&Process Improvement Plan | 事后总结, 并提出过程改进计划 | 1 | 1 |
合计 | 31.5 | 51.5 |
4. 代码实现思路
前端代码思路
- 登录页面
功能描述:进入app看到的第一个页面,包含“登录”和“注册”两个按钮,可以进行登录及跳转注册。
实现思路:在登录页面组件中,使用Vue的数据绑定和事件处理实现用户输入与按钮点击逻辑,通过uni-app的API控制页面跳转。
代码实现:
methods: {
// 处理登录的方法
handleLogin() {
// 模拟登录成功,无论输入如何
// 使用uni-app的switchTab方法跳转到首页
uni.switchTab({
url: '/pages/index/index' // 指定跳转的页面路径
});
},
// 处理跳转到注册页面的方法
navigateToRegister() {
// 使用uni-app的navigateTo方法跳转到注册选择页面
uni.navigateTo({
url: '/pages/register/choice' // 指定跳转的页面路径
})
}
}
- 身份选择
功能描述:应用启动后显示的第一个页面,包含两个身份选择按钮:“我是老师”和“我是学生”,用户可以选择身份后跳转到注册页面。
实现思路:在身份选择页面组件中,使用Vue的事件处理实现按钮点击逻辑,通过uni-app的API存储用户选择并控制页面跳转。
3.注册
功能描述: 本页面是用户注册页面,允许用户填写个人信息来完成注册流程。
实现思路:通过 .wxml 文件定义注册页面的布局,包括头像上传区域、注册表单以及提交按钮。,在 .js 文件中定义数据模型和事件处理方法,包括头像上传逻辑和注册逻辑。uploadAvatar 方法用于处理用户上传头像,register 方法用于处理注册提交,包括验证输入和跳转到登录页面。
代码实现:
methods: {
// 上传头像图片的方法
uploadAvatar() {
// 调用uni-app的chooseImage API让用户选择图片
uni.chooseImage({
count: 1, // 限制用户选择一张图片
sizeType: ['compressed'], // 图片类型,这里只允许压缩图
sourceType: ['album', 'camera'], // 图片来源,可以是相册或者相机
success: (res) => {
// 选择图片成功后,将图片的临时路径赋值给组件的avatar数据属性
this.avatar = res.tempFilePaths[0];
}
});
},
// 处理注册的方法
register() {
// 在这里进行输入验证和注册逻辑
// 假设注册成功后执行以下代码
uni.navigateTo({
url: '/pages/login/login' // 跳转到登录页面
});
}
}
}
4.首页
功能描述: 主页作为应用的导航中心,提供了“搜索项目”和“发布项目”等核心功能。用户可以通过搜索框查找感兴趣的项目或团队,同时,主页还会根推荐合适的跨专业合作项目。
实现思路:
搜索功能:通过在搜索框中输入关键字,并调用后台接口来获取匹配的项目或团队列表。
发布项目:用户可以自己在表单内填入内容进行发布。
推荐项目:根据用户的专业、兴趣等信息,在主页上展示推荐的项目卡片。
-
人才推荐
功能描述: 该页面是一个人才推荐页面,它展示了不同人才的信息卡片,包括姓名、学校、专业和角色(学生或老师)。用户可以通过搜索框查找特定的人才,并且可以通过点击卡片或聊天图标与人才进行交流。
实现思路:
页面布局:使用Flexbox布局创建一个垂直排列的页面结构,包括一个头部区域、搜索框和人才卡片列表。
数据展示:通过v-for指令循环展示people数组中的每个人才信息,每个人才信息都包含在一个卡片内。
交互功能:为每个人才卡片添加点击事件,允许用户查看更多人才信息或与人才进行聊天。
-
消息界面
功能描述: 该页面是一个消息列表页面,展示了用户的聊天列表。用户点击列表项可以跳转到与对方的聊天页面。
实现思路:
页面布局:使用Flexbox布局创建一个垂直排列的消息列表,每个列表项为一个消息卡片。
数据展示:通过v-for指令循环展示messages数组中的每条消息,每个消息卡片包含头像、昵称和新消息指示点。
交互功能:为每个消息卡片添加点击事件,当点击时,标记该消息为已读,并跳转到对应的聊天页面。
-
聊天界面
功能描述: 该页面是一个聊天界面,用户可以输入消息,并点击发送。
实现思路:
数据展示:通过v-for指令循环展示chatMessages数组中的每条消息,根据消息类型(接收或发送)决定消息的排列方向和头像显示。
交互功能:提供一个输入框供用户输入消息,并有一个发送按钮。当用户点击发送按钮时,将输入的消息添加到chatMessages数组中,并清空输入框。
-
个人主页
功能描述: 该页面是一个用户个人主页,根据用户的角色(老师或学生)展示不同的内容,可以通过角色切换按钮在老师和学生的身份之间进行切换,并可以点击进入自己发布的项目和参与的项目。
数据绑定:通过Vue的数据绑定功能,根据userRole的值动态显示老师或学生的主页内容。
交互功能:提供按钮点击事件处理方法,用于角色切换和页面跳转。同时,处理头像加载失败的情况,显示提示信息。
切换角色代码实现:
<!-- 老师主页 -->
<!-- 使用v-if指令判断用户角色是否为老师,如果是,则显示老师主页的内容 -->
<view v-if="userRole === 'teacher'" class="profile">
<!-- 显示欢迎信息 -->
<text>欢迎你,这里是你的老师主页。</text>
<!-- 点击按钮跳转到我的项目页面 -->
<button @click="navigateToMyProject">我的项目</button>
<!-- 点击按钮跳转到指导项目页面 -->
<button @click="navigateToProjectPage">指导项目</button>
</view>
<!-- 学生主页 -->
<!-- 使用v-else-if指令判断用户角色是否为学生,如果是,则显示学生主页的内容 -->
<view v-else-if="userRole === 'student'" class="profile">
<!-- 显示欢迎信息 -->
<text>欢迎你,这里是你的学生主页。</text>
<!-- 点击按钮跳转到我的项目页面 -->
<button @click="navigateToMyProject">我的项目</button>
<!-- 点击按钮跳转到参与项目页面 -->
<button @click="navigateToProjectPage">参与项目</button>
</view>
<!-- 角色切换区域 -->
<view class="role-switch">
<!-- 显示切换角色的提示文本 -->
<text>切换角色:</text>
<!-- 点击按钮将用户角色设置为老师 -->
<button @click="setRole('teacher')">老师</button>
<!-- 点击按钮将用户角色设置为学生 -->
<button @click="setRole('student')">学生</button>
</view>
-
我的项目
功能描述:可以点击进入自己发布的不同项目并进行管理,调整项目状态和审核成员。
实现思路:数据展示:通过v-for指令循环展示people数组中的每个人员信息,并使用数据绑定显示相关信息。
交互功能:为每个人员卡片提供一个按钮,用于切换其加入状态(“同意申请"或"已加入”),并将状态存储在localStorage中。提供一个全局状态切换按钮,用于在"招募中"、"进行中"和"已完成"之间循环切换。
-
参与项目
功能描述:可以随时退出参与的项目。
实现思路:使用exitProject方法处理退出按钮的点击事件,将对应项目的状态更改为“已退出”。
代码实现:
<!-- 退出按钮,根据项目状态显示不同的文本 -->
<button
class="exit-button"
:class="{ 'exited': item.status === '已退出' }"
@click.stop="exitProject(index)"
>
<!-- 如果项目状态为'已退出',则显示'已退出',否则显示'退出' -->
{{ item.status === '已退出' ? '已退出' : '退出' }}
</button>
</view>
</view>
</view>
</view>
</template>
后端代码思路
注册思路
生成register模块,models文件中写入应有的数据模型,配置url环境和视图函数
项目展示思路
生成project模块,models文件写入数据模型,form文件写入格式,配置url环境和视图函数
5. 附加特点设计与展示
在人才推荐界面设置一键沟通按键,可直接点击跳转专人聊天界面,无需寻找
代码实现
goToChat(person) {
// Navigate to the chat page and pass the person data
uni.navigateTo({
url: `/pages/chat/chat?name=${person.name}&id=${person.id}&major=${person.major}&role=${person.role}`
});
},
在个人界面设置身份切换功能,可以切换老师与学生的身份,并跳转管理项目
代码实现
methods: {
setRole(role) {
this.userRole = role; // 根据按钮设置用户身份
},
navigateToMyProject() {
// 跳转到我的项目页面
uni.navigateTo({
url: '/pages/myself/myproject' // 确保路径正确
});
},
navigateToProjectPage() {
// 跳转到项目页面
uni.navigateTo({
url: '/pages/myself/project' // 跳转到 pages/myself/project
});
},
onImageError() {
uni.showToast({ title: '头像加载失败', icon: 'none' });
}
}
6. 项目说明和目录说明
目录说明
- easyjob(front-end)
- .hbuilderx # HBuilderX项目配置文件
- componets/Statusbar # 状态栏
- pages # 页面
- chat # 聊天页面
- creat # 创建项目页面
- index # 首页
- login # 登录页面
- message # 消息页面
- myself # 个人中心页面
- people # 推荐人界面
- post # 发布项目页面
- register # 注册页面
- static # 静态资源
- unpackage
- App.vue
- main.js
- manifest.json
- index.html
- pages.json
- uni.promisify.adaptor.js
- server(back-end)
- server
- __init__.py
- asgi.py
- settings.py
- urls.py
- wsgi.py
- routing.py
- register
- __init__.py
- admin.py
- apps.py
- api_urls.py
- models.py
- tests.py
- views.py
- people.py
- project
- __init__.py
- admin.py
- apps.py
- form.py
- models.py
- tests.py
- views.py
- api_urls.py
- manage.py
- templates
使用说明
点击app打开软件,进行个人信息注册,首页有项目推荐,可点击查看详情;人才页有学生和老师人才推荐,可点击查看人才信息,也可点击右边的聊天标识进入聊天页面;消息页面可以和想认识的人才交流;我的页面可以查看自己所参加的项目或指导的项目。
7. 单元测试
测试工具
我们选用 Jest 作为测试框架,Jest测试的好处是它提供了快速的并行测试执行、内置的代码覆盖率报告以及零配置的易用性,使得编写和运行JavaScript测试变得简单高效。
测试学习教材
学习单元测试的步骤如下:
· 了解单元测试的定义、目的和重要性。选择合适的测试框架(如Jest、Mocha、Jasmine等)和断言库(如Chai、Should.js等)。从最简单的函数开始,学习如何编写测试用例。
· 掌握各种断言方法,用于验证代码的实际行为与预期是否一致。学习使用模拟对象(mocks)、存根(stubs)和间谍(spies)来隔离测试。
· 了解如何使用覆盖率工具来评估测试的全面性。学习如何根据测试结果来修复代码缺陷和重构代码。将单元测试集成到持续集成流程中,确保代码质量。不断学习新的测试技巧和最佳实践,提高测试效率和质量。
具体测试:登录测试
测试代码
const login = require('./login');
describe('Login Function', () => {
it('should login successfully with correct credentials', async () => {
const credentials = {
username: 'testuser',
password: 'testpassword'
};
await expect(login(credentials.username, credentials.password)).resolves.toEqual({
status: 'success',
message: '登录成功'
});
});
it('should fail to login with incorrect credentials', async () => {
const credentials = {
username: 'wronguser',
password: 'wrongpassword'
};
await expect(login(credentials.username, credentials.password)).rejects.toEqual({
status: 'error',
message: '用户名或密码错误'
});
});
});
测试思路
· 第一个测试用例确保当提供正确的用户名和密码时,登录功能能够正常工作。
· 第二个测试用例确保当提供错误的用户名和密码时,登录功能能够正确地处理错误并返回相应的错误信息。
· 由于登录操作通常是异步的(例如,涉及到数据库查询或网络请求),测试用例使用了 async/await 语法来处理异步逻辑。
· toEqual 和 rejects 是 Jest 的匹配器,用于验证函数的返回值是否符合预期。
考虑未来测试的挑战
· 全面性:编写测试用例时,尽量覆盖所有可能的执行路径,包括条件分支和循环。
· 编写清晰、有组织的测试代码,以便其他测试人员理解和维护。
· 为测试用例编写文档,说明每个测试的目的和预期结果。
· 确保测试用例本身不会因为外部变化而失败,例如避免使用硬编码的值。
· 设计测试框架和测试数据构造方法时,考虑未来的扩展性,以便容易添加新的测试用例。
· 模拟测试人员可能故意输入的“恶意”数据,测试代码的防御能力。
· 鼓励测试人员提供反馈,并根据反馈调整测试策略。
8. Github项目签到截图
9. 遇见的代码模块异常或结对困难与解决办法
1.问题:myproject页面点击卡片跳转,在浏览器上模拟存在但是打包成app点击无法跳转。
尝试和解决办法:通过筛查是否是按钮使用了事件冒泡,并且有一个父元素的事件处理器捕获了所有的事件,导致其他按钮的事件处理器没有被触发,将卡片的点击功能变为一个,不存在父子元素,在点开的界面里再次加入被删减的功能。同时检查代码发现遗留的localstorage逻辑上的错误,进行修改,多次打包测试解决问题。
收获:积累了宝贵的经验,学会了如何优化组件设计,通过合并点击功能,避免了不必要的父子元素关系,了解了代码审查的重要性。
2.问题:发行软件时软件的图标没有按上传的图片并且打包时屡屡出现问题。
尝试和解决办法:查阅资料发现图标只能是png格式而我上传了jpg格式,转换了图标的格式。打包出现问题经过筛查发现是图片的名称中有中文,修改图片名称,成功打包。
收获:了解到app对图标的格式要求,以及文件命名的规范,意识到在软件开发过程中,即使是看似小的细节(如文件格式和命名)也很重要。
3.问题:更改一个页面的格式其他页面也发生了变化。
尝试和解决办法:经过查阅资料发现是不同的页面中相同的名字的全局格式互相影响,采取了两种方式进行解决,第一种是改变变量的名称,第二种是修改style为style scoped。
收获:加深了对全局样式和局部样式的理解,知道了新的技巧,提高了解决问题的能力。
10. 对队友的评价
值得学习的地方:
队友积极好学,在前端开发上很有效率,做的界面基本符合原型设计;并且能够及时修正错误,迅速找到解决方案
需要改进的地方:
队友在部分模块上还是不能尽善尽美,可以考虑更深入学习测试框架的功能