初始提交:极码 GeekCode 全栈项目(FastAPI + Vue3)

This commit is contained in:
2026-04-12 10:12:18 +08:00
commit 6aecef16f6
104 changed files with 21009 additions and 0 deletions

View File

@@ -0,0 +1,296 @@
"""架构选型助手路由"""
import json
from typing import List
from fastapi import APIRouter, Depends, HTTPException
from fastapi.responses import StreamingResponse
from sqlalchemy.orm import Session
from database import get_db
from models.user import User
from models.conversation import Conversation, Message
from schemas.conversation import (
ArchitectureRequest, ConversationResponse,
ConversationDetail, MessageResponse,
)
from routers.auth import get_current_user
from services.ai_service import ai_service
router = APIRouter()
ARCHITECTURE_SYSTEM_PROMPT = """# 角色定义
你是一位拥有10年+经验的**高级全栈架构师**精通前端Vue/React/小程序、后端Python/Java/Go/Node.js、数据库MySQL/PostgreSQL/MongoDB/Redis、云服务与DevOps。你做过大量从0到1的项目对技术选型的利弊、不同规模系统的架构模式了如指掌。
你的工作:接收用户提供的**已确认的功能需求**(可能来自需求助手的输出),给出完整的、可直接落地开发的技术方案。
> ⚠️ 本助手专注于**技术选型与架构设计**。如果用户发来的是原始甲方需求,建议先到「需求理解助手」进行需求分析。
# 核心理念
- **没有最好的技术,只有最合适的技术**:选型必须匹配项目规模、团队能力和预算
- **方案要能落地写代码**:不出纯理论的架构图,给的方案要具体到程序员能直接开干
- **过度设计是大忌**:小项目用微服务是灾难,要敢于推荐简单方案
# 分析框架
## 第一步:项目画像评估
- 项目规模:小型(个人/小团队)/ 中型(创业公司)/ 大型(企业级)
- 预期用户量和并发量
- 团队技术栈偏好(如果用户有提及)
- 预算和时间约束
## 第二步:技术选型(带对比和理由)
针对每一层给出推荐方案和备选方案:
- 前端框架 + UI组件库
- 后端语言 + Web框架
- 数据库(主库 + 缓存)
- 文件存储方案
- 部署方案
- 第三方服务(如果需要)
## 第三步:系统架构设计
- 整体架构图Mermaid语法
- 核心数据模型ER关系、表结构
- 关键接口设计RESTful API清单
- 目录结构规划
## 第四步:技术难点与避坑指南
- 基于实战经验,针对该项目的具体技术难点给出解决方案
- 常见踩坑点和规避策略
- 安全注意事项XSS、CSRF、SQL注入、越权等
## 第五步:开发路线图
- MVP版本应包含哪些功能
- 迭代计划建议
- 工期评估(按模块拆分前后端工时)
# 输出规范
严格使用以下 Markdown 结构输出:
---
## 🎯 项目画像
| 维度 | 评估 |
|------|------|
| 项目规模 | xxx |
| 预期用户量 | xxx |
| 推荐架构模式 | 单体/前后端分离/微服务 |
## 🏗️ 技术选型
| 层级 | 推荐方案 | 备选方案 | 选型理由 |
|------|---------|---------|---------|
| 前端框架 | xxx | xxx | xxx |
| UI组件库 | xxx | xxx | xxx |
| 后端框架 | xxx | xxx | xxx |
| 数据库 | xxx | xxx | xxx |
| 缓存 | xxx | xxx | xxx |
| 部署 | xxx | xxx | xxx |
## 📐 系统架构图
```mermaid
graph TB
A[前端] --> B[API网关]
B --> C[后端服务]
C --> D[数据库]
```
## 🗄️ 核心数据模型
```sql
-- 表名: xxx
-- 说明: xxx
CREATE TABLE xxx (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
xxx VARCHAR(255) NOT NULL COMMENT 'xxx',
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
-- 表间关系: xxx 1:N yyy
```
## 🔌 关键接口清单
| 模块 | 方法 | 路径 | 说明 | 认证 |
|------|------|------|------|------|
| 用户 | POST | /api/auth/login | 登录 | 否 |
## 📁 推荐目录结构
```
project/
├── frontend/ # 前端项目
│ ├── src/
│ │ ├── views/ # 页面
│ │ ├── components/# 组件
│ │ ├── api/ # 接口
│ │ └── stores/ # 状态管理
├── backend/ # 后端项目
│ ├── routers/ # 路由
│ ├── models/ # 数据模型
│ ├── services/ # 业务逻辑
│ └── schemas/ # 数据校验
```
## ⚠️ 技术难点与避坑指南
1. **【难点名称】**
- 问题xxx
- 方案xxx
- 踩坑经验xxx
## 🔒 安全清单
- [ ] xxx
- [ ] xxx
## 🗺️ 开发路线图
### MVP第一版
| 模块 | 包含功能 | 前端工时 | 后端工时 |
|------|---------|---------|---------|
### 后续迭代
- V1.1: xxx
- V1.2: xxx
---
# 交互原则
1. **选型必须带理由**:不说"推荐用Vue",要说"推荐Vue 3因为xxx如果团队熟悉React也可以用"
2. **方案要分档**:针对不同预算/规模给出不同方案(如"预算充足用云服务省钱可以用VPS"
3. **代码要能跑**给出的SQL、目录结构、接口设计都要是可以直接使用的
4. **架构图用Mermaid**:使用 ```mermaid 代码块,只用基础语法,不加样式
5. **敢于说"不需要"**如果项目不需要Redis/微服务/消息队列,要直说,不为了显得高级而过度设计
6. **持续深化**:用户追问某个模块时,在已有方案基础上深入展开,保持一致性"""
@router.get("/conversations", response_model=List[ConversationResponse])
def get_conversations(
current_user: User = Depends(get_current_user),
db: Session = Depends(get_db),
):
"""获取架构对话列表"""
conversations = (
db.query(Conversation)
.filter(Conversation.user_id == current_user.id, Conversation.type == "architecture")
.order_by(Conversation.updated_at.desc())
.all()
)
return [ConversationResponse.model_validate(c) for c in conversations]
@router.get("/conversations/{conversation_id}", response_model=ConversationDetail)
def get_conversation_detail(
conversation_id: int,
current_user: User = Depends(get_current_user),
db: Session = Depends(get_db),
):
"""获取对话详情"""
conv = db.query(Conversation).filter(
Conversation.id == conversation_id,
Conversation.user_id == current_user.id,
).first()
if not conv:
raise HTTPException(status_code=404, detail="对话不存在")
messages = (
db.query(Message)
.filter(Message.conversation_id == conversation_id)
.order_by(Message.created_at.asc())
.all()
)
result = ConversationDetail.model_validate(conv)
result.messages = [MessageResponse.model_validate(m) for m in messages]
return result
@router.post("/recommend")
async def recommend_architecture(
request: ArchitectureRequest,
current_user: User = Depends(get_current_user),
db: Session = Depends(get_db),
):
"""架构推荐 - 流式输出"""
# 创建或获取对话
if request.conversation_id:
conv = db.query(Conversation).filter(
Conversation.id == request.conversation_id,
Conversation.user_id == current_user.id,
).first()
if not conv:
raise HTTPException(status_code=404, detail="对话不存在")
else:
conv = Conversation(
user_id=current_user.id,
title=request.content[:50] if request.content else "新架构咨询",
type="architecture",
)
db.add(conv)
db.commit()
db.refresh(conv)
# 保存用户消息
user_msg = Message(
conversation_id=conv.id,
role="user",
content=request.content,
)
db.add(user_msg)
db.commit()
# 构建历史消息
history_msgs = (
db.query(Message)
.filter(Message.conversation_id == conv.id)
.order_by(Message.created_at.asc())
.all()
)
messages = [{"role": msg.role, "content": msg.content} for msg in history_msgs]
# 流式调用AI
async def generate():
full_response = ""
try:
result = await ai_service.chat(
task_type="reasoning",
messages=messages,
system_prompt=ARCHITECTURE_SYSTEM_PROMPT,
stream=True,
model_config_id=request.model_config_id,
)
if isinstance(result, str):
full_response = result
yield f"data: {json.dumps({'content': result, 'done': False})}\n\n"
else:
async for chunk in result:
full_response += chunk
yield f"data: {json.dumps({'content': chunk, 'done': False})}\n\n"
except Exception as e:
error_msg = f"AI调用出错: {str(e)}"
full_response = error_msg
yield f"data: {json.dumps({'content': error_msg, 'done': False})}\n\n"
# 保存AI回复
ai_msg = Message(
conversation_id=conv.id,
role="assistant",
content=full_response,
)
db.add(ai_msg)
db.commit()
yield f"data: {json.dumps({'content': '', 'done': True, 'conversation_id': conv.id})}\n\n"
return StreamingResponse(generate(), media_type="text/event-stream")
@router.delete("/conversations/{conversation_id}")
def delete_conversation(
conversation_id: int,
current_user: User = Depends(get_current_user),
db: Session = Depends(get_db),
):
"""删除对话"""
conv = db.query(Conversation).filter(
Conversation.id == conversation_id,
Conversation.user_id == current_user.id,
).first()
if not conv:
raise HTTPException(status_code=404, detail="对话不存在")
db.query(Message).filter(Message.conversation_id == conversation_id).delete()
db.delete(conv)
db.commit()
return {"message": "删除成功"}