找回密码
 立即注册
首页 业界区 业界 软工工程第二次结对作业《Fzu-help》

软工工程第二次结对作业《Fzu-help》

阕阵闲 4 天前
软工工程第二次结对作业《FZU-help》

1. 相关链接

软件工程课程班级链接作业要求作业链接作业目标在第一次需求分析的基础下实现程序学号102201312队友102201311张硕Github仓库102201311-1022013122. 具体分工

成员分工内容张硕设计项目预期模板,负责“留言板”,“项目大厅”,“我的”界面的开发陈言泷负责后端数据库的实现,前端“注册”,“项目发布”的编写实现。3. PSP表格

1.png

4.设计思路

以下描述了需求分析、技术选型、模块设计等。
4.1.1.需求分析

我们先对第一次结对作业所设计的模型,进行了分析。认为第一次的设计模型无法很好的帮助交流,项目发起公示的功能。在此基础上,我们决定优化项目发起的功能,并在项目发布下增加留言板,方便有共同兴趣的同学交流。
在对"rojectParter"要求进行思考分析后,得出的主要功能模块为:

  • 注册
  • 大厅
  • 我的项目管理
  • 发起项目
  • 个人中心
4.1.2.技术选型

基于uniapp框架,设计的一个适应多端使用的小程序《FZU-help》.
配合云开发平台:https://unicloud.dcloud.net.cn/,实现前后端均部署到云服务器上。

  • 前端网页托管:
2.png


  • 后端云数据库+云函数
3.png

技术栈:

  • vite
  • vue3
  • ts
  • uniCloud
  • wotDesignUni
  • sp-editor
环境要求

  • node > 16.20.0
  • npm > 8.19.4
  • HBuilder X > 4.07
部署

  • Serverless 服务
  • 云原生容器平台(支付宝云)
集成插件

  • sp-editor 基于官方的富文本编辑器editor组件改良版
  • wotDesignUni 基于vue3+Typescript构建的精美ui库
  • mp-html 富文本解析器
平台兼容性

阿里云腾讯云支付宝云√×√Vue2Vue3×√App快应用微信小程序支付宝小程序百度小程序字节小程序QQ小程序HBuilderX 4.07 app-vue×√××××钉钉小程序快手小程序飞书小程序京东小程序××××H5-SafariAndroid Browser微信浏览器(Android)QQ浏览器(Android)ChromeIEEdgeFirefoxPC-Safari√√√√√×√√使用语言:

  • 前端框架主力:Vue.js 是这个项目的核心前端框架,负责管理整个应用的用户界面和交互逻辑。Vue的组件化设计能够帮助模块化开发,提升代码的复用性。
  • 编程语言主力:JavaScript 和 TypeScript 搭配使用,JavaScript 负责业务逻辑,TypeScript 提供类型检查和提高代码质量。二者的结合能够帮助团队在开发时更好地控制代码的健壮性和可扩展性。
  • 样式管理:SCSS 是主要的样式工具,通过预处理器功能能够简化复杂样式的管理,而少量的CSS则可能用于一些基础样式的处理。
  • 功能实现:前端功能模块灵活运用**uniapp下所设计好的插件****,实现软件功能模块快速搭建实现。
  • 数据库管理:使用uniapp下的云服务器,后端管理。
4.png

5.模块设计

5.1. 注册模块

前端设计:


  • 界面

    • 表单包括输入框:用户名、邮箱、密码、确认密码。
    • 注册按钮与“已有账号?登录”链接。
    • 用户体验优化:提供加载指示、注册成功后的跳转提示。

  • 技术

    • HTML 表单 + CSS 样式。
    • 使用 JavaScriptVue.js等进行表单验证和交互。

后端设计:


  • API

    • POST /register: 接受前端表单的数据,执行用户验证和数据库插入。

  • 数据库

    • 用户表包含字段:用户ID、用户名、密码(需加密)、注册时间等。

  • 逻辑

    • 密码加密存储(如bcrypt)。

5.2. 项目发起模块

前端设计:


  • 界面

    • 项目名称、项目描述、多行输入框。
    • 任务创建功能,图标化的任务显示。
    • 提供AI大模型(需付费),或允许自定义。

  • 技术

    • 表单设计 + 动态交互:使用Vue.js等前端框架。

后端设计:


  • API

    • 接受创建项目的数据,项目名、描述、团队成员、开始和结束时间等。

  • 数据库

    • 项目表:项目名、描述、发起人等。

  • 逻辑

    • 验证发起者的权限是否能创建项目,发送通知。

5.3. 留言榜模块

前端设计:


  • 界面

    • 类似于讨论板,分为留言列表和留言框。
    • 留言区支持富文本输入(文本、图片、链接等)。
    • 实时刷新留言

  • 技术

    • 留言板组件化设计来动态渲染留言。

后端设计:


  • API
    提交留言。
    获取某个项目下的所有留言。
  • 数据库

    • 留言表:commentID、项目ID、用户ID、留言内容、是否为回复等。

  • 逻辑

    • 权限管理:留言权限(公共权限)。

5.4. 项目管理模块

前端设计:


  • 界面

    • 看板风格的任务管理板,类似Trello,使用卡片展示任务,任务可拖动改变状态(待办、进行中、完成)。
    • 支持任务的细节查看与编辑,如负责人分配、截止日期、优先级标记等。
    • 项目进度条和项目日历,提供视觉化的项目管理工具。

  • 技术

    • 前端使用React+Redux或Vue.js+Vuex来管理复杂的状态变化。
    • 拖拽功能可通过React Beautiful DnD或Vue Draggable实现。
    • 进度条可以使用chart.js或D3.js等库来动态显示进度。

后端设计:


  • API

    • 获取项目的所有任务和其状态。
    • 新建任务。
    • 更新任务状态、负责人等。

  • 数据库

    • 任务表:项目ID、项目类型,负责人、创建时间等。
    • 用户-任务关联表:用于管理任务的负责人和参与者。

  • 逻辑

    • 后端需处理任务状态的变更、权限验证(只有项目负责人可以编辑任务)。
    • 进度计算逻辑:通过任务的完成百分比自动更新项目进度。

6. 关键实现的流程图或数据流图

项目发布数据流表

5.png

项目整体流程图

6.png

7.实现成果展示

使用说明:

  • 手机端扫码即可直接使用(快捷方便,根本不需要下载源码,配置环境,小声bb......)
  • 当然也可以直接pc端使用:点击我
7.png

解释项目的目录结构:

  • page文件夹vue.js控制前后端页面
  • static保存静态图片文件
  • uni_modules功能组件模块
  • uniCloud-alipay 云数据库、云函数
8.png

项目大厅

主要分为五部分的菜单栏:“最新”,“热门”,“竞赛“,”科研“,”创业“
在项目大厅你总可以找到自己心仪的项目
9.png

留言板

招募志同道合的伙伴,并交流项目信息。
10.png

11.png

发布项目

填入项目的基本信息,选择项目的标签,招募你的队友。
12.png

我的项目

添加项目分类,管理查看项目进度
13.png

14.png

个人中心

编辑个人主页信息,查看项目草稿,分类
15.png


注册与登录

使用学号注册登录
17.png

18.png

8. 重要代码片段及解释


  • 1.大厅程序home.vue部分代码

    • 实现了大厅界面设计
    1. <template>
    2.         <view >
    3.                 <wd-tabs v-model="active" animated swipeable @change="tabsChange">
    4.                         <block v-for="item in navList" :key="item.name">
    5.                                 <wd-tab :title="item.title" :name="item.name">
    6.                                         <scroll-view scroll-y="true">
    7.                                                 <view >
    8.                                                         <wd-gap height="85rpx"></wd-gap>
    9.                                                        
    10.                                                         <view  v-for="item in articList" :key="item._id" @click="gotoDetail(item._id)">
    11.                                                                 <blog-item :blog="item" @updateList="updateList(item._id)" />
    12.                                                         </view>
    13.                                                         <view >{{ loadText }}</view>
    14.                                                 </view>
    15.                                         </scroll-view>
    16.                                 </wd-tab>
    17.                         </block>
    18.                 </wd-tabs>
    19.         </view>
    20. </template>
    复制代码
  • 2.发布程序publish.vue部分代码

    • 实现了如何提交到数据库的逻辑
    1. /**
    2. * 确认提交
    3. * @param status 0-草稿箱 1-已发布 2-审核中
    4. */
    5. const onSubmit = (status: number = 1) => {
    6.         articleParams.picurls = getImgList(articleParams.content, 9);
    7.         loading.value = true;
    8.        
    9.         const dbCollection = db.collection("travel-articles");  
    10.             
    11.         // 根据isEdit的值决定是更新还是添加文章  
    12.         const operation = isEdit ?
    13.                 dbCollection.doc(artId.value).update({ ...articleParams, article_status: status }) :
    14.                 dbCollection.add({ ...articleParams, article_status: status });  
    15.        
    16.         operation.then((response: ApiResponse) => {
    17.                 console.log("==== 发布", response)
    18.                 uni.showToast({
    19.                         title: "保存成功",
    20.                         icon: "none",
    21.                 })
    22.                 setTimeout(() => {
    23.                         loading.value = false;
    24.                         handleBackHome();
    25.                 }, 1500)
    26.         }).catch(() => {
    27.                 uni.showToast({
    28.                         title: "保存失败,请联系管理员",
    29.                         icon: "none",
    30.                 })
    31.                 loading.value = false;
    32.         })
    33. }
    复制代码
    19.png


9.附加特点设计与展示

内接大语言模型通义千问
20.png

设计的创意独到之处及意义


  • 增强功能:通过接入大模型,可以为应用程序增加更高级的功能,如自然语言处理、智能推荐等,从而提升用户体验。
  • 节约资源:将复杂的模型处理放到外部服务器,可以节省本地设备的计算资源和存储空间,减轻负担。
  • 实时更新:外接大模型能够及时获取最新的模型版本和算法更新,无需用户手动升级。
  • 高效处理大数据:大模型可以处理和分析海量数据,提供更准确的分析和预测结果。
  • 跨平台兼容:大模型的外接接口可以支持多种平台,提升应用的可扩展性和灵活性。
  • 降低开发成本:借助现有的大模型,项目发布者可以减少从零开始开发复杂算法的时间和成本。
实现思路

查找大语言模型的接口,通过云服务器连接
重要代码片段及解释
  1. module.exports = {
  2.         TURBO_BASE_URL: "https://dashscope.aliyuncs.com", // 通义千问接口地址前缀
  3.         TURBO_KEY: "", // 通义千问key
  4. }
复制代码
解释:这段代码是内置AI通义千问大模型的接口,创建项目时利用大模型来帮助项目创建者编辑文本。
10. 单元测试

10.1 测试工具与教程

测试工具:vue-test-utils和jest
教程:
确保你安装了必要的测试库,比如 vue-test-utils 和 jest。在 package.json 中加入以下依赖:
  1. "devDependencies": {  
  2.         "jest": "^27.0.0",  
  3.         "@vue/test-utils": "^2.0.0",  
  4.         "vue-jest": "^3.0.0"  
  5. }
复制代码
10.2 单元测试代码展示
  1. import { mount } from '@vue/test-utils';  
  2. import Register from '@/path/to/your/register.vue'; // 替换为真实路径  
  3. describe('Register.vue', () => {  
  4.     let wrapper;  
  5.     beforeEach(() => {  
  6.         wrapper = mount(Register);  
  7.     });  
  8.     it('should update username data on input', async () => {  
  9.         const usernameInput = wrapper.find('uni-easyinput[placeholder="请输入学号"]');  
  10.         await usernameInput.setValue('test_user');  
  11.         expect(wrapper.vm.formData.username).toBe('test_user');  
  12.     });  
  13.     it('should submit form successfully', async () => {  
  14.         // 填充表单字段  
  15.         await wrapper.setData({  
  16.             formData: {  
  17.                 username: 'test_user',  
  18.                 nickname: 'Test Name',  
  19.                 password: 'password123',  
  20.                 password2: 'password123',  
  21.                 captcha: '1234' // 假设验证码要求是4个字符  
  22.             }  
  23.         });  
  24.         // 提交表单  
  25.         await wrapper.find('button[type="primary"]').trigger('click');  
  26.         // 你可以在这里增加一些期望,比如检查是否调用了某个方法  
  27.         // expect(...).toBe(...); 这取决于你的完整逻辑  
  28.     });  
  29.     it('should show an error if captcha is invalid', async () => {  
  30.         // 填充表单字段  
  31.         await wrapper.setData({  
  32.             formData: {  
  33.                 username: 'test_user',  
  34.                 nickname: 'Test Name',  
  35.                 password: 'password123',  
  36.                 password2: 'password123',  
  37.                 captcha: '' // 空的验证码  
  38.             }  
  39.         });  
  40.         // 提交表单  
  41.         await wrapper.find('button[type="primary"]').trigger('click');  
  42.         // 验证是否弹出了错误提示  
  43.         // 这里可以根据你的逻辑验证  
  44.         expect(wrapper.vm.$refs.captcha.focusCaptchaInput).toBe(true);  
  45.     });  
  46. });
复制代码
解释:我们将测试register.vue组件,来验证表单提交和输入验证逻辑。
本示例使用 @vue/test-utils 的 mount 方法对组件进行挂载,确保组件生命周期函数正确执行。
10.3 测试数据构造思路

1. 正向场景(Valid Test Cases)

这些是测试可以成功注册的情况:

  • 有效的用户名和密码:

    • 用户名:仅数字学号
    • 昵称:学号姓名
    • 密码:至少 8 个字符,包括字母和数字
    • 再次输入的密码应与密码一致
    • 验证码:符合长度和格式要求(例如 4 位数字)

  1. javascriptconst validTestData = {  
  2.     username: 'validUser123',  
  3.     nickname: 'Valid User',  
  4.     password: 'Password123',  
  5.     password2: 'Password123',  
  6.     captcha: '1234'  
  7. };  
复制代码
2. 边界情况(Boundary Test Cases)

这些测试旨在检查系统对输入边界的处理:

  • 最短和最长输入:

    • 用户名长度为 1 和最大限制(例如 20 字符)
    • 密码最短(例如 8 个字符)和最大(例如 20 字符)

  1. javascriptconst boundaryTestData = [  
  2.     { username: 'a', password: 'Password123', password2: 'Password123', captcha: '1234' }, // 边界最短  
  3.     { username: 'aVeryLongUserNameThatExceedsLimit', password: 'Password123', password2: 'Password123', captcha: '1234' } // 边界最长  
  4. ];  
复制代码
3. 负向场景(Invalid Test Cases)

这些场景用于测试错误输入条件,包括不符合要求的字段。

  • 缺少必填字段:

    • 用户名、密码、验证码为空等

  • 密码不匹配:

    • 输入的两个密码不一致

  • 无效格式的验证码:

    • 验证码格式不正确,如字母、特殊字符等

  1. javascriptconst invalidTestData = [  
  2.     { username: '', nickname: 'Valid User', password: 'Password123', password2: 'Password123', captcha: '1234' }, // 用户名为空  
  3.     { username: 'testUser', nickname: 'Valid User', password: 'Password123', password2: '', captcha: '1234' }, // 密码未确认  
  4.     { username: 'testUser', nickname: 'Valid User', password: 'Password123', password2: 'Password456', captcha: '1234' }, // 密码不匹配  
  5.     { username: 'testUser', nickname: 'Valid User', password: 'Password123', password2: 'Password123', captcha: 'abc' } // 验证码格式不正确  
  6. ];  
复制代码
4. 特殊字符和空格处理

用来测试系统如何处理包含特殊字符或空格的输入。
  1. javascriptconst specialCharTestData = {  
  2.     username: 'test user!', // 包含空格和特殊字符  
  3.     password: '1234!@#$', // 包含特殊字符  
  4.     password2: '1234!@#$', // 包含特殊字符和一致性  
  5.     captcha: '1234'  
  6. };  
复制代码
5. 状态变化测试

这些测试用于验证在不同用户状态下的注册流程:

  • 已经存在的用户名(比如用户名冲突)
  • 同一用户尝试重复注册
  1. javascriptconst existingUserTestData = {  
  2.     username: 'existingUser123', // 这个用户在系统中已存在  
  3.     nickname: 'Existing User',  
  4.     password: 'Password123',  
  5.     password2: 'Password123',  
  6.     captcha: '1234'  
  7. };  
复制代码
11. GitHub代码签入记录

21.png

12. 遇到的问题及解决方法

1.项目详细页面异常

异常描述
项目页面大厅显示正常,点击页面空白
解决方法

  • 检查后台数据库接口是否正常。
  • 确定前端代码是否编写正确。
解决与收获:前端页面代码错打,导致页面无法正常显示。
在面对bug时,找相应代码,别慌。
2.注册页面实现与预期不符

异常描述
使用学号作为注册账号时出现bug,无法以纯数字登录。
解决方法

  • 通过关键字找到相应注册页面
  • 分析注册时编写限制逻辑
解决与收获:逻辑修改即成功。
设计逻辑框架时需要仔细严谨。
13. 对队友
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册