Appearance
章节4:结业项目实战
学习目标
完成本章学习后,你将能够:
- 独立完成 B2C 电商平台的全栈开发(Vue3 + Django + DRF + MySQL + Redis + Docker)
- 独立完成企业 OA 办公管理系统的全栈开发
- 掌握大型项目的架构方法论、模块拆分与团队协作
- 完成从需求到上线的全流程实战
4.1 项目一:B2C 电商平台
4.1.1 项目概述
| 项目 | 说明 |
|---|---|
| 项目名称 | EShop —— B2C 电商平台 |
| 技术栈 | Vue3 + TypeScript + Element Plus + Django + DRF + MySQL + Redis + Docker |
| 目标用户 | 普通消费者 + 平台运营管理员 |
| 核心功能 | 用户系统、商品浏览搜索、购物车、下单支付、后台管理、数据统计 |
4.1.2 完整项目架构
bash
eshop/
├── frontend/ # 前端项目(Vue3 + TypeScript)
│ ├── public/
│ │ └── favicon.ico
│ ├── src/
│ │ ├── api/ # API 接口层
│ │ │ ├── request.ts # Axios 实例(拦截器/Token/错误处理)
│ │ │ ├── user.ts # 用户相关接口
│ │ │ ├── product.ts # 商品相关接口
│ │ │ ├── cart.ts # 购物车接口
│ │ │ ├── order.ts # 订单接口
│ │ │ ├── payment.ts # 支付接口
│ │ │ └── admin.ts # 后台管理接口
│ │ ├── assets/ # 静态资源(样式/图片/图标)
│ │ │ ├── styles/
│ │ │ │ ├── global.scss # 全局样式
│ │ │ │ ├── variables.scss # SCSS 变量
│ │ │ │ └── mixins.scss # SCSS 混入
│ │ │ └── images/
│ │ ├── components/ # 公共组件
│ │ │ ├── AppHeader.vue # 顶部导航栏
│ │ │ ├── AppFooter.vue # 底部信息
│ │ │ ├── ProductCard.vue # 商品卡片
│ │ │ ├── CategoryMenu.vue # 分类菜单
│ │ │ ├── SearchBar.vue # 搜索栏
│ │ │ ├── Loading.vue # 加载状态
│ │ │ └── EmptyState.vue # 空状态占位
│ │ ├── composables/ # 组合式函数(Composables)
│ │ │ ├── useAuth.ts # 认证状态
│ │ │ ├── useCart.ts # 购物车逻辑
│ │ │ ├── usePagination.ts # 分页逻辑
│ │ │ └── usePermission.ts # 权限检查
│ │ ├── layouts/ # 布局组件
│ │ │ ├── MainLayout.vue # 前台主布局
│ │ │ ├── AdminLayout.vue # 后台管理布局
│ │ │ └── AuthLayout.vue # 登录注册布局
│ │ ├── router/ # 路由配置
│ │ │ ├── index.ts # 路由实例
│ │ │ ├── routes.ts # 路由表
│ │ │ └── guards.ts # 路由守卫(鉴权/重定向)
│ │ ├── stores/ # Pinia 状态管理
│ │ │ ├── user.ts # 用户状态
│ │ │ ├── cart.ts # 购物车状态
│ │ │ └── app.ts # 应用级状态
│ │ ├── types/ # TypeScript 类型定义
│ │ │ ├── user.d.ts
│ │ │ ├── product.d.ts
│ │ │ ├── order.d.ts
│ │ │ └── api.d.ts # 统一响应类型
│ │ ├── utils/ # 工具函数
│ │ │ ├── format.ts # 格式化(金额/时间)
│ │ │ ├── storage.ts # 本地存储封装
│ │ │ └── validate.ts # 表单校验
│ │ ├── views/ # 页面组件
│ │ │ ├── home/ # 首页
│ │ │ │ ├── HomeView.vue
│ │ │ │ └── components/
│ │ │ │ ├── BannerCarousel.vue # 轮播图
│ │ │ │ ├── HotProducts.vue # 热销商品
│ │ │ │ └── NewArrivals.vue # 新品上架
│ │ │ ├── product/ # 商品
│ │ │ │ ├── ListView.vue # 商品列表页
│ │ │ │ ├── DetailView.vue # 商品详情页
│ │ │ │ └── components/
│ │ │ │ ├── ProductFilter.vue # 筛选面板
│ │ │ │ ├── ProductGallery.vue # 商品图库
│ │ │ │ └── ProductReviews.vue # 用户评价
│ │ │ ├── cart/ # 购物车
│ │ │ │ ├── CartView.vue
│ │ │ │ └── components/
│ │ │ │ └── CartItem.vue # 购物车项
│ │ │ ├── order/ # 订单
│ │ │ │ ├── ConfirmView.vue # 确认订单
│ │ │ │ ├── ListView.vue # 订单列表
│ │ │ │ ├── DetailView.vue # 订单详情
│ │ │ │ └── components/
│ │ │ │ └── OrderStatus.vue # 状态时间线
│ │ │ ├── payment/ # 支付
│ │ │ │ └── PayView.vue # 支付页面
│ │ │ ├── user/ # 用户
│ │ │ │ ├── LoginView.vue
│ │ │ │ ├── RegisterView.vue
│ │ │ │ ├── ProfileView.vue
│ │ │ │ └── AddressView.vue
│ │ │ └── admin/ # 后台管理
│ │ │ ├── DashboardView.vue # 控制台
│ │ │ ├── ProductManage.vue # 商品管理
│ │ │ ├── OrderManage.vue # 订单管理
│ │ │ ├── UserManage.vue # 用户管理
│ │ │ └── StatsView.vue # 数据统计
│ │ ├── App.vue
│ │ └── main.ts
│ ├── .env.development # 开发环境变量
│ ├── .env.production # 生产环境变量
│ ├── .eslintrc.cjs
│ ├── tsconfig.json
│ ├── vite.config.ts
│ └── package.json
│
├── backend/ # 后端项目(Django + DRF)
│ ├── apps/
│ │ ├── user/ # 用户模块
│ │ │ ├── __init__.py
│ │ │ ├── admin.py
│ │ │ ├── models.py # User / Address
│ │ │ ├── serializers.py # Register / Login / Profile
│ │ │ ├── views.py # RegisterView / LoginView / ProfileView
│ │ │ ├── urls.py
│ │ │ ├── permissions.py # IsOwnerOrAdmin
│ │ │ └── tests.py
│ │ ├── product/ # 商品模块
│ │ │ ├── __init__.py
│ │ │ ├── admin.py
│ │ │ ├── models.py # Category / Product / ProductImage
│ │ │ ├── serializers.py
│ │ │ ├── views.py # CategoryViewSet / ProductViewSet
│ │ │ ├── filters.py # 自定义过滤器
│ │ │ ├── urls.py
│ │ │ └── tests.py
│ │ ├── cart/ # 购物车模块
│ │ │ ├── __init__.py
│ │ │ ├── models.py # CartItem
│ │ │ ├── serializers.py
│ │ │ ├── views.py # CartViewSet
│ │ │ └── tests.py
│ │ ├── order/ # 订单模块
│ │ │ ├── __init__.py
│ │ │ ├── models.py # Order / OrderItem
│ │ │ ├── serializers.py
│ │ │ ├── views.py # OrderViewSet
│ │ │ ├── services.py # OrderService(下单事务逻辑)
│ │ │ ├── signals.py # 订单状态变更信号
│ │ │ ├── urls.py
│ │ │ └── tests.py
│ │ ├── payment/ # 支付模块
│ │ │ ├── __init__.py
│ │ │ ├── models.py # Payment
│ │ │ ├── services/
│ │ │ │ ├── alipay.py # 支付宝SDK封装
│ │ │ │ └── wechat.py # 微信支付SDK封装
│ │ │ ├── views.py # PayView / AlipayNotifyView
│ │ │ ├── urls.py
│ │ │ └── tests.py
│ │ └── admin/ # 后台管理模块
│ │ ├── __init__.py
│ │ ├── views.py # StatsView / DashboardView
│ │ ├── serializers.py
│ │ └── urls.py
│ ├── config/ # 项目配置
│ │ ├── __init__.py
│ │ ├── settings/
│ │ │ ├── base.py # 公共配置
│ │ │ ├── dev.py # 开发环境
│ │ │ └── prod.py # 生产环境
│ │ ├── urls.py # 根路由
│ │ ├── wsgi.py
│ │ ├── asgi.py
│ │ └── celery.py # Celery 配置
│ ├── utils/ # 公共工具
│ │ ├── exceptions.py # 自定义异常
│ │ ├── middleware.py # 自定义中间件
│ │ ├── pagination.py # 分页
│ │ ├── response.py # 统一响应
│ │ └── cache.py # Redis 缓存工具
│ ├── scripts/ # 管理脚本
│ │ ├── init_data.py # 初始化测试数据
│ │ └── seed.py # 种子数据
│ ├── Dockerfile
│ ├── manage.py
│ ├── requirements.txt
│ ├── .pylintrc
│ └── gunicorn.conf.py
│
├── nginx/
│ └── nginx.conf # Nginx 反向代理配置
├── docker-compose.yml # 容器编排
├── .env # 环境变量(不提交 Git)
├── .env.example # 环境变量模板
├── .gitignore
├── README.md # 项目说明文档
└── locustfile.py # 性能压测4.1.3 数据库 E-R 总图
┌───────────┐ ┌──────────────┐ ┌──────────────┐
│ User │1──N │ CartItem │1──1 │ Product │
└───────────┘ └──────────────┘ └──────────────┘
│ │
│1 │N
│ │
│ ┌───────────┐ ┌──────────────┐ │
├──N│ Address │ │ OrderItem │N│
│ └───────────┘ └──────┬───────┘ │
│ │ │
│1 │N │
├────────────────────────────┤ │
│ │ │
│ ┌───────────┐ │ │
└──N│ Order │1──────────N┘ │
└─────┬─────┘ │
│1 │
│ │
┌─────┴─────┐ ┌───────┴──────┐
│ Payment │ │ Category │
└───────────┘ └──────────────┘
│
1─────N─────┐
│ │
┌────┴──────┐
│ Product │
└───────────┘4.1.4 核心业务流程
┌──────────────────────────────────────────────────────────────┐
│ 用户购物完整流程 │
│ │
│ ① 注册登录 ──→ ② 浏览商品 ──→ ③ 加入购物车 │
│ │ │
│ ▼ │
│ ④ 选择地址 ──→ ⑤ 确认下单 ──→ ⑥ 选择支付方式 │
│ │ │
│ ▼ │
│ ⑦ 扫码支付 ──→ ⑧ 支付回调 ──→ ⑨ 查看订单状态 │
│ │ │
│ ▼ │
│ ⑩ 确认收货 ──→ ⑪ 评价商品 ──→ 完成 │
└──────────────────────────────────────────────────────────────┘4.1.5 技术亮点总结
| 模块 | 技术亮点 |
|---|---|
| 前端 | Composition API + TypeScript、Pinia 状态管理、路由守卫鉴权、Axios 拦截器统一错误处理 |
| 后端 | DRF ViewSet + Serializer、JWT 无状态认证、RBAC 权限控制、django-filter 动态筛选 |
| 数据库 | MySQL 8.0 + utf8mb4、外键与索引优化、Fulltext 全文索引、事务原子性下单 |
| 缓存 | Redis 缓存热门商品/分类树、Session 替代、Celery 异步任务(短信/邮件) |
| 部署 | Docker 多阶段构建、Nginx 动静分离、Gunicorn + Gevent 高性能部署 |
4.2 项目二:企业 OA 办公管理系统
4.2.1 项目概述
| 项目 | 说明 |
|---|---|
| 项目名称 | EasyOA —— 企业办公管理系统 |
| 技术栈 | Vue3 + Element Plus + Django + DRF + MySQL + Redis + Docker |
| 目标用户 | 企业员工、部门主管、系统管理员 |
| 核心功能 | 组织架构管理、考勤打卡、审批流程、公告通知、日程管理 |
4.2.2 完整项目架构
bash
easyoa/
├── frontend/
│ ├── src/
│ │ ├── api/
│ │ │ ├── request.ts
│ │ │ ├── auth.ts # 认证
│ │ │ ├── department.ts # 部门
│ │ │ ├── employee.ts # 员工
│ │ │ ├── attendance.ts # 考勤
│ │ │ ├── approval.ts # 审批
│ │ │ ├── notice.ts # 公告
│ │ │ └── schedule.ts # 日程
│ │ ├── components/
│ │ │ ├── OrgTree.vue # 组织架构树
│ │ │ ├── ApprovalTimeline.vue # 审批时间线
│ │ │ ├── CalendarView.vue # 日历组件
│ │ │ └── FileUploader.vue # 文件上传
│ │ ├── views/
│ │ │ ├── dashboard/ # 工作台
│ │ │ ├── organization/ # 组织架构
│ │ │ ├── attendance/ # 考勤管理
│ │ │ ├── approval/ # 审批中心
│ │ │ ├── notice/ # 公告管理
│ │ │ └── system/ # 系统设置
│ │ └── ...
│ └── Dockerfile
│
├── backend/
│ ├── apps/
│ │ ├── organization/ # 组织架构模块
│ │ │ ├── models.py # Department / Employee
│ │ │ ├── views.py # DepartmentViewSet / EmployeeViewSet
│ │ │ └── serializers.py
│ │ ├── attendance/ # 考勤模块
│ │ │ ├── models.py # AttendanceRecord / LeaveRequest
│ │ │ ├── views.py
│ │ │ └── serializers.py
│ │ ├── approval/ # 审批模块
│ │ │ ├── models.py # ApprovalRequest / ApprovalNode
│ │ │ ├── views.py
│ │ │ └── serializers.py
│ │ ├── notice/ # 公告模块
│ │ │ ├── models.py # Notice
│ │ │ ├── views.py
│ │ │ └── serializers.py
│ │ └── system/ # 系统管理
│ │ ├── models.py # SystemConfig / OperationLog
│ │ ├── views.py
│ │ └── serializers.py
│ └── ...
├── docker-compose.yml
└── README.md4.2.3 OA 核心数据模型
python
# ===== 组织架构 =====
class Department(models.Model):
name = models.CharField(max_length=64, verbose_name="部门名称")
parent = models.ForeignKey(
'self', on_delete=models.CASCADE, null=True, blank=True,
related_name='children'
)
manager = models.ForeignKey(
'Employee', on_delete=models.SET_NULL, null=True, blank=True,
related_name='managed_dept', verbose_name="部门负责人"
)
sort_order = models.IntegerField(default=0)
class Meta:
db_table = 'oa_department'
class Employee(models.Model):
"""员工信息(继承 User 或一对一关联)"""
user = models.OneToOneField('user.User', on_delete=models.CASCADE)
department = models.ForeignKey(
Department, on_delete=models.CASCADE, related_name='employees'
)
position = models.CharField(max_length=64, verbose_name="职位")
employee_no = models.CharField(max_length=32, unique=True, verbose_name="工号")
hire_date = models.DateField(verbose_name="入职日期")
is_active = models.BooleanField(default=True)
# ===== 考勤 =====
class AttendanceRecord(models.Model):
employee = models.ForeignKey(Employee, on_delete=models.CASCADE)
date = models.DateField(auto_now_add=True)
check_in_time = models.DateTimeField(null=True, blank=True, verbose_name="上班打卡")
check_out_time = models.DateTimeField(null=True, blank=True, verbose_name="下班打卡")
status = models.CharField(max_length=20, choices=[
('normal', '正常'), ('late', '迟到'),
('early', '早退'), ('absent', '缺勤'),
], default='normal')
# ===== 审批流程 =====
class ApprovalRequest(models.Model):
"""审批请求"""
employee = models.ForeignKey(Employee, on_delete=models.CASCADE, verbose_name="申请人")
category = models.CharField(max_length=32, choices=[
('leave', '请假'), ('expense', '报销'),
('purchase', '采购'), ('overtime', '加班'),
])
title = models.CharField(max_length=256)
content = models.JSONField(verbose_name="申请内容(根据类型不同)")
status = models.CharField(max_length=20, choices=[
('pending', '审批中'), ('approved', '已通过'),
('rejected', '已驳回'), ('cancelled', '已撤回'),
], default='pending')
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
db_table = 'oa_approval_request'
class ApprovalNode(models.Model):
"""审批节点(支持多级审批)"""
request = models.ForeignKey(
ApprovalRequest, on_delete=models.CASCADE, related_name='nodes'
)
reviewer = models.ForeignKey(Employee, on_delete=models.CASCADE, verbose_name="审批人")
level = models.IntegerField(default=1, verbose_name="审批层级")
status = models.CharField(max_length=20, choices=[
('pending', '待审批'), ('approved', '已通过'), ('rejected', '已驳回')
], default='pending')
comment = models.TextField(blank=True, verbose_name="审批意见")
reviewed_at = models.DateTimeField(null=True, blank=True)4.2.4 OA 审批流程状态机
请假申请 ──→ 主管审批 ──→ 经理审批 ──→ 人事归档
│ │
├── 驳回 ──→ 结束 └── 完成
│
└── 一级通过 ──→ 二级审批4.2.5 OA 系统前端示例
vue
<!-- frontend/src/views/approval/ApprovalDetail.vue -->
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { useRoute } from 'vue-router'
import { getApprovalDetail, approveRequest, rejectRequest } from '@/api/approval'
import { ElMessage, ElDescriptions } from 'element-plus'
const route = useRoute()
const detail = ref<any>(null)
const comment = ref('')
onMounted(async () => {
detail.value = await getApprovalDetail(route.params.id as string)
})
const handleApprove = async () => {
await approveRequest(detail.value.id, { comment: comment.value })
ElMessage.success('审批通过')
detail.value.status = 'approved'
}
const handleReject = async () => {
await rejectRequest(detail.value.id, { comment: comment.value })
ElMessage.success('已驳回')
detail.value.status = 'rejected'
}
</script>
<template>
<div v-if="detail" class="approval-detail">
<el-card>
<template #header>
<div class="card-header">
<span>{{ detail.title }}</span>
<el-tag
:type="detail.status === 'approved' ? 'success'
: detail.status === 'rejected' ? 'danger' : 'warning'"
>
{{ detail.status === 'pending' ? '审批中'
: detail.status === 'approved' ? '已通过'
: '已驳回' }}
</el-tag>
</div>
</template>
<el-descriptions :column="2" border>
<el-descriptions-item label="申请人">{{ detail.employee_name }}</el-descriptions-item>
<el-descriptions-item label="申请类型">{{ detail.category_label }}</el-descriptions-item>
<el-descriptions-item label="提交时间">{{ detail.created_at }}</el-descriptions-item>
<el-descriptions-item label="部门">{{ detail.department_name }}</el-descriptions-item>
</el-descriptions>
<div class="content-box" v-html="detail.content_html"></div>
</el-card>
<!-- 审批时间线 -->
<el-card style="margin-top: 16px">
<template #header><span>审批进度</span></template>
<el-timeline>
<el-timeline-item
v-for="node in detail.nodes" :key="node.id"
:timestamp="node.reviewed_at || '待审批'"
:type="node.status === 'approved' ? 'success'
: node.status === 'rejected' ? 'danger' : 'info'"
>
{{ node.reviewer_name }} ——
{{ node.status === 'pending' ? '待审批'
: node.status === 'approved' ? '已通过'
: '已驳回' }}
<p v-if="node.comment">{{ node.comment }}</p>
</el-timeline-item>
</el-timeline>
</el-card>
<!-- 审批操作 -->
<el-card v-if="detail.current_reviewer" style="margin-top: 16px">
<el-input v-model="comment" type="textarea" placeholder="审批意见(选填)" />
<div class="action-buttons">
<el-button type="primary" @click="handleApprove">通过</el-button>
<el-button type="danger" @click="handleReject">驳回</el-button>
</div>
</el-card>
</div>
</template>4.3 项目实战建议
4.3.1 开发流程
阶段一:需求分析(2天)
├── 梳理功能清单
├── 绘制原型图(Figma / 墨刀)
└── 编写 PRD 文档
阶段二:系统设计(3天)
├── 数据库 E-R 设计
├── 接口规范文档(Swagger / Apifox)
└── 项目目录初始化
阶段三:核心开发(14天)
├── 第1周:用户认证 + 商品管理(电商)/ 组织架构(OA)
├── 第2周:购物车/订单(电商)/ 审批流程(OA)
└── 第3天:支付集成 / 后台统计
阶段四:联调测试(3天)
├── 前后端接口联调
├── 功能回归测试
└── 编写单元测试
阶段五:部署上线(2天)
├── Docker 容器化
├── Nginx + HTTPS 配置
└── 监控与日志4.3.2 关键技术选型对比
| 场景 | 电商平台推荐 | OA 系统推荐 |
|---|---|---|
| 前端组件库 | Element Plus(表格/表单丰富) | Element Plus(树/时间线/日历) |
| 状态管理 | Pinia(购物车/用户状态) | Pinia(用户/应用配置) |
| 权限模型 | RBAC(角色-权限) | ABAC(属性-权限,更细粒度) |
| 缓存策略 | Redis 缓存热门商品/JWT | Redis 缓存组织结构树 |
| 异步任务 | Celery(订单超时/短信) | Celery(审批通知邮件) |
| 搜索 | 数据库 Fulltext / Elasticsearch | 数据库 LIKE 查询即可 |
| 文件存储 | 本地 / OSS 对象存储 | 本地 / MinIO |
4.3.3 数据统计看板
电商平台看板:
- 今日订单数、销售额、新增用户数
- 近 30 天销售趋势(折线图)
- 商品分类销售占比(饼图)
- 用户地域分布(中国地图)
- TOP10 热销商品(柱状图)
OA 系统看板:
- 今日出勤率
- 待审批单据数量
- 各部门人员分布
- 请假类型占比
4.4 学习资源推荐
4.4.1 官方文档
- Vue3: https://vuejs.org/guide/
- Django REST Framework: https://www.django-rest-framework.org/
- Element Plus: https://element-plus.org/
- Docker: https://docs.docker.com/
4.4.2 推荐阅读
- 《Vue.js 设计与实现》—— 霍春阳
- 《Django 企业开发实战》—— 胡阳
- 《高性能 MySQL》—— Baron Schwartz
小结
知识回顾
- B2C 电商平台:覆盖了用户、商品、购物车、订单、支付、后台管理六大核心模块,是典型的全栈实战项目
- 企业 OA 系统:组织架构树、考勤打卡、多级审批流程,侧重工作流引擎设计
- 项目架构方法论:模块化拆分、清晰的目录结构、分层架构(前端/API/业务/数据)
- 全流程实战:从需求分析到系统设计,从编码实现到部署上线,覆盖软件工程全生命周期
练习与思考
- 电商项目:为电商平台新增"优惠券/满减活动"模块,设计数据表及下单时的优惠计算逻辑
- OA 项目:为 OA 系统添加"会议室预约"功能,设计时间冲突检测算法
- 项目优化:针对电商平台的高并发场景(如秒杀),设计一种扣减库存的方案(Redis 预减 + 消息队列异步落地)
- 团队协作:假设你带领 4 人团队(2 前端 + 2 后端)开发电商项目,请画出 Git 分支策略和任务分解甘特图
- 结业思考:回顾本模块全部 4 章内容,写一份不少于 500 字的学习总结,包含你印象最深的技术点和遇到的难点及解决方案