| 这个作业属于哪个课程 | 前往班级圈子 |
|---|---|
| 这个作业要求在哪里 | 查看作业要求 |
| 这个作业的目标 | 1. 个人平台搭建 2. 熟悉API调用 3. 自我认知与规划 |
| 学号 | 102401309 |
0. 准备工作
前往
1. huggingface API 调用
1.1 流程
| 步骤 | 任务 | 要点 | 注意 |
|---|---|---|---|
| 1 | Token 生成 | Settings - Access Tokens | 额度限制可能需要多个账号 |
| 2 | 环境安装依赖 | pip install flask huggingface_hub pillow python-dotenv |
在项目虚拟环境下安装 |
| 3 | 构建有关文件 | .env, app.py |
写入 Token,运行启动 Flask |
| 4 | 前后端交互与调用 | http://127.0.0.1:5000 |
提示词迭代 |
1.2 代码
AI 生成,点击展开
.env
HF_TOKEN=hf_...
app.py
# ==================== 第1步:导入工具箱 ====================
import os
import base64
import io
from flask import Flask, request, jsonify
from huggingface_hub import InferenceClient
from PIL import Image
from dotenv import load_dotenv
# ==================== 第2步:加载密钥 ====================
load_dotenv()
HF_TOKEN = os.getenv("HF_TOKEN")
if not HF_TOKEN:
raise ValueError("❌ 没有找到 HF_TOKEN!请检查 .env 文件是否存在并填写了令牌。")
MODEL_ID = "XLabs-AI/flux-RealismLora"
client = InferenceClient(token=HF_TOKEN)
# ==================== 第3步:创建Flask应用 ====================
app = Flask(__name__)
# ==================== 第4步:风格化前端页面 ====================
@app.route('/')
def index():
return '''
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Flux 真实感 · AI 图像生成</title>
<!-- 字体:Inter 和 JetBrains Mono,营造专业感 -->
<link href=" https://fonts.googleapis.com/css2?family=Inter:opsz ,wght@14..32,400;14..32,500;14..32,600;14..32,700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet" />
<style>
/* ===== 全局重置 & 暗色主题 ===== */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Inter', -apple-system, sans-serif;
background: #0b0d0f;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 40px 24px;
background-image: radial-gradient(ellipse at 20% 50%, rgba(30, 40, 60, 0.4) 0%, transparent 60%),
radial-gradient(ellipse at 80% 50%, rgba(60, 30, 50, 0.3) 0%, transparent 60%);
}
/* ===== 主容器 - 16:9 比例约束 ===== */
.container {
max-width: 1280px;
width: 100%;
aspect-ratio: 16 / 9;
background: rgba(18, 22, 28, 0.85);
backdrop-filter: blur(16px);
-webkit-backdrop-filter: blur(16px);
border-radius: 40px;
padding: 48px 56px;
border: 1px solid rgba(255, 255, 255, 0.06);
box-shadow: 0 30px 80px rgba(0, 0, 0, 0.8), inset 0 1px 0 rgba(255, 255, 255, 0.05);
display: flex;
flex-direction: column;
overflow-y: auto;
}
/* ===== 滚动条美化 ===== */
.container::-webkit-scrollbar {
width: 4px;
}
.container::-webkit-scrollbar-track {
background: transparent;
}
.container::-webkit-scrollbar-thumb {
background: rgba(255, 255, 255, 0.15);
border-radius: 10px;
}
/* ===== 顶部导航 / 品牌 ===== */
.header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 36px;
flex-shrink: 0;
}
.brand {
display: flex;
align-items: center;
gap: 12px;
}
.brand-icon {
width: 40px;
height: 40px;
background: linear-gradient(135deg, #6C5CE7, #a855f7);
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
font-size: 20px;
font-weight: 700;
color: #fff;
}
.brand h1 {
font-size: 22px;
font-weight: 600;
color: #ffffff;
letter-spacing: -0.3px;
}
.brand h1 span {
color: #a78bfa;
font-weight: 400;
}
.badge {
font-size: 12px;
font-weight: 500;
color: rgba(255, 255, 255, 0.4);
background: rgba(255, 255, 255, 0.06);
padding: 6px 16px;
border-radius: 100px;
border: 1px solid rgba(255, 255, 255, 0.06);
letter-spacing: 0.3px;
}
/* ===== CSS Grid 核心布局:左(输入) + 右(输出) ===== */
.main-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 40px;
flex: 1;
min-height: 0;
}
/* ===== 左卡片:输入区 ===== */
.input-card {
background: rgba(255, 255, 255, 0.03);
border-radius: 24px;
padding: 32px;
border: 1px solid rgba(255, 255, 255, 0.06);
display: flex;
flex-direction: column;
transition: border-color 0.3s ease;
}
.input-card:focus-within {
border-color: rgba(167, 139, 250, 0.3);
}
.input-card label {
font-size: 13px;
font-weight: 600;
color: rgba(255, 255, 255, 0.5);
text-transform: uppercase;
letter-spacing: 0.8px;
margin-bottom: 12px;
}
.input-card textarea {
flex: 1;
background: rgba(255, 255, 255, 0.04);
border: 1px solid rgba(255, 255, 255, 0.08);
border-radius: 16px;
padding: 20px;
font-family: 'Inter', sans-serif;
font-size: 16px;
line-height: 1.7;
color: #e8edf5;
resize: none;
outline: none;
transition: all 0.3s ease;
min-height: 140px;
}
.input-card textarea::placeholder {
color: rgba(255, 255, 255, 0.2);
font-weight: 400;
}
.input-card textarea:focus {
border-color: rgba(167, 139, 250, 0.4);
background: rgba(255, 255, 255, 0.06);
box-shadow: 0 0 0 4px rgba(167, 139, 250, 0.05);
}
/* ===== 提示词示例快速填充 ===== */
.prompt-examples {
display: flex;
gap: 8px;
flex-wrap: wrap;
margin: 16px 0 20px 0;
}
.prompt-examples button {
background: rgba(255, 255, 255, 0.05);
border: 1px solid rgba(255, 255, 255, 0.06);
border-radius: 100px;
padding: 6px 16px;
font-size: 12px;
font-family: 'Inter', sans-serif;
color: rgba(255, 255, 255, 0.5);
cursor: pointer;
transition: all 0.2s ease;
font-weight: 500;
}
.prompt-examples button:hover {
background: rgba(167, 139, 250, 0.15);
color: #c4b5fd;
border-color: rgba(167, 139, 250, 0.2);
}
/* ===== 生成按钮 ===== */
.generate-btn {
width: 100%;
padding: 16px 24px;
background: linear-gradient(135deg, #6C5CE7, #8b5cf6);
border: none;
border-radius: 16px;
font-family: 'Inter', sans-serif;
font-size: 16px;
font-weight: 600;
color: #ffffff;
cursor: pointer;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
letter-spacing: 0.3px;
position: relative;
overflow: hidden;
margin-top: auto;
}
.generate-btn:hover {
transform: translateY(-2px);
box-shadow: 0 12px 40px rgba(107, 92, 231, 0.35);
}
.generate-btn:active {
transform: translateY(0px);
box-shadow: 0 4px 20px rgba(107, 92, 231, 0.2);
}
.generate-btn:disabled {
opacity: 0.5;
cursor: not-allowed;
transform: none !important;
box-shadow: none !important;
}
/* ===== 右卡片:输出区 ===== */
.output-card {
background: rgba(255, 255, 255, 0.03);
border-radius: 24px;
border: 1px solid rgba(255, 255, 255, 0.06);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 24px;
position: relative;
min-height: 300px;
overflow: hidden;
}
.output-card .placeholder {
color: rgba(255, 255, 255, 0.12);
font-size: 14px;
font-weight: 500;
letter-spacing: 0.5px;
text-align: center;
line-height: 1.8;
}
.output-card .placeholder .icon {
font-size: 48px;
display: block;
margin-bottom: 16px;
opacity: 0.3;
}
#result-image {
max-width: 100%;
max-height: 100%;
border-radius: 16px;
display: none;
object-fit: contain;
box-shadow: 0 8px 40px rgba(0, 0, 0, 0.6);
transition: opacity 0.6s ease;
}
#result-image.visible {
display: block;
animation: fadeIn 0.6s ease;
}
@keyframes fadeIn {
0% { opacity: 0; transform: scale(0.96); }
100% { opacity: 1; transform: scale(1); }
}
/* ===== 状态提示 ===== */
#status {
margin-top: 16px;
font-size: 13px;
font-weight: 500;
color: rgba(255, 255, 255, 0.3);
text-align: center;
transition: all 0.3s ease;
font-family: 'JetBrains Mono', monospace;
min-height: 24px;
}
#status.loading {
color: #a78bfa;
}
#status.success {
color: #34d399;
}
#status.error {
color: #f87171;
}
/* ===== 响应式:平板 ===== */
@media (max-width: 1024px) {
.container {
aspect-ratio: auto;
padding: 32px 28px;
border-radius: 28px;
}
.main-grid {
grid-template-columns: 1fr;
gap: 28px;
}
.input-card textarea {
min-height: 100px;
}
}
/* ===== 响应式:手机 ===== */
@media (max-width: 640px) {
body {
padding: 16px;
}
.container {
padding: 24px 16px;
border-radius: 20px;
}
.header {
flex-direction: column;
align-items: flex-start;
gap: 12px;
margin-bottom: 24px;
}
.brand h1 {
font-size: 18px;
}
.input-card {
padding: 20px;
}
.input-card textarea {
font-size: 14px;
padding: 14px;
min-height: 80px;
}
.generate-btn {
padding: 14px 20px;
font-size: 14px;
}
.badge {
font-size: 10px;
padding: 4px 12px;
}
}
</style>
</head>
<body>
<div class="container">
<!-- ===== 头部 ===== -->
<header class="header">
<div class="brand">
<div class="brand-icon">✦</div>
<h1>Flux <span>· 真实感</span></h1>
</div>
<span class="badge">Hugging Face · XLabs-AI</span>
</header>
<!-- ===== 主区域 Grid ===== -->
<div class="main-grid">
<!-- 左:输入卡片 -->
<div class="input-card">
<label for="prompt">提示词</label>
<textarea id="prompt" placeholder="描述你想要的真实世界画面… 例如:A photorealistic cat sitting on a wooden table, soft lighting, 8k">A photorealistic orange tabby cat sitting on a rustic wooden table, soft sunlight streaming through a window, cinematic lighting, shallow depth of field, highly detailed, 8k, national geographic style</textarea>
<!-- 快速示例 -->
<div class="prompt-examples">
<button data-prompt="A photorealistic Japanese street at night, neon lights reflecting on wet pavement, cinematic, 8k, ultra detailed">🌃 雨夜街头</button>
<button data-prompt="A photorealistic close-up portrait of a young woman with freckles, natural sunlight, shallow depth of field, sharp focus, 8k, shot on Canon EOS R5">👩 人像特写</button>
<button data-prompt="A photorealistic macro shot of a dew-covered rose petal, morning light, bokeh background, hyper-detailed, 8k, nature photography">🌹 微距花卉</button>
</div>
<button class="generate-btn" id="generateBtn" onclick="generateImage()">✦ 生成图像</button>
</div>
<!-- 右:输出卡片 -->
<div class="output-card" id="outputCard">
<div class="placeholder" id="placeholder">
<span class="icon">🖼️</span>
输入提示词,点击生成<br />
<span style="font-size:12px;opacity:0.5;">Flux 真实感模型 · 约 10–30 秒</span>
</div>
<img id="result-image" alt="生成的图像" />
<div id="status">就绪</div>
</div>
</div>
</div>
<!-- ===== JavaScript ===== -->
<script>
// 快速填充示例
document.querySelectorAll('.prompt-examples button').forEach(btn => {
btn.addEventListener('click', function() {
document.getElementById('prompt').value = this.dataset.prompt;
});
});
async function generateImage() {
const prompt = document.getElementById('prompt');
const btn = document.getElementById('generateBtn');
const img = document.getElementById('result-image');
const placeholder = document.getElementById('placeholder');
const status = document.getElementById('status');
const text = prompt.value.trim();
if (!text) {
alert('请先输入一段提示词!');
return;
}
// UI 状态:加载中
btn.disabled = true;
btn.textContent = '⏳ 生成中...';
status.textContent = '⏳ 正在请求 AI 模型…';
status.className = 'loading';
img.className = '';
img.style.display = 'none';
placeholder.style.display = 'block';
try {
const response = await fetch('/generate', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ prompt: text })
});
const data = await response.json();
if (!response.ok || data.error) {
throw new Error(data.error || '服务器处理失败');
}
// 成功:显示图片
img.src = 'data:image/png;base64,' + data.image;
img.style.display = 'block';
img.className = 'visible';
placeholder.style.display = 'none';
status.textContent = '✅ 生成成功!';
status.className = 'success';
} catch (error) {
status.textContent = '❌ ' + error.message;
status.className = 'error';
img.style.display = 'none';
placeholder.style.display = 'block';
} finally {
btn.disabled = false;
btn.textContent = '✦ 生成图像';
}
}
// 回车快捷键(Ctrl+Enter 生成)
document.getElementById('prompt').addEventListener('keydown', function(e) {
if (e.ctrlKey && e.key === 'Enter') {
e.preventDefault();
generateImage();
}
});
</script>
</body>
</html>
'''
# ==================== 第5步:后端接口 ====================
@app.route('/generate', methods=['POST'])
def generate():
data = request.get_json()
user_prompt = data.get('prompt', '').strip()
if not user_prompt:
return jsonify({'error': '提示词不能为空'}), 400
try:
print(f"📡 正在请求 AI 模型,提示词为: {user_prompt}")
image: Image.Image = client.text_to_image(user_prompt, model=MODEL_ID)
buffered = io.BytesIO()
image.save(buffered, format="PNG")
img_base64 = base64.b64encode(buffered.getvalue()).decode('utf-8')
return jsonify({'image': img_base64})
except Exception as e:
print(f"🔥 API 调用异常: {e}")
return jsonify({'error': f'AI 服务异常: {str(e)}'}), 500
# ==================== 第6步:启动服务 ====================
if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0', port=5000)
1.3 截图
- 运行记录

- 前端页面



1.4 提示词
增量修饰实现具体化迭代
- 内容:主体+环境+细节(材质)
- 形式:规格+风格+效果(光照)
1.5 总结
熟悉了 huggingface 模型 API 调用的流程,额度与账号注册限制增加了完成作业的不确定性。此外,前后端代码实现门槛较高,需要大量依赖 AI
2. 个人主页搭建
前往
3. 自我评估
3.1 已具备的专业知识和能力
| 类型 | 具体(程度) |
|---|---|
| 基础理论 | 数据结构与算法、计算机组成原理、计算机网络、操作系统、计算机图形学 |
| 编程语言 | C/C++ (进阶 - 竞赛)、C# (基础 - unity)、Python (基础)、Shaderlab / HLSL (入门) |
| 工具环境 | Linux / Git (服务器)、Unity、DCC (PS / Blender / 3dsMax) |
| AI 应用 | 提示词工程、Agent部署(ClaudeCode+Deepseek) |
3.2 感兴趣的技术方向
- 技术美术
- 计算机动画与游戏设计
- 全栈开发
3.3 目前欠缺的能力
| 能力 | 具体 |
|---|---|
| 系统化软件开发 | 参与完整软件工程生命周期 |
| 后端开发技术 | Spring Boot、Django 等主流框架 |
| 前端工程化 | HTML/CSS/JavaScript 外,React/Vue 等主流框架 |
| 数据库设计 | SQL 操作,数据库设计与优化 |
| 软件测试与质量保障 | 测试理论与工具 |
| 设计模式与架构设计 | 设计方法论 |
| 团队协作与项目管理 | 多人协作开发 |
- 软件开发有关代码界定模糊,总代码量不便统计,只讨论编程代码目前约一万行。截至目前所有课程缺少系统学习软件开发编程,且对开发过程代码增量暂无概念,借助 AI 的非个人编程代码量无参考价值,只能说明构建了链条,故不做预期。
- 对于课程期望,希望能完备开发理论、熟悉开发全程、培养开发思维、锻炼架构能力,同步推进学习开发工具
4、课程学习规划
理论:过程框架(沟通→策划→建模→构建→部署)、需求工程、设计原则(抽象/模块化/信息隐藏/耦合与内聚)、测试策略、质量保障、团队协作
一、认知框架
点击查看
1.1 软件工程的本质
核心:如何将模糊的用户需求,经过系统化的分析、设计、实现和验证,转化为可运行、可维护、可扩展的软件产品。
1.2 生命周期模型
| 模型 | 核心思想 | 适用场景 | 课程项目建议 |
|---|---|---|---|
| 瀑布模型 | 阶段线性推进,每阶段有明确产出 | 需求稳定、规模可控 | 理解其“阶段划分”思想即可 |
| 敏捷开发 | 迭代增量,快速响应变化 | 需求不确定、需要快速交付 | 推荐采用:适合课程项目节奏 |
| 螺旋模型 | 迭代+风险驱动 | 大型高风险项目 | 理解其“风险优先”思想 |
理论“过程框架将软件工程活动归纳为沟通、策划、建模、构建、部署五个大类。敏捷开发是这一框架在“快速迭代”场景下的具体实践。
1.3 三要素框架
每个开发阶段都包含三个维度:
| 维度 | 含义 | 举例(以需求分析为例) |
|---|---|---|
| 过程 | 要做哪些事、产出什么 | 需求获取→分析→建模→验证→SRS文档 |
| 方法 | 用什么方法论指导 | 用例驱动分析、用户故事 |
| 工具 | 用什么工具辅助 | Visual Paradigm、Draw.io |
1.4 课程知识地图
软件工程课程
├── 需求工程 ──────── 需求获取、分析、建模、验证
├── 软件设计 ──────── 架构设计、模块划分、接口设计、数据库设计
├── 编码实现 ──────── 编码规范、版本控制、代码审查
├── 软件测试 ──────── 单元测试、集成测试、系统测试、验收测试
├── 项目管理 ──────── 进度管理、风险管理、团队协作
└── 质量保障 ──────── 质量模型、评审、度量
1.5 学习路径设计原则
- 整体优先:先理解全链条,再深入各阶段细节
- 项目驱动:每学一个阶段,即在团队项目中实践对应内容
- 理论-实践循环:课堂学理论 → 项目做实践 → 复盘提炼认知
二、五阶段详解
点击查看
阶段一:需求分析
| 维度 | 内容 |
|---|---|
| 是什么 | 将“用户想要什么”转化为“开发者能理解的、无歧义的规范描述”。核心产出:《软件需求规格说明书》(SRS)。 |
| 为什么 | 大量项目失败的根本原因不是技术不行,而是需求从一开始就理解错了。需求阶段修正问题的成本是编码阶段的1/10。 |
| 怎么做 | ① 需求获取:访谈、问卷、原型演示 ② 需求分析:区分功能性需求与非功能性需求 ③ 需求建模:用例图、活动图、用户故事 ④ 需求验证:与用户确认 ⑤ 编写SRS |
| 核心方法 | 用例驱动分析(适合交互型系统)、用户故事(适合敏捷场景)、领域建模(适合复杂业务) |
| 主流工具 | Visual Paradigm(UML建模)、Draw.io(轻量绘图)、Figma(原型设计) |
| 课程关联 | 软件工程“需求工程”章节;配套SRS编写实验 |
| 实践任务 | 选取一个核心模块,完成:① 用户故事 ② 用例图(≥3个用例)③ 用例规约(前置条件/主流程/异常流程) |
理论:需求工程分为获取、分析、规约、验证、管理五个活动。需求分析的核心是搞清楚用户真正需要什么,而非用户说了什么。
阶段二:系统设计
| 维度 | 内容 |
|---|---|
| 是什么 | 将需求转化为可实施的技术方案。需求回答“做什么”,设计回答“怎么做”。核心产出:架构图、数据库设计、API规范。 |
| 为什么 | 设计决定了系统的架构质量。架构缺陷在后期修复的成本极高,甚至需要推倒重来。 |
| 怎么做 | ① 架构设计:选择架构模式 ② 模块划分:高内聚、低耦合 ③ 接口设计:REST API规范 ④ 数据库设计:E-R图、表结构 ⑤ UI/UX设计 |
| 架构模式 | 分层架构(MVC) :表现层/业务逻辑层/数据访问层,适合中小型项目, 课程项目首选 微服务架构:按业务拆分独立服务,适合大型系统,理解思想即可 事件驱动架构:消息队列解耦,适合异步场景,可用于通知等辅助模块 |
| 主流工具 | MySQL Workbench(数据库设计)、Swagger/OpenAPI(接口设计)、C4 Model + Structurizr(架构描述) |
| 课程关联 | 软件工程“软件设计”章节;数据库系统原理“数据库设计”实验 |
| 实践任务 | ① 画三层架构图 ② MySQL Workbench设计≥3张核心表+E-R图 ③ Swagger定义≥5个REST API |
理论回扣:设计概念包括抽象、模块化、信息隐藏、耦合与内聚。好的设计是让修改一个功能时,不需要改动其他功能。
阶段三:编码实现
| 维度 | 内容 |
|---|---|
| 是什么 | 将设计方案转化为可运行代码。不只是实现功能,还包括遵循编码规范、编写单元测试、进行代码审查、使用版本控制。 |
| 为什么 | 编码是设计的具体化。没有规范的编码,代码将难以维护、难以协作、难以扩展。 |
| 怎么做 | ① 搭建开发环境 ② 按模块编码 ③ 遵循代码规范 ④ Git版本管理(小步提交、频繁集成)⑤ 编写单元测试 |
| 主流工具 | VS Code / PyCharm / IntelliJ IDEA(IDE)、Postman/Apifox(API调试)、DBeaver/Navicat(数据库管理)、Git/GitHub(版本控制) |
技术栈选择(决策框架)
前端技术栈:
基础层 生产层
├── HTML(结构) ├── Vue 3 + TypeScript
├── CSS(表现) ├── React + TypeScript
└── JavaScript(行为) └── Element Plus / Ant Design
说明:HTML/CSS/JavaScript是前端的基础层,Vue/React是构建在基础层之上的效率工。课程项目推荐 Vue 3 + TypeScript + Element Plus——学习曲线平缓,组件丰富,适合快速构建界面。
后端语言选择:
| 语言 | 框架 | 优势 |
|---|---|---|
| **JavaScript / TypeScript | Express / NestJS / Fastify | 前后端同语言,npm生态庞大,适合I/O密集、实时应用、API服务 |
| Java | Spring Boot | 行业主流,生态成熟,就业面广 |
| C# | ASP.NET Core | 与Unity C#经验衔接 |
| Python | FastAPI / Django | 推荐:上手快,与AI结合好 |
AI辅助编码
| 工具 | 用途 | 推荐场景 |
|---|---|---|
| GitHub Copilot | 代码补全、多文件重构 | 日常编码 |
| Cursor | AI驱动的代码编辑 | 复杂重构 |
| Claude Code | 任务级智能体,读取整个代码库 | 多步修改、测试生成 |
| 课程关联 | 面向对象程序设计、高级语言程序设计、数据结构与算法 |
| 实践任务 | ① 搭建项目基础框架 ② 实现≥1个端到端功能 ③ Git提交≥20次有意义的commit |
理论:代码规范是团队协作的基础。编码规范、代码审查、单元测试是保证代码质量的三道防线。
阶段四:测试验证
| 维度 | 内容 |
|---|---|
| 是什么 | 发现系统缺陷,验证系统是否满足需求,建立对软件质量的信心。测试不是“开发完之后随便点一点”,而是有策略、有层次、有工具支撑的系统化过程。 |
| 为什么 | 质量是构建出来的,不是测试出来的。但测试是验证质量是否达标的关键手段。 |
| 怎么做 | ① 单元测试:单个函数/方法 ② 集成测试:模块间接口 ③ 系统测试:端到端功能 ④ 验收测试:是否满足用户需求 |
| 测试层次 | 单元测试(pytest/Jest/JUnit)→ 集成测试(Testcontainers/Mockito)→ 系统测试(Playwright/Cypress)→ 验收测试(手工+自动化) |
| AI辅助测试 | GitHub Copilot Testing(直接生成单元测试)、code-testing-generator(多语言测试生成) |
| 课程关联 | 软件工程“软件测试”章节 |
| 实践任务 | ① 后端≥2个核心函数单元测试,覆盖率≥70% ② 前端≥1个端到端测试 ③ 记录≥2个缺陷及修复方案 |
理论:测试策略包括单元测试、集成测试、确认测试、系统测试。测试的目的是发现错误,而不是证明程序没有错误。
阶段五:部署与运维
| 维度 | 内容 |
|---|---|
| 是什么 | 将开发完成的软件发布到生产环境,确保运行稳定、高效。核心产出:可访问的线上系统。 |
| 为什么 | 软件的价值在于交付给用户使用。部署是软件从“代码”变为“产品”的关键环节。 |
| 怎么做 | ① 环境配置:服务器、依赖、环境变量 ② CI/CD:自动构建、测试、部署 ③ 容器化:Docker打包 ④ 监控与日志 |
| 主流工具 | GitHub Actions(CI/CD,采用率33%领先)、Docker + Kubernetes(容器化)、Jenkins(CI,28%)、GitLab CI/CD(19%) |
| 课程关联 | 计算机网络(HTTP协议、端口)、计算机操作系统(Linux命令、进程管理) |
| 实践任务 | ① 编写Dockerfile ② 配置GitHub Actions流水线 ③ 部署前端静态页面(GitHub Pages) |
理论:“部署”作为过程框架的最后一个活动。软件发布不是终点,而是运维的起点。
三、贯穿性主题
点击查看
3.1 团队协作与版本控制
| 实践 | 要点 |
|---|---|
| Git工作流 | 小步提交、频繁集成、分支管理(feature branch) |
| 代码审查 | 每次合并请求至少一人审查,关注逻辑、规范、安全 |
| 任务管理 | 明确分工,定期同步(每日站会/每周例会) |
| 文档同步 | 文档与代码同步更新,不是“做完再补” |
理论:“团队合作”列为软件工程的核心要素之一,团队协作的本质是降低沟通成本。
3.2 质量保障
| 层次 | 手段 |
|---|---|
| 代码质量 | 编码规范、静态分析、代码审查 |
| 测试质量 | 单元测试、集成测试、覆盖率度量 |
| 过程质量 | 里程碑评审、风险跟踪、持续改进 |
3.3 AI辅助开发
| 阶段 | AI用法 | 推荐工具 |
|---|---|---|
| 需求分析 | 分析访谈记录、生成用例图初稿 | Visual Paradigm AI、ChatGPT |
| 系统设计 | 辅助生成数据库表结构、API定义 | Cursor、Claude |
| 编码实现 | 代码补全、多文件重构、代码解释 | GitHub Copilot、Cursor、Claude Code |
| 测试验证 | 自动生成单元测试、测试套件 | GitHub Copilot Testing |
| 代码审查 | AI驱动的PR审查、安全扫描 | CodeRabbit、SonarQube |
| 部署运维 | 生成Dockerfile、CI/CD配置 | GitHub Copilot、Amazon Q Developer |
四、综合实践
点击查看
项目建议
项目名称:个人任务管理系统(To-Do List + 团队协作)
技术栈:Vue 3 + TypeScript(前端)/ Python FastAPI(后端)/ MySQL + Redis(数据层)/ Docker + GitHub Actions(部署)
周次安排
| 周次 | 阶段 | 具体任务 | 产出 |
|---|---|---|---|
| 第1-2周 | 需求分析 | 用户故事、用例图、SRS | SRS文档 + 用例图 |
| 第3-4周 | 系统设计 | 三层架构图、E-R图、REST API | 设计文档 + API规范 |
| 第5-9周 | 编码实现 | 前后端开发、Git管理、代码审查 | 可运行系统 |
| 第10-11周 | 测试验证 | 单元测试 + 端到端测试 | 测试报告 |
| 第12-14周 | 部署运维 | Docker容器化、CI/CD、上线 | 线上可访问系统 |
验收标准
- 系统完整运行,核心功能可用
- Git提交≥30次有意义的commit
- 单元测试覆盖率≥60%
- 完整项目文档(SRS + 设计文档 + API文档 + 测试报告)
- CI/CD流水线自动部署
附:博客园 Markdown 编辑器配置截图

浙公网安备 33010602011771号