1. 项目概述与技术选型
在线问答平台是当前互联网教育和技术社区中不可或缺的基础设施。这个基于Python+Flask+Vue3的在线答疑系统,采用了前后端分离的现代化架构设计,能够为师生、开发者或任何需要知识交流的场景提供高效的互动平台。
为什么选择这个技术栈组合?Flask作为Python轻量级Web框架的代表,相比Django等全功能框架,它提供了更高的灵活性和可定制性。对于问答系统这种需要快速迭代的中型项目,Flask的"微内核+插件"模式非常合适。而Vue3作为前端主流框架,其组合式API和响应式系统的改进,特别适合构建动态交互复杂的问答界面。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 后端Flask服务搭建
2.1 基础环境配置
首先需要建立Python虚拟环境:
bash复制python -m venv venv
source venv/bin/activate # Linux/Mac
venv\Scripts\activate # Windows
安装核心依赖:
bash复制pip install flask flask-sqlalchemy flask-cors flask-jwt-extended
注意:生产环境务必固定版本号,可使用
pip freeze > requirements.txt生成依赖清单
2.2 数据模型设计
问答系统的核心数据模型包括用户、问题和回答三个主要实体:
python复制from datetime import datetime
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True, nullable=False)
email = db.Column(db.String(120), unique=True, nullable=False)
password_hash = db.Column(db.String(128))
questions = db.relationship('Question', backref='author', lazy=True)
answers = db.relationship('Answer', backref='author', lazy=True)
class Question(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(200), nullable=False)
content = db.Column(db.Text, nullable=False)
created_at = db.Column(db.DateTime, default=datetime.utcnow)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
answers = db.relationship('Answer', backref='question', lazy=True)
class Answer(db.Model):
id = db.Column(db.Integer, primary_key=True)
content = db.Column(db.Text, nullable=False)
is_accepted = db.Column(db.Boolean, default=False)
created_at = db.Column(db.DateTime, default=datetime.utcnow)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
question_id = db.Column(db.Integer, db.ForeignKey('question.id'), nullable=False)
2.3 API接口实现
典型的RESTful API设计示例:
python复制from flask import request, jsonify
from werkzeug.security import generate_password_hash
@app.route('/api/questions', methods=['GET'])
def get_questions():
page = request.args.get('page', 1, type=int)
per_page = request.args.get('per_page', 10, type=int)
questions = Question.query.order_by(
Question.created_at.desc()
).paginate(page=page, per_page=per_page)
return jsonify({
'items': [q.to_dict() for q in questions.items],
'total': questions.total
})
@app.route('/api/questions', methods=['POST'])
@jwt_required()
def create_question():
data = request.get_json()
question = Question(
title=data['title'],
content=data['content'],
user_id=get_jwt_identity()
)
db.session.add(question)
db.session.commit()
return jsonify(question.to_dict()), 201
3. 前端Vue3开发
3.1 项目初始化
使用Vite创建Vue3项目:
bash复制npm create vite@latest qa-frontend --template vue
cd qa-frontend
npm install axios vue-router pinia @element-plus/icons-vue
3.2 状态管理设计
采用Pinia管理全局状态:
javascript复制// stores/question.js
import { defineStore } from 'pinia'
export const useQuestionStore = defineStore('question', {
state: () => ({
questions: [],
currentQuestion: null,
isLoading: false
}),
actions: {
async fetchQuestions(page = 1) {
this.isLoading = true
try {
const res = await axios.get(`/api/questions?page=${page}`)
this.questions = res.data.items
} finally {
this.isLoading = false
}
},
async postQuestion(questionData) {
const res = await axios.post('/api/questions', questionData)
this.questions.unshift(res.data)
}
}
})
3.3 核心页面组件
问题列表组件示例:
vue复制<template>
<div class="question-list">
<el-button type="primary" @click="showDialog = true">提问</el-button>
<div v-if="store.isLoading" class="loading">加载中...</div>
<div v-else>
<div v-for="q in store.questions" :key="q.id" class="question-item
