110
社区成员
发帖
与我相关
我的任务
分享| 这个作业属于哪个课程 | 202501福大-软件工程实践-W班 |
|---|---|
| 这个作业要求在哪里 | 团队作业——CodeArts团队实战 |
| 这个作业的目标 | 完成CodeArts团队实战 |
| 其他参考文献 | 《构建之法》 |
本系统主要涉及两类参与者,分别是普通用户和管理员。
用户使用系统的旅程始于注册与登录。成功进入系统后,用户可以通过管理个人信息用例,填写或更新其购车预算、偏好车型、使用场景等关键信息,这些信息将构成用户的个人画像,为后续的精准咨询奠定数据基础。核心的交互环节是发起购车咨询。用户提交结构化的意向表单后,系统会自动触发生成购车建议这一子流程。该过程通过调用大语言模型,结合用户画像,生成一份结构化的购车分析报告。“生成购车建议”是“发起购车咨询”不可或缺的组成部分,二者构成严格的包含关系。咨询结束后,用户可以随时查看咨询记录,回顾历史对话与建议。如果用户对某次咨询结果满意或不满意,可以提交反馈,进行评分或留言。作为正向激励,提交反馈这一行为可以扩展至获取/兑换积分用例,即用户通过反馈、分享等行为积累积分,并最终用于兑换礼品,从而形成一个完整的激励闭环。
管理员侧的功能主要集中于监督、管理与分析。他们可以查看所有咨询记录,以便进行内容审核和问题追溯;同时具备管理用户账号的权限,如冻结违规账户,保障系统安全。此外,管理员可以通过查看用户行为统计来了解系统活跃度与用户偏好,并借助热门话题分析功能,提取高频咨询主题,从而指导知识库的更新与市场运营策略的制定。

系统有如下核心类:

登录与注册模块是系统用户身份认证的基础组件,负责用户账号的创建、身份校验及会话管理,为后续的 AI 咨询、积分管理等功能提供安全访问控制。核心功能包括:邮箱注册(含验证码校验)、手机号密码登录、密码重置(支持邮箱 / 手机验证码方式),并基于 Sa-Token 框架实现身份令牌管理。
该模块后端架构分为四个层次。请求层通过UserController接收 HTTP 请求,定义注册、登录等接口,负责参数合法性校验(如非空检查、密码一致性验证)。
@PostMapping("/register")
public void register(@RequestBody CreateUserReq req) {
// 处理注册逻辑
if (StringUtils.isBlank(req.getEmail())) {
throw new BadRequestException("邮箱不能为空");
}
if (StringUtils.isBlank(req.getPassword())) {
throw new BadRequestException("密码不能为空");
}
if (StringUtils.isBlank(req.getConfirmPassword())) {
throw new BadRequestException("确认密码不能为空");
}
if (!req.getPassword().equals(req.getConfirmPassword())) {
throw new BadRequestException("密码不一致");
}
if (StringUtils.isBlank(req.getCode())) {
throw new BadRequestException("验证码不能为空");
}
if (!validCodeService.check(req.getEmail(), req.getCode())) {
throw new BadRequestException("验证码错误");
}
userService.createUser(req);
}
@PostMapping("/login")
public SaResult login(@RequestBody LoginReq req) {
if (StringUtils.isBlank(req.getPhone())) {
throw new BadRequestException("手机号不能为空");
}
if (StringUtils.isBlank(req.getPassword())) {
throw new BadRequestException("密码不能为空");
}
SaTokenInfo tokenInfo = userService.login(req);
return SaResult.data(tokenInfo);
}
业务层用UserService接口及实现类封装核心逻辑,包括用户创建、密码加密、身份验证、Token 生成等。
public interface UserService {
void createUser(CreateUserReq req);
SaTokenInfo login(LoginReq req);
void updateUser(UserDto userDto);
void updatePassword(UpdatePwReq req);
void resetPassword(CheckEmailCodeReq req);
void increasePoints(Integer points);
void resetPasswordByPhone(CheckPhoneCodeReq req);
String signIn(Long userId);
Integer getContinuousDays(Long userId);
List<UserDto> getPointsRank(Long id);
List<UserDto> getAllPointsRank();
}
数据层基于 MyBatis-Plus 实现与数据库交互,通过UserMapper操作sys_user表,存储用户账号信息。而安全层依赖 Sa-Token 框架实现会话管理,通过PasswdUtil对密码进行加密存储,避免明文泄露。
个人页面模块是用户管理自身信息、查看积分与签到状态的核心入口,承担用户信息展示、编辑、积分分解锁及日常签到等功能,为用户提供个性化数据管理与交互服务。核心功能包括:个人信息查询与更新、密码修改与重置、积分查询与排名查看、头像上传与展示、每日签到与连续签到天数统计。
后端架构中,接口层通过UserController暴露 HTTP 接口,涵盖信息查询、更新、密码操作、积分管理、签到等功能。部分代码如下:
@PostMapping("/login")
public SaResult login(@RequestBody LoginReq req) {
if (StringUtils.isBlank(req.getPhone())) {
throw new BadRequestException("手机号不能为空");
}
if (StringUtils.isBlank(req.getPassword())) {
throw new BadRequestException("密码不能为空");
}
SaTokenInfo tokenInfo = userService.login(req);
return SaResult.data(tokenInfo);
}
@GetMapping("/info")
public UserDto getUserInfo() {
// 检查是否已登录
if (!StpUtil.isLogin()) {
throw new BadRequestException("用户未登录");
}
// 从Session中获取用户对象
User user = (User) StpUtil.getSession().get("user");
if (user == null) {
throw new BadRequestException("用户信息不存在");
}
// 将User对象转换为UserDto
UserDto userDto = UserConvert.toUserDto(user);
return userDto;
}
@PutMapping("/update")
public void updateUserInfo(@RequestBody UserDto userDto) {
userService.updateUser(userDto);
}
@PutMapping("/updatePassword")
public void updatePassword(@RequestBody UpdatePwReq req) {
userService.updatePassword(req);
}
@PutMapping("/increasePoints")
public void increasePoints(@RequestParam Integer points) {
if (points == null || points <= 0) {
throw new BadRequestException("积分必须大于0");
}
userService.increasePoints(points);
}
业务层使用UserService接口及实现类封装核心逻辑,包括用户信息 CRUD、密码加密与校验、积分计算、签到状态管理等。数据层基于 MyBatis-Plus 实现数据访问,通过UserMapper操作sys_user表存储用户基础信息,UserSignInMapper操作user_sign_in表记录签到数据。
在安全设计方面,所有接口通过 Sa-Token 拦截未登录请求,确保仅登录用户可访问个人信息。采用PasswdUtil对密码进行 AES 加密存储,避免明文泄露;密码修改 / 重置需验证验证码或旧密码,防止恶意操作。密码修改时,用户提交旧密码与新密码,后端校验旧密码正确性,确认一致后加密存储新密码。
public class PasswdUtil {
private static final String AES = "AES"; // 加密算法
private static final String CHARSET = "UTF-8"; // 字符集
private static final String SECRET_KEY = "app@agent"; // 密钥(需要妥善保管)
private static final String ALGORITHM = "SHA1PRNG"; // 算法
/**
* 加密
*
* @param data 明文密码
* @return 加密后的密码
*/
public static String encode(String data) {
if (data == null) {
return null;
}
try {
// 生成加密密钥
SecretKeySpec key = generateKey();
// 创建加密器
Cipher cipher = Cipher.getInstance(AES);
cipher.init(Cipher.ENCRYPT_MODE, key);
// 加密数据
byte[] encryptedData = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));
// 使用Base64编码返回
return Base64.getEncoder().encodeToString(encryptedData);
} catch (Exception e) {
throw new RuntimeException("加密失败", e);
}
}
/**
* 解密
*
* @param encryptedData 加密后的密码
* @return 解密后的明文密码
*/
public static String decode(String encryptedData) {
try {
// 生成解密密钥
SecretKeySpec key = generateKey();
// 创建解密器
Cipher cipher = Cipher.getInstance(AES);
cipher.init(Cipher.DECRYPT_MODE, key);
// 解密数据
byte[] decodedData = cipher.doFinal(Base64.getDecoder().decode(encryptedData));
return new String(decodedData, StandardCharsets.UTF_8);
} catch (Exception e) {
throw new RuntimeException("解密失败", e);
}
}
/**
* 生成密钥
*
* @return SecretKeySpec 对象
*/
private static SecretKeySpec generateKey() throws Exception {
// 使用指定密钥生成器
KeyGenerator keyGenerator = KeyGenerator.getInstance(AES);
SecureRandom secureRandom = SecureRandom.getInstance(ALGORITHM);
secureRandom.setSeed(PasswdUtil.SECRET_KEY.getBytes(StandardCharsets.UTF_8));
keyGenerator.init(128, secureRandom);
SecretKey secretKey = keyGenerator.generateKey();
return new SecretKeySpec(secretKey.getEncoded(), AES);
}
}
查询模块实现多种功能,包括:基于用户输入生成专业购车建议、支持多轮对话上下文管理、会话历史记录与查询、多 AI 模型切换(如 GLM、Qwen),并基于用户购车偏好提供精准推荐。
会话管理模块中,在会话创建时,用户首次发送消息,getOrCreateActiveSession自动创建新会话(状态为 “进行中”,status=0);调用startNewSession可手动结束当前会话并创建新会话(旧会话状态更新为 “已完成”,status=1)。
@PostMapping("/new-session")
public Map<String, Object> startNewSession() {
Long userId = StpUtil.getLoginIdAsLong();
Long newSessionId = aiChatService.startNewSession(userId);
return Map.of(
"code", 200,
"message", "新会话已创建",
"sessionId", newSessionId
);
}
会话存储,把会话信息(用户 ID、状态、创建时间)存入car_consult_session表,通过userId索引快速查询用户历史会话。
// 获取某次会话的完整聊天记录
@GetMapping("/session/{sessionId}/messages")
public List<ChatMessage> getSessionMessages(@PathVariable Long sessionId) {
Long userId = StpUtil.getLoginIdAsLong();
// 校验 sessionId 是否属于该用户(略)
List<ChatMessage> messages = aiChatService.getSessionMessages(sessionId);
return messages;
}
消息交互时,前端提交消息内容与模型类型(model),后端校验非空后,通过saveMessage将用户消息(role=user)存入chat_message表,关联当前会话 ID。接着构建对话上下文,加载当前会话的历史消息,结合系统提示(SYSTEM_PROMPT)生成完整对话链(区分 GLM 和 Qwen 模型的消息格式)。调用模型时,根据model参数选择不同大模型接口,返回 AI 回复后存入数据库(role=assistant)。
// 用户发送消息
public String sendMessage(Long userId, String userInput,String model) {
Long sessionId = getOrCreateActiveSession(userId);
// 保存用户消息
saveMessage(sessionId, "user", userInput);
if ("glm".equals(model)){// 构建完整对话历史(含 system prompt)
List<ai.z.openapi.service.model.ChatMessage> messages = buildMessagesForAi(sessionId);
// 调用 AI
String aiResponse = zhipuAiClient.chatWithHistory(messages);
// 保存 AI 回复
saveMessage(sessionId, "assistant", aiResponse);
// 可选:判断是否结束会话(例如用户说“谢谢,不需要了”)
if (shouldEndSession(aiResponse, userInput)) {
endSession(sessionId);
}
return aiResponse;
}
if ("Qwen".equals(model)) {
// 3. 获取该 session 所有历史消息(按时间排序)
List<ChatMessage> history = messageMapper.selectList(
new QueryWrapper<ChatMessage>()
.eq("session_id", sessionId)
.orderByAsc("created_at")
);
// 4. 构造 DashScope 所需的 Message 列表
List<Message> QwenMessages = new ArrayList<>();
QwenMessages.add(Message.builder()
.role(Role.SYSTEM.getValue())
.content(SYSTEM_PROMPT)
.build());
for (ChatMessage msg : history) {
String role = "user".equals(msg.getRole()) ? Role.USER.getValue() : Role.ASSISTANT.getValue();
QwenMessages.add(Message.builder()
.role(role)
.content(msg.getContent())
.build());
}
// 5. 调用 DashScope
String aiReply = callDashScope(QwenMessages);
saveMessage(sessionId, "assistant",aiReply);
// 可选:判断是否结束会话(例如用户说“谢谢,不需要了”)
if (shouldEndSession(aiReply, userInput)) {
endSession(sessionId);
}
return aiReply;
}
return null;
}
private String callDashScope(List<Message> messages) {
try {
Generation gen = new Generation();
GenerationParam param = GenerationParam.builder()
.apiKey(dashScopeApiKey)
.model("qwen-flash") // 或 qwen-max(更强)、qwen-turbo(更快)
.messages(messages)
.resultFormat(GenerationParam.ResultFormat.MESSAGE)
.build();
GenerationResult result = gen.call(param);
List<GenerationOutput.Choice> choices = result.getOutput().getChoices();
if (choices != null && !choices.isEmpty()) {
return choices.get(0).getMessage().getContent();
} else {
throw new RuntimeException("AI 返回为空");
}
} catch (Exception e) {
throw new RuntimeException("AI 服务暂时不可用,请稍后再试");
}
}
minio下载
下载地址:
https://dl.minio.org.cn/server/minio/release/windows-amd64/minio.exe
在PowerShell或命令提示符中,cd命令进到可执行文件的位置,或添加minio.exe文件所在路径 至windows系统环境变量 $PATH 中。
假设存放路径为:D:\tool\minio\minio.exe,就需要:cd D:\tool\minio,
然后执行命令:
minio.exe server C:\mydata --address ":9001" --console-address ":9000"
C:\mydata: 这是存储数据的目录路径,请替换为你自己的路径。--address ":9001": 指定用于 S3 API 请求的端口。--console-address ":9000": 指定用于 Web 控制台的端口。访问 MinIO控制台:
http://127.0.0.1:9000
MinIO使用监听的端口为 9000 端口,这个端口使用API与MinIO服务器进行通信和进行SDK调用,通过浏览器访问 9000 端口会自动跳转至MinIO控制台。
登录MinIO 控制台可以使用默认的 Root用户名/密码 登录: minioadmin / minioadmin 。
就可以显示相关控制台的详细信息。






修改为自己创建的access-key、secret-key
进入项目目录
# 切换到你的项目文件夹(替换为实际路径)
cd D:\code1\qianduan\smart-car-system
依赖下载
# 安装项目核心依赖
npm install
# 安装 Tailwind 及相关工具(Windows 下必须显式指定版本)
npm install -D tailwindcss@3.3.5 postcss@8.4.31 autoprefixer@10.4.16
项目启动
npm start
JDK 安装
java -version验证。Maven 配置
mvn -v验证。数据库安装
数据库创建
用户登录

用户注册

个人界面

对话界面

对话结果









旧版本:17次
前端:34次
后端:2次
master版本:1次
总计:54次
| 学号 | 姓名 | 工作内容 |
|---|---|---|
| 102300428 | 何振坤 | 开发积分系统、管理员模块和数据统计功能 |
| 102300103 | 刘子祎 | 开发前端项目基础框架、登录注册页面和用户信息管理组件 |
| 102300106 | 陈思焓 | 实现购车咨询表单、结果展示页面和所有UI样式布局 |
| 102300110 | 尹肇兴 | 搭建后端项目框架和数据库结构,编写核心配置文件和部署脚本 |
| 102300123 | 鲁申如 | 编写单元测试、压力测试脚本和API接口测试用例 |
| 102300125 | 林浩宇 | 封装阿里百炼和智普AI的API调用,实现咨询结果生成逻辑 |
| 102300425 | 郭育铭 | 开发咨询记录存储、查询接口和业务逻辑处理模块 |
| 102300426 | 陈炜滨 | 编写用户注册登录、信息管理等API接口和JWT认证逻辑 |
| 学号 | 姓名 | 存在的问题与困难 | 解决方案 | 心得体会 |
|---|---|---|---|---|
| 102300428 | 何振坤 | 积分规则设计复杂,数据统计维度多,管理员权限管理困难 | 参考电商积分系统设计,使用RBAC权限模型,采用图表库实现数据可视化 | 通过开发积分系统,深入理解了用户激励机制设计,掌握了复杂业务逻辑的实现方法 |
| 102300103 | 刘子祎 | 前端框架选型困难,组件复用性差,用户交互体验优化挑战大 | 采用Vue3+TypeScript,设计可复用组件库,使用响应式布局和交互动效 | 前端架构设计需要充分考虑扩展性和维护性,组件化开发大大提升了开发效率 |
| 102300106 | 陈思焓 | UI设计风格统一难,表单验证复杂,响应式布局适配多种设备 | 制定统一的设计规范,使用表单验证库,采用移动优先的响应式设计 | 用户体验是前端开发的核心,细节决定成败,良好的UI设计能显著提升用户满意度 |
| 102300110 | 尹肇兴 | 数据库表结构设计复杂,API接口规范制定困难,部署环境配置繁琐 | 使用数据库设计工具,制定统一的API响应格式,采用Docker容器化部署 | 后端架构设计需要前瞻性,良好的数据库设计和API规范是项目成功的基础 |
| 102300123 | 鲁申如 | 测试用例覆盖不全,压力测试场景设计复杂,性能瓶颈定位困难 | 采用测试金字塔模型,使用JMeter进行压力测试,结合日志分析定位问题 | 测试是质量的保证,自动化测试能有效减少回归测试工作量,提升代码质量 |
| 102300125 | 林浩宇 | 不同LLM API接口差异大,响应结果解析复杂,提示词工程优化困难 | 设计统一的适配器模式,制定标准化的响应格式,通过A/B测试优化提示词 | LLM集成需要充分考虑异常处理和降级策略,提示词的质量直接影响咨询效果 |
| 102300425 | 郭育铭 | 业务逻辑复杂度高,数据一致性要求严格,并发访问性能优化挑战 | 采用事务保证数据一致性,使用Redis缓存热点数据,优化数据库查询 | 业务逻辑开发需要深入理解需求,良好的代码结构和注释能提升团队协作效率 |
| 102300426 | 陈炜滨 | 用户认证安全要求高,密码加密存储复杂,权限控制逻辑繁琐 | 使用bcrypt加密密码,实现JWT token机制,设计细粒度的权限控制 | 安全是用户系统的生命线,必须从多维度保障用户数据安全和系统稳定 |
| 学号 | 姓名 | 贡献度 |
|---|---|---|
| 102300428 | 何振坤 | 12 |
| 102300103 | 刘子祎 | 12 |
| 102300106 | 陈思焓 | 12 |
| 102300110 | 尹肇兴 | 13 |
| 102300123 | 鲁申如 | 12 |
| 102300125 | 林浩宇 | 13 |
| 102300425 | 郭育铭 | 14 |
| 102300426 | 陈炜滨 | 12 |
| PSP | 时间占比 | 实际耗时(分钟) | 说明 |
|---|---|---|---|
| 计划 | 15% | 180 | 进行需求分析,制定开发计划 |
| 估计时间 | 22 | 任务工作量估计 | |
| 开发 | 65% | 780 | 实际编码时间 |
| 需求分析 | 60 | 需求分析 | |
| 生成设计文档 | 45 | 生成设计文档 | |
| 设计复审 | 30 | 设计复审 | |
| 代码规范制定 | 15 | 代码规范制定 | |
| 具体设计 | 75 | 具体设计 | |
| 具体编码 | 300 | 具体编码 | |
| 代码复审 | 45 | 代码复审 | |
| 测试 | 150 | 测试 | |
| 报告 | 20% | 240 | 撰写报告和文档 |
| 测试报告 | 60 | 测试报告 | |
| 计算工作量 | 30 | 计算工作量 | |
| 事后总结与过程改进计划 | 150 | 事后总结,提出改进计划 | |
| 合计 | 100% | 1200 | 总工作时间20小时 |
| PSP | 时间占比 | 实际耗时(分钟) | 说明 |
|---|---|---|---|
| 计划 | 18% | 216 | 前端技术选型和架构设计 |
| 估计时间 | 30 | 任务工作量估计 | |
| 开发 | 62% | 744 | 前端开发实现 |
| 需求分析 | 60 | 需求分析 | |
| 生成设计文档 | 45 | 生成设计文档 | |
| 设计复审 | 30 | 设计复审 | |
| 代码规范制定 | 15 | 代码规范制定 | |
| 具体设计 | 90 | 组件设计 | |
| 具体编码 | 375 | 具体编码 | |
| 代码复审 | 60 | 代码复审 | |
| 测试 | 105 | 测试 | |
| 报告 | 20% | 240 | 撰写报告和文档 |
| 测试报告 | 60 | 测试报告 | |
| 计算工作量 | 30 | 计算工作量 | |
| 事后总结与过程改进计划 | 150 | 事后总结,提出改进计划 | |
| 合计 | 100% | 1200 | 总工作时间20小时 |
| PSP | 时间占比 | 实际耗时(分钟) | 说明 |
|---|---|---|---|
| 计划 | 15% | 180 | UI/UX设计规划 |
| 估计时间 | 24 | 任务工作量估计 | |
| 开发 | 65% | 780 | 界面开发和样式实现 |
| 需求分析 | 60 | 需求分析 | |
| 生成设计文档 | 60 | 生成设计文档 | |
| 设计复审 | 30 | 设计复审 | |
| 代码规范制定 | 15 | 代码规范制定 | |
| 具体设计 | 120 | 页面设计 | |
| 具体编码 | 390 | 具体编码 | |
| 代码复审 | 45 | 代码复审 | |
| 测试 | 96 | 测试 | |
| 报告 | 20% | 240 | 撰写报告和文档 |
| 测试报告 | 60 | 测试报告 | |
| 计算工作量 | 30 | 计算工作量 | |
| 事后总结与过程改进计划 | 150 | 事后总结,提出改进计划 | |
| 合计 | 100% | 1200 | 总工作时间20小时 |
| PSP | 时间占比 | 实际耗时(分钟) | 说明 |
|---|---|---|---|
| 计划 | 18% | 216 | 后端架构设计规划 |
| 估计时间 | 30 | 任务工作量估计 | |
| 开发 | 62% | 744 | 后端框架搭建和开发 |
| 需求分析 | 60 | 需求分析 | |
| 生成设计文档 | 60 | 生成设计文档 | |
| 设计复审 | 30 | 设计复审 | |
| 代码规范制定 | 15 | 代码规范制定 | |
| 具体设计 | 90 | 架构设计 | |
| 具体编码 | 360 | 具体编码 | |
| 代码复审 | 60 | 代码复审 | |
| 测试 | 105 | 测试 | |
| 报告 | 20% | 240 | 撰写报告和文档 |
| 测试报告 | 60 | 测试报告 | |
| 计算工作量 | 30 | 计算工作量 | |
| 事后总结与过程改进计划 | 150 | 事后总结,提出改进计划 | |
| 合计 | 100% | 1200 | 总工作时间20小时 |
| PSP | 时间占比 | 实际耗时(分钟) | 说明 |
|---|---|---|---|
| 计划 | 12% | 144 | 测试计划和策略制定 |
| 估计时间 | 15 | 任务工作量估计 | |
| 开发 | 58% | 696 | 测试用例编写和执行 |
| 需求分析 | 45 | 需求分析 | |
| 生成设计文档 | 30 | 生成测试文档 | |
| 设计复审 | 15 | 设计复审 | |
| 代码规范制定 | 15 | 代码规范制定 | |
| 具体设计 | 60 | 测试方案设计 | |
| 具体编码 | 270 | 测试代码编写 | |
| 代码复审 | 30 | 代码复审 | |
| 测试 | 255 | 测试执行 | |
| 报告 | 30% | 360 | 测试报告和总结 |
| 测试报告 | 150 | 测试报告 | |
| 计算工作量 | 30 | 计算工作量 | |
| 事后总结与过程改进计划 | 180 | 事后总结,提出改进计划 | |
| 合计 | 100% | 1200 | 总工作时间20小时 |
| PSP | 时间占比 | 实际耗时(分钟) | 说明 |
|---|---|---|---|
| 计划 | 18% | 216 | LLM集成方案设计 |
| 估计时间 | 30 | 任务工作量估计 | |
| 开发 | 62% | 744 | API集成和开发 |
| 需求分析 | 75 | 需求分析 | |
| 生成设计文档 | 60 | 生成设计文档 | |
| 设计复审 | 30 | 设计复审 | |
| 代码规范制定 | 15 | 代码规范制定 | |
| 具体设计 | 90 | 接口设计 | |
| 具体编码 | 345 | 具体编码 | |
| 代码复审 | 45 | 代码复审 | |
| 测试 | 120 | 测试 | |
| 报告 | 20% | 240 | 撰写报告和文档 |
| 测试报告 | 60 | 测试报告 | |
| 计算工作量 | 30 | 计算工作量 | |
| 事后总结与过程改进计划 | 150 | 事后总结,提出改进计划 | |
| 合计 | 100% | 1200 | 总工作时间20小时 |
| PSP | 时间占比 | 实际耗时(minutes) | 说明 |
|---|---|---|---|
| 计划 | 15% | 180 | 咨询业务逻辑设计 |
| 估计时间 | 24 | 任务工作量估计 | |
| 开发 | 65% | 780 | 业务逻辑开发实现 |
| 需求分析 | 60 | 需求分析 | |
| 生成设计文档 | 45 | 生成设计文档 | |
| 设计复审 | 30 | 设计复审 | |
| 代码规范制定 | 15 | 代码规范制定 | |
| 具体设计 | 90 | 业务逻辑设计 | |
| 具体编码 | 405 | 具体编码 | |
| 代码复审 | 45 | 代码复审 | |
| 测试 | 126 | 测试 | |
| 报告 | 20% | 240 | 撰写报告和文档 |
| 测试报告 | 60 | 测试报告 | |
| 计算工作量 | 30 | 计算工作量 | |
| 事后总结与过程改进计划 | 150 | 事后总结,提出改进计划 | |
| 合计 | 100% | 1200 | 总工作时间20小时 |
| PSP | 时间占比 | 实际耗时(分钟) | 说明 |
|---|---|---|---|
| 计划 | 15% | 180 | 用户认证系统设计 |
| 估计时间 | 24 | 任务工作量估计 | |
| 开发 | 65% | 780 | 用户系统开发实现 |
| 需求分析 | 60 | 需求分析 | |
| 生成设计文档 | 45 | 生成设计文档 | |
| 设计复审 | 30 | 设计复审 | |
| 代码规范制定 | 15 | 代码规范制定 | |
| 具体设计 | 90 | 安全架构设计 | |
| 具体编码 | 390 | 具体编码 | |
| 代码复审 | 45 | 代码复审 | |
| 测试 | 141 | 测试 | |
| 报告 | 20% | 240 | 撰写报告和文档 |
| 测试报告 | 60 | 测试报告 | |
| 计算工作量 | 30 | 计算工作量 | |
| 事后总结与过程改进计划 | 150 | 事后总结,提出改进计划 | |
| 合计 | 100% | 1200 | 总工作时间20小时 |