基于 Vue.js(前端)+ Python(后端)+ MySQL (数据库)的线上外包任务系统首页全栈方案
·
基于 Vue.js(前端)+ Python(后端)+ MySQL (数据库)的线上外包任务系统首页全栈方案
一、数据库Mysql部分
-
在mysql中新建数据库,名称为wai_group
新建前已有数据库如图:

执行命令,建立数据库wai_group后如图:

-
切换wai_group为当前数据库,此时数据库中Table为空

-
执行命令,新建Table


-
新建task、task_accept、user表后,Mysql的表结构基本实现。
二、后端FastAPI部分
1. 后端已经成功运行,如图所示
三、前端Vue部分
-
打开一个新的命令行窗口(不要关闭后端的窗口,后端服务要一直运行),进入前端项目目录并启动服务(命令为:npm run dev):

-
启动后访问
http://localhost:5173,进入自己的登录首页。
-
便可根据自己的需求扩展其他页面的功能了,每增加一个页面,对应配置好路由
四、相关原始代码
-
main.js文件
import router from './router' // 新增这行 import { createApp } from 'vue' import App from './App.vue' import ElementPlus from 'element-plus' import 'element-plus/dist/index.css' import axios from 'axios' const app = createApp(App); // 配置Axios请求拦截器(添加JWT令牌) axios.interceptors.request.use(config => { const token = localStorage.getItem('access_token'); if (token) config.headers.Authorization = `Bearer ${token}`; return config }); app.config.globalProperties.$axios = axios; app.use(router).use(ElementPlus).mount('#app'); // 新增这行,放在 app.use(ElementPlus) 后面 -
main.py文件
from fastapi import FastAPI, Depends, HTTPException, UploadFile from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm from jose import JWTError, jwt from passlib.context import CryptContext import pymysql from datetime import datetime, timedelta from pydantic import BaseModel # 配置 SECRET_KEY = "your-secret-key-32bytes-long" # 替换为随机32位字符串 ALGORITHM = "HS256" ACCESS_TOKEN_EXPIRE_MINUTES = 30 # 数据库连接 def get_db(): db = pymysql.connect(host="localhost", user="meimei", password="123", db="wai_group") try: yield db finally: db.close() # 密码加密 pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") app = FastAPI() # 数据模型(Pydantic) class UserCreate(BaseModel): username: str; password: str; role: int; skill: str = None class TaskCreate(BaseModel): title: str; content: str; budget: float; deadline: datetime # JWT认证 def create_access_token(data: dict): to_encode = data.copy() to_encode.update({"exp": datetime.utcnow() + timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)}) return jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM) oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token") def get_current_user(token: str = Depends(oauth2_scheme), db=Depends(get_db)): try: payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM]) username: str = payload.get("sub") if not username: raise HTTPException(status_code=401, detail="无效令牌") cursor = db.cursor(pymysql.cursors.DictCursor) cursor.execute("SELECT * FROM user WHERE username=%s", (username,)) user = cursor.fetchone() if not user: raise HTTPException(status_code=401, detail="用户不存在") return user except JWTError: raise HTTPException(status_code=401, detail="令牌失效") # 1. 用户注册 @app.post("/register") def register(user: UserCreate, db=Depends(get_db)): cursor = db.cursor() hashed_pwd = pwd_context.hash(user.password) try: cursor.execute("INSERT INTO user(username,password,role,skill) VALUES(%s,%s,%s,%s)", (user.username, hashed_pwd, user.role, user.skill)) db.commit() return {"code": 200, "msg": "注册成功"} except: db.rollback(); raise HTTPException(status_code=400, detail="用户名已存在") # 2. 用户登录(获取JWT令牌) @app.post("/token") def login(form_data: OAuth2PasswordRequestForm = Depends(), db=Depends(get_db)): cursor = db.cursor(pymysql.cursors.DictCursor) cursor.execute("SELECT * FROM user WHERE username=%s", (form_data.username,)) user = cursor.fetchone() if not user or not pwd_context.verify(form_data.password, user["password"]): raise HTTPException(status_code=400, detail="账号或密码错误") access_token = create_access_token(data={"sub": user["username"]}) return {"access_token": access_token, "token_type": "bearer"} # 3. 发布任务 @app.post("/task/publish") def publish_task(task: TaskCreate, current_user=Depends(get_current_user), db=Depends(get_db)): if current_user["role"] != 1: raise HTTPException(status_code=403, detail="仅发布者可发布任务") cursor = db.cursor() cursor.execute("INSERT INTO task(publisher_id,title,content,budget,deadline) VALUES(%s,%s,%s,%s,%s)", (current_user["id"], task.title, task.content, task.budget, task.deadline)) db.commit() return {"code": 200, "msg": "任务发布成功", "task_id": cursor.lastrowid} # 4. 浏览待接单任务 @app.get("/task/list") def get_task_list(db=Depends(get_db)): cursor = db.cursor(pymysql.cursors.DictCursor) cursor.execute("SELECT t.*, u.username FROM task t JOIN user u ON t.publisher_id=u.id WHERE t.status=0") return {"code": 200, "data": cursor.fetchall()} # 5. 接包者接单 @app.post("/task/accept/{task_id}") def accept_task(task_id: int, current_user=Depends(get_current_user), db=Depends(get_db)): if current_user["role"] != 2: raise HTTPException(status_code=403, detail="仅接包者可接单") cursor = db.cursor() # 检查任务状态(是否待接单) cursor.execute("SELECT status FROM task WHERE id=%s", (task_id,)) task = cursor.fetchone() if not task or task["status"] != 0: raise HTTPException(status_code=400, detail="任务不可接单") # 插入接单记录 + 更新任务状态为进行中 cursor.execute("INSERT INTO task_accept(task_id,acceptor_id) VALUES(%s,%s)", (task_id, current_user["id"])) cursor.execute("UPDATE task SET status=1 WHERE id=%s", (task_id,)) db.commit() return {"code": 200, "msg": "接单成功"} # 6. 提交任务成果(简化:仅标记完成) @app.post("/task/finish/{task_id}") def finish_task(task_id: int, current_user=Depends(get_current_user), db=Depends(get_db)): cursor = db.cursor() # 检查是否是该任务的接包者 cursor.execute("SELECT id FROM task_accept WHERE task_id=%s AND acceptor_id=%s AND status=0", (task_id, current_user["id"])) if not cursor.fetchone(): raise HTTPException(status_code=403, detail="无权限操作此任务") # 更新接单状态 + 任务状态 cursor.execute("UPDATE task_accept SET status=1, finish_time=NOW() WHERE task_id=%s AND acceptor_id=%s", (task_id, current_user["id"])) cursor.execute("UPDATE task SET status=2 WHERE id=%s", (task_id,)) db.commit() return {"code": 200, "msg": "任务已提交,等待验收"}- login.vue文件
<template> <el-form :model="form" label-width="80px" style="width: 400px; margin: 100px auto"> <el-form-item label="用户名" prop="username"> <el-input v-model="form.username"></el-input> </el-form-item> <el-form-item label="密码" prop="password"> <el-input v-model="form.password" type="password"></el-input> </el-form-item> <el-form-item label="角色"> <el-radio-group v-model="form.role"> <el-radio label="1">发布者</el-radio> <el-radio label="2">接包者</el-radio> </el-radio-group> </el-form-item> <el-form-item> <el-button type="primary" @click="login">登录</el-button> <el-button @click="goRegister">注册</el-button> </el-form-item> </el-form> </template> <script setup> import { ref } from 'vue' import { useRouter } from 'vue-router' import { ElMessage } from 'element-plus' const router = useRouter(); const form = ref({ username: '', password: '', role: '1' }); const login = async () => { try { const res = await $axios.post('/token', new URLSearchParams({ username: form.value.username, password: form.value.password, grant_type: 'password' })); localStorage.setItem('access_token', res.data.access_token) router.push(form.value.role === '1' ? '/publish-task' : '/task-list') } catch (error) { ElMessage.error(error.response?.data?.detail || '账号或密码错误') } }; const goRegister = () => { router.push('/register') // 若未创建注册页,可先注释或跳转到其他页面 } </script>
ist’)
} catch (error) {
ElMessage.error(error.response?.data?.detail || ‘账号或密码错误’)
}
};
const goRegister = () => {
router.push('/register') // 若未创建注册页,可先注释或跳转到其他页面
}
</script>
```
以上步骤及代码供大家参考和交流!!!
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐



所有评论(0)