一、项目简介
协同办公平台是企业内部常见的信息化系统,用来解决任务分派、进度跟踪、公告同步、制度文档沉淀等问题。本文实现一个可运行的 Python 全栈项目:后端使用 FastAPI 提供 RESTful API,数据库使用 SQLite,前端使用 Vue 3 + Vite 构建单页应用。
项目重点不是单一算法演示,而是一套完整的全栈闭环:用户注册、登录、Token 鉴权、任务看板、公告中心、知识文档、前后端接口联调和部署运行说明。
二、技术栈
| 层次 | 技术 |
|---|---|
| 后端框架 | FastAPI |
| 数据库 | SQLite |
| ORM | SQLAlchemy |
| 数据校验 | Pydantic |
| 认证鉴权 | passlib bcrypt 密码哈希 + python-jose JWT |
| 前端 | Vue 3 + Vite |
| 通信方式 | RESTful API + Bearer Token |
| 打包运行 | uvicorn、npm scripts |
三、系统架构
text
┌──────────────────────┐
│ Vue 3 + Vite 前端 │
│ 登录页/看板/公告/文档 │
└──────────┬───────────┘
│ HTTP + JSON + Bearer Token
┌──────────▼───────────┐
│ FastAPI 后端 │
│ Auth / Task / Notice │
│ Document API │
└──────────┬───────────┘
│ SQLAlchemy ORM
┌──────────▼───────────┐
│ SQLite office.db │
│ users/tasks/... │
└──────────────────────┘
前端负责界面渲染与登录状态管理;后端负责业务校验、密码哈希、JWT 签发和权限控制;SQLite 用于保存用户、任务、公告和文档数据。
四、功能模块
- 用户认证模块:注册、登录、获取当前用户、退出登录。
- 组织成员模块:登录后可查看平台成员,用于任务负责人选择。
- 任务协作模块:创建任务、按关键词查询、状态流转,任务仅对创建人和负责人可见。
- 公告模块:团队公告发布与列表展示。
- 知识文档模块:维护制度文档、项目说明、流程资料等。
- 前端鉴权模块:Token 持久化、自动带 Authorization 请求头、退出清理登录态。
五、数据库/数据模型设计
后端核心模型位于 backend/app/models.py。
1. 用户表 users
字段包括用户名、邮箱、姓名、部门、密码哈希、状态和创建时间。密码只保存哈希值,不保存明文。
python
class User(Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True, index=True)
username = Column(String(50), unique=True, index=True, nullable=False)
email = Column(String(120), unique=True, index=True, nullable=False)
hashed_password = Column(String(255), nullable=False)
full_name = Column(String(80), nullable=False)
department = Column(String(80), default="综合部")
2. 任务表 tasks
任务表记录任务标题、描述、状态、优先级、截止日期、创建人和负责人。
python
class Task(Base):
__tablename__ = "tasks"
id = Column(Integer, primary_key=True, index=True)
title = Column(String(120), nullable=False)
status = Column(String(20), default="待处理")
priority = Column(String(20), default="普通")
owner_id = Column(Integer, ForeignKey("users.id"), nullable=False)
assignee_id = Column(Integer, ForeignKey("users.id"), nullable=True)
3. 公告和文档表
announcements 用于保存公告标题、内容和作者;documents 用于保存文档名称、分类、摘要和正文。它们都通过外键关联用户。
六、后端接口设计
| 方法 | 路径 | 说明 | 是否鉴权 |
|---|---|---|---|
| GET | /api/health |
健康检查 | 否 |
| POST | /api/auth/register |
用户注册 | 否 |
| POST | /api/auth/login |
登录获取 Token | 否 |
| GET | /api/users/me |
当前用户信息 | 是 |
| GET | /api/users |
成员列表 | 是 |
| POST | /api/tasks |
创建任务 | 是 |
| GET | /api/tasks |
查询任务 | 是 |
| PUT | /api/tasks/{task_id} |
更新任务 | 是 |
| POST | /api/announcements |
发布公告 | 是 |
| GET | /api/announcements |
公告列表 | 是 |
| POST | /api/documents |
新增文档 | 是 |
| GET | /api/documents |
文档列表 | 是 |
鉴权依赖位于 main.py:
python
def get_current_user(token: str = Depends(oauth2_scheme), db: Session = Depends(get_db)):
username = decode_token(token)
if not username:
raise HTTPException(status_code=401, detail="登录已失效")
user = crud.get_user_by_username(db, username)
if not user or not user.is_active:
raise HTTPException(status_code=401, detail="用户不可用")
return user
七、前端页面设计
前端采用 Vue 3 单文件组件结构,核心文件如下:
text
frontend/src/main.js # 创建 Vue 应用
frontend/src/App.vue # 主界面与业务交互
frontend/src/api.js # API 封装与 Token 管理
frontend/src/style.css # 页面样式
页面分为两个状态:
- 未登录:展示登录/注册表单。
- 已登录:展示顶部用户信息、任务看板、公告中心、知识文档和创建表单。
API 封装会自动附加 Token:
javascript
if (token) headers.Authorization = `Bearer ${token}`
const res = await fetch(`${API_BASE}${path}`, { ...options, headers })
八、核心代码讲解
1. 密码哈希与 Token 生成
security.py 使用 passlib 对密码进行 bcrypt 哈希,使用 JWT 保存登录用户身份:
python
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
def get_password_hash(password: str) -> str:
return pwd_context.hash(password)
def create_access_token(data: dict, expires_delta: timedelta | None = None) -> str:
to_encode = data.copy()
expire = datetime.utcnow() + (expires_delta or timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES))
to_encode.update({"exp": expire})
return jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
2. 登录接口
登录接口使用 OAuth2PasswordRequestForm 接收用户名和密码,验证成功后返回 Bearer Token:
python
@app.post("/api/auth/login", response_model=schemas.Token)
def login(form: OAuth2PasswordRequestForm = Depends(), db: Session = Depends(get_db)):
user = crud.get_user_by_username(db, form.username)
if not user or not verify_password(form.password, user.hashed_password):
raise HTTPException(status_code=400, detail="用户名或密码错误")
token = create_access_token(data={"sub": user.username})
return {"access_token": token, "token_type": "bearer"}
3. 任务权限控制
任务查询只返回当前用户创建或分配给当前用户的任务,避免不同用户之间互相看到无关任务:
python
def list_tasks(db: Session, user_id: int, keyword: str = ""):
q = db.query(models.Task).filter(
or_(models.Task.owner_id == user_id, models.Task.assignee_id == user_id)
)
if keyword:
q = q.filter(models.Task.title.contains(keyword))
return q.order_by(models.Task.updated_at.desc()).all()
4. Vue 登录状态处理
前端登录成功后保存 Token,刷新页面时通过 /api/users/me 恢复用户状态:
javascript
export function setToken(value) {
token = value || ''
if (token) localStorage.setItem('office_token', token)
else localStorage.removeItem('office_token')
}
onMounted(async()=>{
if(getToken()){
try{ await bootstrap() }catch{ setToken('') }
}
})
九、部署与运行步骤
1. 启动后端
bash
cd project/backend
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
启动后访问:
- API 地址:
http://127.0.0.1:8000 - Swagger 文档:
http://127.0.0.1:8000/docs
2. 启动前端
bash
cd project/frontend
npm install
npm run dev
前端默认访问:http://127.0.0.1:5173。
3. 初始化使用
- 注册第一个用户,例如
admin / 123456。 - 登录后创建任务、公告、文档。
- 再注册一个普通成员,把任务分配给该成员。
- 普通成员登录后可以看到分配给自己的任务,并更新任务状态。
十、项目总结
本项目实现了一个完整的协同办公全栈应用,覆盖从数据模型、认证鉴权、业务接口到 Vue 前端页面的完整开发流程。它适合作为 Python 全栈项目练习模板,也可以继续扩展审批流、日程会议、文件上传、消息通知、角色权限等企业办公场景功能。