当前位置: 首页 > news >正文

基于 Django+Vue3 的 AI 海报生成平台开发(海报模块专项)

1、项目介绍

1.1、需求分析

1.1.1、功能性需求

从业务场景出发,AI 海报生成平台的核心需求围绕 “便捷、智能、可定制” 的海报创作全流程展开,具体包括:

  • AI 辅助创作能力提供提示词助手(多轮对话式 AI),帮助用户生成专业海报描述,降低创作门槛;支持通过 Coze 智能体豆包视觉大模型实现 “文本→海报”“海报→优化海报” 的 AI 驱动创作。
  • 海报生成功能:支持模板选择(热门、小红书、商业、节日等分类)、关键词推荐(如 “科技感未来城市”“简约风格插画”)、图片比例自定义(1:1、2:3、4:3 等),满足不同场景(社交分享、商业宣传、节日活动)的海报尺寸需求。
  • 海报优化功能:支持海报内容修改(基于豆包视觉大模型)、画面清晰化、自定义添加 Logo 和二维码;允许上传本地海报进行二次编辑,覆盖 “生成→修改→完善” 的全链路需求。
  • 数据持久化与隔离:用户生成的海报记录、对话会话需长期存储,且严格按用户隔离(通过用户 ID 关联数据),支持记录查询、筛选(按海报类型)、删除操作。
  • 交互体验优化:提示词助手支持流式对话(实时返回 AI 回复),海报生成 / 修改过程显示加载状态,响应式布局适配 PC、平板、手机等设备。

1.1.2、非功能性需求

  • 性能需求:AI 接口响应时间≤5s(流式对话支持增量返回,降低等待感知);图片上传大小限制≤5MB,避免占用过多带宽;页面加载时间≤2s。
  • 兼容性需求:前端支持 Chrome、Edge、Safari 等主流浏览器;响应式适配PC端。
  • 安全性需求:图片上传需过滤非图片格式文件;第三方 API 密钥(Coze、豆包)需通过环境变量或配置文件管理,避免硬编码;用户数据(海报记录、对话)需按用户 ID 隔离,防止越权访问。
  • 可用性需求:操作流程直观(如模板 “一键使用”、关键词 “点击添加”);错误提示明确(如 “图片 URL 不能为空”“生成失败:网络错误”);支持本地图片拖拽上传,降低操作成本。

1.2、技术栈

围绕海报模块的开发需求,技术栈分为后端前端两层,重点集成 AI 能力与前后端交互能力:

层面技术 / 工具用途说明
后端核心Django 5.2.5Web 框架,提供请求路由、数据模型定义、中间件支持(如 CORS 跨域)
Django REST Framework (DRF)构建 RESTful API,处理海报生成、对话等接口逻辑
MySQL 8.0存储用户海报记录(poster_records)、聊天会话(chat_sessions)等数据
AI 能力集成Coze API提供工作流(海报生成)、智能体(提示词助手)能力
豆包视觉大模型(doubao-seededit)实现海报修改、画面优化的视觉生成能力
前端核心Vue 3 (Composition API + TS)构建组件化、类型安全的前端界面
Element Plus提供模板选择、对话界面、表单等 UI 组件,支持响应式
Pinia状态管理,存储海报模板、生成记录、对话历史等全局数据
辅助工具Axios前端与后端 API 交互,处理流式响应、请求拦截(如添加 Token)
Saaa实现响应式样式、渐变动画、自定义滚动条等视觉效果
FreeImage.host + 代理服务器处理本地图片上传,将本地文件转换为可访问的网络 URL

1.3 项目运行效果图

(注:以下为功能页面描述,建议实际运行项目后截取对应截图插入)

  1. 海报生成页

  1. 左侧为模板选择区(Tab 切换 “热门模板”“小红书海报” 等分类,模板卡片 hover 显示 “使用模板” 按钮),右侧为输入区(热门关键词标签、提示词文本框、比例选择器、“生成海报” 按钮),顶部为渐变风格标题栏(含 “智能生成”“多种模板” 等功能标识)。

  2. 提示词助手页

  1. 左侧为会话列表(显示会话标题、最后一条消息预览、时间),右侧为聊天区(欢迎消息→用户输入→AI 流式回复,底部为输入框和发送按钮),支持会话新建、删除、切换。

3.修改海报页

  1. 三栏布局 —— 左侧 “画面调整” 面板(修改描述输入、生成记录管理)、中间 “海报预览” 区(支持图片缩放、下载、取消预览)、右侧 “元素添加” 面板(Logo / 二维码上传、位置选择),支持本地海报拖拽上传。

1.4 项目目录结构

原项目目录已具备基础结构,但为提升可维护性,对海报相关目录进行优化(补充分层、明确职责),优化后结构如下:

1.4.1 后端目录(Django)


1.4.2 前端目录(Vue3)

2. 项目架构分析

2.1 架构图

2.2 架构图内容解析

(1)数据流向逻辑

  1. 用户操作→前端:用户在 “生成海报页” 选择模板、输入提示词,前端通过posterApi.ts将参数(promptpropotion)发送给后端。
  2. 前端→后端:后端路由(/api/posters/posters/)将请求转发至PostersView视图,视图调用CozeServicerun_coze_workflow()方法,传入参数调用 Coze 工作流 API。
  3. 后端→第三方 AI:Coze 工作流生成海报 URL 后返回后端,后端将 URL 存入poster_records表(关联当前用户 ID),并将结果返回前端。
  4. 前端渲染:前端 Pinia 存储海报 URL,跳转至 “修改海报页” 预览,用户可进一步添加 Logo、二维码或优化画面。

(2)核心分层职责

  • 前端层:负责交互与视觉渲染,通过 Pinia 管理全局状态(如模板列表、当前海报 URL),通过 Axios 处理请求(含流式响应,如提示词助手的实时回复)。

  • 后端层:负责业务逻辑与数据管理,视图层处理请求参数校验,服务层封装 AI 接口调用,数据模型层确保用户数据隔离(如PosterRecorduser外键关联SysUser)。
  • 第三方服务层:提供 AI 能力(Coze 生成海报、豆包优化画面)和图片存储(FreeImage.host),代理服务器解决图片上传的跨域问题。

3. 开发的主要功能分析(含代码、注释、效果图)

3.1 提示词助手

提示词助手是降低用户创作门槛的核心功能,基于 Coze 智能体实现多轮对话,支持会话记录持久化,核心解决 “用户不会写提示词” 的问题。

3.1.1 扣子(Coze)智能体的设计

核心逻辑:通过 Coze API 创建聊天机器人实例,支持文本交互与流式回复,封装CozeChatBot类统一管理对话逻辑。

关键代码(后端services/coze_service.py

from cozepy import Coze, TokenAuth, Message, ChatEventType
from typing import List, Optional
import logging# 配置日志
logger = logging.getLogger(__name__)# Coze API配置(建议从环境变量读取,此处为示例)
COZE_API_TOKEN = 'pat_JfvLHMeGpuTHvi7tVNsFIrQs3xo4mbGQ45JCmNPHvR4Ziin7wwmUYul6jdINZg9m'
COZE_BASE_URL = 'https://api.coze.cn/v3'
BOT_ID = '7543072474888929280'  # 预配置的海报提示词助手智能体IDclass CozeChatBot:def __init__(self, bot_id: str = BOT_ID, user_id: str = "default_user", conversation_history: List[Message] = None):"""初始化Coze聊天机器人:param bot_id: 智能体ID(Coze平台创建):param user_id: 用户ID(用于会话隔离):param conversation_history: 历史对话记录"""# 初始化Coze客户端self.coze_client = Coze(auth=TokenAuth(token=COZE_API_TOKEN),base_url=COZE_BASE_URL)self.bot_id = bot_idself.user_id = user_id# 对话历史(默认空列表)self.conversation_history: List[Message] = conversation_history or []def chat_stream(self, user_input: str):"""流式对话(核心!实时返回AI回复):param user_input: 用户输入的提示词需求(如“帮我写一个奶茶海报的提示词”):yield: AI回复的增量内容"""try:# 1. 构建用户消息(Coze要求的格式)user_message = Message.build_user_question_text(user_input)self.conversation_history.append(user_message)# 2. 调用Coze流式APIstream = self.coze_client.chat.stream(bot_id=self.bot_id,user_id=self.user_id,additional_messages=self.conversation_history  # 携带历史对话)# 3. 处理流式响应bot_response = ""for event in stream:# 增量消息事件(实时返回每一段回复)if event.event == ChatEventType.CONVERSATION_MESSAGE_DELTA:if event.message and event.message.content:bot_response += event.message.contentyield event.message.content  # 增量返回给前端# 对话完成事件(记录Token使用)elif event.event == ChatEventType.CONVERSATION_CHAT_COMPLETED:logger.info(f"Token使用量: {event.chat.usage.token_count}")# 4. 保存AI回复到历史记录bot_message = Message.build_assistant_answer(bot_response)self.conversation_history.append(bot_message)except Exception as e:logger.error(f"流式对话失败: {str(e)}")yield f"错误: {str(e)}"

设计说明

  • 封装CozeChatBot类,屏蔽 Coze API 的细节,视图层只需调用chat_stream()即可实现流式对话。
  • 通过user_id参数关联当前登录用户,确保不同用户的对话历史隔离;conversation_history参数支持多轮对话上下文关联。

3.1.2 多轮对话的实现

核心逻辑:前端通过流式 HTTP 响应接收 AI 增量回复,实时更新界面;后端通过ChatSession(会话)和ChatMessage(消息)模型管理多轮对话。

关键代码(前端views/poster/PosterChat.vue

// 发送流式消息
const sendStreamMessage = async (message: string) => {searchDataStore.isStreaming = true;searchDataStore.streamingMessage = "";try {// 调用后端流式接口const response = await fetch("/api/posters/chat/", {method: "POST",headers: {"Content-Type": "application/json","Authorization": `Bearer ${localStorage.getItem("token")}`},body: JSON.stringify({session_id: currentSessionId.value, // 会话ID(为空则新建)message: message,stream: true})});if (!response.ok) throw new Error("请求失败");// 处理流式响应const reader = response.body?.getReader();const decoder = new TextDecoder();let buffer = "";while (true) {const { done, value } = await reader!.read();if (done) break;// 解码二进制流const chunk = decoder.decode(value, { stream: true });buffer += chunk;const lines = buffer.split("\n");buffer = lines.pop() || "";// 解析每一行数据(SSE格式:data: {...})for (const line of lines) {if (line.startsWith("data: ")) {const data = JSON.parse(line.slice(6));if (data.type === "chunk") {// 增量更新AI回复searchDataStore.streamingMessage += data.content;await scrollToBottom(); // 滚动到底部} else if (data.type === "end") {// 对话完成,保存AI消息到本地状态searchDataStore.currentChatSession?.messages.push({id: data.message_id,message_type: "assistant",content: searchDataStore.streamingMessage,create_time: new Date().toISOString()});}}}}} catch (error: any) {ElMessage.error(`发送失败: ${error.message}`);} finally {searchDataStore.isStreaming = false;}
};

效果图描述
用户输入 “帮我写一个咖啡店夏季海报的提示词” 后,输入框右侧显示 “发送中...”,AI 回复以 “打字机” 效果实时显示(如 “咖啡店夏季海报提示词建议:1. 风格:清新日系风,背景用浅薄荷绿... ”),无需等待完整回复,提升交互体验。

3.1.3 会话记录的长久储存与用户隔离

核心逻辑:通过ChatSession(会话)和ChatMessage(消息)模型关联用户 ID,实现 “用户→会话→消息” 的层级隔离;后端接口查询时过滤当前用户的会话,确保数据安全。

关键代码(后端models.py

from django.db import models
from user.models import SysUser
import uuidclass ChatSession(models.Model):"""聊天会话模型(用户→多会话)"""id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)user = models.ForeignKey(SysUser,on_delete=models.CASCADE,related_name="chat_sessions",  # 反向查询:用户.chat_sessions.all()verbose_name="关联用户")title = models.CharField(max_length=200, default="新对话", verbose_name="会话标题")create_time = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")update_time = models.DateTimeField(auto_now=True, verbose_name="最后更新时间")is_active = models.BooleanField(default=True, verbose_name="是否活跃")class Meta:db_table = "chat_sessions"ordering = ["-update_time"]  # 按更新时间倒序(最新会话在前)class ChatMessage(models.Model):"""聊天消息模型(会话→多消息)"""MESSAGE_TYPE_CHOICES = [("user", "用户消息"), ("assistant", "AI回复")]id = models.AutoField(primary_key=True)session = models.ForeignKey(ChatSession,on_delete=models.CASCADE,related_name="messages",  # 反向查询:会话.messages.all()verbose_name="所属会话")message_type = models.CharField(max_length=20, choices=MESSAGE_TYPE_CHOICES)content = models.TextField(verbose_name="消息内容")create_time = models.DateTimeField(auto_now_add=True, verbose_name="发送时间")class Meta:db_table = "chat_messages"ordering = ["create_time"]  # 按发送时间正序(历史消息顺序)

查询逻辑(后端views.py

class ChatSessionDetailView(APIView):permission_classes = [IsAuthenticated]  # 仅登录用户可访问def get(self, request, session_id):"""获取指定会话的消息(用户隔离)"""try:# 1. 过滤:仅查询当前用户的活跃会话session = ChatSession.objects.get(id=session_id,user=request.user,  # 关键!用户隔离is_active=True)# 2. 获取会话下的所有消息messages = ChatMessage.objects.filter(session=session).order_by("create_time")# 3. 格式化返回message_list = [{"id": msg.id,"message_type": msg.message_type,"content": msg.content,"create_time": msg.create_time.strftime("%Y-%m-%d %H:%M:%S")} for msg in messages]return Response({"code": 200,"data": {"session_id": str(session.id), "messages": message_list}})except ChatSession.DoesNotExist:return Response({"code": 404, "message": "会话不存在"})

3.2 生成海报

3.2.1 扣子(Coze)工作流的设计

核心逻辑:通过 Coze 工作流串联 “参数接收→AI 生成→结果返回” 的流程,支持动态传入模板、提示词、比例等参数,无需后端编写复杂 AI 逻辑。

关键代码(后端services/coze_service.py

def run_coze_workflow(parameters: Dict[str, str]) -> Optional[str]:"""调用Coze工作流生成海报:param parameters: 工作流参数(img、prompt、propotion等):return: 生成的海报URL"""try:logger.info(f"执行Coze工作流,参数: {parameters}")# 1. 启动Coze工作流流式运行stream = coze_client.workflows.runs.stream(workflow_id="7541234832299802667",  # Coze工作流IDparameters=parameters)# 2. 处理工作流事件流,提取海报URLreturn _handle_workflow_stream(stream)except Exception as e:logger.error(f"工作流执行失败: {str(e)}")raise Exception(f"生成海报失败: {str(e)}")def _handle_workflow_stream(stream: Stream[WorkflowEvent]) -> Optional[str]:"""处理工作流事件流,提取图片URL"""for event in stream:# 消息事件:工作流返回结果(含海报URL)if event.event == WorkflowEventType.MESSAGE:if event.message and event.message.content:try:# Coze工作流返回格式:{"output": "https://xxx.png"}content = json.loads(event.message.content)if "output" in content:return content["output"]  # 返回海报URLexcept json.JSONDecodeError:logger.warning("解析工作流结果失败")# 错误事件:抛出异常elif event.event == WorkflowEventType.ERROR:error_msg = event.error.message if event.error else "未知错误"raise Exception(f"工作流出错: {error_msg}")# 未获取到URLraise Exception("工作流未返回海报URL")

Coze 工作流设计建议(补充优化):
在 Coze 平台创建工作流时,建议按以下节点设计:

  1. 参数接收节点:定义img(模板 URL)、prompt(提示词)、propotion(比例)等输入参数。
  2. AI 生成节点:调用 Coze 的 “图像生成” 能力,将参数注入生成 prompt(如 “根据模板 {img},按比例 {propotion},生成 {prompt} 风格的海报”)。
  3. 结果返回节点:将生成的图片 URL 按{"output": "xxx"}格式返回,便于后端解析。

3.2.2 模板和关键词

核心逻辑:前端通过 Pinia 存储模板数据和热门关键词,用户选择模板后自动填充对应的提示词,关键词支持 “点击添加”,降低输入成本。

关键代码(前端stores/posters.ts

// 热门关键词(优化后:按场景分类)
const hotKeywords = ref([{ label: "科技感", category: "风格" },{ label: "未来城市", category: "场景" },{ label: "简约插画", category: "风格" },{ label: "商业宣传", category: "用途" },// ... 更多关键词
]);// 海报模板数据(按类型分类)
const posterTemplates = ref({hot: [  // 热门模板{ id: "hot1", url: "/assets/images/posters/hot/hot1.png", prompt: "科技感未来城市海报,霓虹灯效果" },{ id: "hot2", url: "/assets/images/posters/hot/hot2.png", prompt: "简约风格产品宣传海报,清新色调" },],xiaohongshu: [  // 小红书模板{ id: "xh1", url: "/assets/images/posters/xiaohongshu/xh1.png", prompt: "小红书美食探店海报,暖色调,突出食物细节" },]
});// 选择模板:自动填充提示词
const selectTemplate = (template: PosterTemplate) => {searchValue.value = template.prompt;  // 填充提示词currentTemplate.value = template;    // 记录当前模板
};// 选择关键词:追加到提示词
const selectKeyword = (keyword: string) => {if (searchValue.value) {searchValue.value += ` ${keyword}`;} else {searchValue.value = keyword;}
};

效果图描述

  • 模板区域:以网格布局展示模板卡片,hover 时显示 “使用模板” 按钮,点击后右侧输入框自动填充该模板的默认提示词(如 “科技感未来城市海报,霓虹灯效果”)。
  • 关键词区域:以标签云形式展示关键词,点击 “科技感” 后,输入框内容追加 “科技感”(如原内容为 “未来城市”,变为 “未来城市 科技感”)。

3.2.3 比例的选择

核心逻辑:支持 5 种常用海报比例(1:1、2:3、4:3、9:16、16:9),用户选择后将比例值传入后端,Coze 工作流按比例生成海报。

关键代码(前端components/poster/RatioSelector.vue

<template><el-selectv-model="selectedRatio"placeholder="选择海报比例"@change="handleRatioChange"><el-optionv-for="(item, key) in ratioOptions":key="key":label="`${item.label}(${item.value})`":value="key"><!-- 比例预览:小方块展示比例 --><div class="ratio-preview" :style="{ width: item.width, height: item.height }"></div></el-option></el-select>
</template><script setup lang="ts">
import { ref } from "vue";
import { useSearchDataStore } from "@/stores/posters.ts";const searchDataStore = useSearchDataStore();
const selectedRatio = ref("2");  // 默认2:3(竖版,适合小红书)// 比例配置(优化后:含预览尺寸)
const ratioOptions = ref({"1": { label: "正方形", value: "1:1", width: "40px", height: "40px" },"2": { label: "竖版照片", value: "2:3", width: "40px", height: "60px" },"3": { label: "标准照片", value: "4:3", width: "53px", height: "40px" },"4": { label: "长屏", value: "9:16", width: "22.5px", height: "40px" },"5": { label: "宽屏", value: "16:9", width: "71px", height: "40px" }
});// 比例变化:同步到Pinia
const handleRatioChange = (value: string) => {searchDataStore.setImageRatio(value, ratioOptions.value[value].value);
};
</script><style scoped>
.ratio-preview {display: inline-block;margin-right: 8px;border: 2px solid #667eea;border-radius: 4px;
}
</style>

3.3 修改海报

3.3.1 修改海报(豆包视觉大模型)

核心逻辑:用户上传原始海报 URL 和修改提示词(如 “将背景改为森林”),后端调用豆包视觉大模型(doubao-seededit-3-0-i2i-250628)实现 “图生图” 优化。

关键代码(后端services/doubao_service.py

from volcenginesdkarkruntime import Ark
import os
import random
from dotenv import load_dotenv# 加载环境变量(优化:避免密钥硬编码)
load_dotenv()
ARK_API_KEY = os.environ.get("ARK_API_KEY")# 初始化豆包客户端
doubao_client = Ark(base_url="https://ark.cn-beijing.volces.com/api/v3",api_key=ARK_API_KEY
)def modify_poster(image_url: str, prompt: str) -> str:"""调用豆包视觉大模型修改海报:param image_url: 原始海报URL:param prompt: 修改提示词:return: 修改后的海报URL"""try:# 调用豆包图生图APIresponse = doubao_client.images.generate(model="doubao-seededit-3-0-i2i-250628",  # 豆包视觉大模型IDprompt=prompt,image=image_url,  # 原始图片(图生图)seed=random.randint(1, 10000),  # 随机种子(避免重复)guidance_scale=8.5,  # 引导力度(越高越贴近prompt)size="adaptive",  # 自适应原始图片尺寸watermark=False  # 不添加水印)# 提取结果if response.data and len(response.data) > 0:return response.data[0].urlraise Exception("豆包未返回修改后的图片")except Exception as e:raise Exception(f"修改海报失败: {str(e)}")

3.3.2 清晰化

核心逻辑:用户点击 “变清晰” 按钮时,后端不传入修改提示词,仅将原始海报 URL 传入 Coze 工作流,通过 AI 提升画面分辨率和清晰度。

关键代码(后端views.py

class PostersView(APIView):permission_classes = [IsAuthenticated]def post(self, request):# 获取参数img = request.data.get("img")  # 原始海报URLprompt = request.data.get("prompt", "")  # 默认为空(清晰化)# 1. 确定海报类型(清晰化:无prompt且有img)if img and not prompt:poster_type = "enhance"  # 清晰化类型# 构造参数(仅传img,不传递prompt)parameters = {"img": img, "prompt": "提升画面清晰度,优化细节", "propotion": ""}else:# 其他类型(生成/修改)poster_type = "modify" if img else "generate"parameters = {"img": img, "prompt": prompt, "propotion": request.data.get("propotion")}# 2. 调用Coze工作流(清晰化)try:image_url = run_coze_workflow(parameters)# 3. 保存记录PosterRecord.objects.create(user=request.user,image_url=image_url,prompt="画面清晰化",poster_type=poster_type)return Response({"code": 200, "data": {"image_url": image_url}})except Exception as e:return Response({"code": 500, "message": f"清晰化失败: {str(e)}"})

3.3.3 添加 logo 和二维码

核心逻辑:用户上传 Logo / 二维码图片(本地或 URL),选择位置(左上、右上、右下等 9 个位置),后端将参数传入 Coze 工作流,实现元素叠加。

关键代码(前端components/poster/ElementAdd.vue

<template><!-- Logo上传 --><div class="element-upload"><h3>添加Logo</h3><el-uploadaction="/api/upload"  # 后端上传接口(或代理服务器):on-success="handleLogoUpload":before-upload="checkImageSize"><div class="upload-area">点击上传Logo</div></el-upload><!-- 位置选择 --><el-select v-model="logoPosition" placeholder="选择Logo位置"><el-option label="左上" value="nw"></el-option><el-option label="右上" value="ne"></el-option><el-option label="右下" value="se"></el-option><!-- 其他位置 --></el-select></div><!-- 二维码上传(逻辑同上) --><div class="element-upload"><h3>添加二维码</h3><!-- 略... --></div><!-- 确认添加按钮 --><el-button @click="addElements">添加到海报</el-button>
</template><script setup lang="ts">
import { ref } from "vue";
import { useSearchDataStore } from "@/stores/posters.ts";
import { posterApi } from "@/api/posterApi.ts";const searchDataStore = useSearchDataStore();
const logoPosition = ref("nw");  // 默认左上
const qrPosition = ref("se");   // 默认右下
const logoUrl = ref("");
const qrUrl = ref("");// 检查图片大小(≤5MB)
const checkImageSize = (file: File) => {const isLt5M = file.size / 1024 / 1024 < 5;if (!isLt5M) {ElMessage.error("图片大小不能超过5MB");}return isLt5M;
};// Logo上传成功:保存URL
const handleLogoUpload = (response: any) => {logoUrl.value = response.data.image_url;
};// 添加元素到海报
const addElements = async () => {try {const result = await posterApi.addElements({img: searchDataStore.img_uml,  // 当前海报URLlogo_img: logoUrl.value,logo_place: logoPosition.value,qr_img: qrUrl.value,qr_place: qrPosition.value});// 更新海报URLsearchDataStore.img_uml = result.data.image_url;ElMessage.success("元素添加成功");} catch (error) {ElMessage.error("添加失败");}
};
</script>

3.3.4 上传本地海报修改

核心逻辑:支持本地图片拖拽 / 点击上传,通过代理服务器(proxy-server.js)上传到 FreeImage.host,转换为可访问的网络 URL,再进行修改。

关键代码(前端utils/imageUtils.ts

import { ElMessage } from "element-plus";export const uploadLocalImage = async (file: File): Promise<string> => {try {// 1. 检查文件类型if (!file.type.startsWith("image/")) {throw new Error("请上传图片文件");}// 2. 检查文件大小if (file.size > 5 * 1024 * 1024) {throw new Error("图片大小不能超过5MB");}// 3. 构造FormData(FreeImage.host要求的格式)const formData = new FormData();formData.append("key", "6d207e02198a847aa98d0a2a901485a5");  // FreeImage API KeyformData.append("source", file);formData.append("format", "json");// 4. 调用代理服务器(解决跨域)const response = await fetch("http://localhost:3000/upload", {method: "POST",body: formData});const data = await response.json();// 5. 提取网络URLif (data.status_code === 200 && data.image?.url) {return data.image.url;}throw new Error("上传失败: " + data.error?.message);} catch (error: any) {ElMessage.error(error.message);throw error;}
};

代理服务器作用
FreeImage.host 的 API 存在跨域限制(前端无法直接调用),proxy-server.js作为中间层,接收前端请求后转发至 FreeImage.host,再将结果返回前端,解决跨域问题。

3.3.5 生成记录的长久储存和用户隔离

核心逻辑:通过PosterRecord模型关联用户 ID,存储海报 URL、提示词、类型等信息;前端支持按类型筛选(生成 / 修改 / 清晰化),用户仅能查看自己的记录。

关键代码(后端views.py

class PosterRecordsView(APIView):permission_classes = [IsAuthenticated]def get(self, request):"""获取用户的海报记录(支持筛选)"""# 1. 获取筛选参数poster_type = request.GET.get("poster_type")  # 类型筛选search = request.GET.get("search")            # 关键词搜索(提示词)# 2. 基础查询:当前用户的未删除记录queryset = PosterRecord.objects.filter(user=request.user,is_deleted=False)# 3. 应用筛选条件if poster_type:queryset = queryset.filter(poster_type=poster_type)if search:queryset = queryset.filter(prompt__icontains=search)  # 模糊搜索# 4. 格式化返回records = [{"id": record.id,"image_url": record.image_url,"prompt": record.prompt,"poster_type": record.poster_type,"poster_type_display": record.get_poster_type_display(),  # 中文显示(如“生成海报”)"create_time": record.create_time.strftime("%Y-%m-%d %H:%M:%S")} for record in queryset.order_by("-create_time")]return Response({"code": 200,"data": {"records": records,"total_count": len(records)}})

3.3.6 本地上传图片转换图片地址

核心逻辑:通过 FreeImage.host 的 API 将本地图片转换为网络 URL,前端调用代理服务器上传,后端存储转换后的 URL 用于后续修改。

关键代码(后端utils/image_utils.py

import requestsdef convert_local_image_to_url(file_path: str) -> str:"""本地图片文件转换为网络URL(后端备用方案,前端优先用代理):param file_path: 本地图片路径:return: 网络URL"""url = "https://freeimage.host/api/1/upload"data = {"key": "6d207e02198a847aa98d0a2a901485a5","format": "json"}files = {"source": open(file_path, "rb")}response = requests.post(url, data=data, files=files)response_data = response.json()if response_data["status_code"] == 200:return response_data["image"]["url"]raise Exception(f"图片转换失败: {response_data['error']['message']}")

4. 项目总结

4.1 核心功能实现

功能模块实现要点
提示词助手基于 Coze 智能体的流式多轮对话、会话记录用户隔离、持久化存储
海报生成Coze 工作流驱动、模板 / 关键词辅助、多比例支持
海报修改豆包视觉大模型(图生图)、画面清晰化、Logo / 二维码添加、本地图片上传转换
记录管理海报记录 / 会话记录的用户隔离、筛选(类型 / 关键词)、删除

4.2 技术亮点

  1. 多 AI 服务协同:集成 Coze(工作流 + 智能体)和豆包(视觉大模型),分别负责 “海报生成 / 对话” 和 “海报修改”,优势互补。
  2. 流式交互体验:提示词助手采用流式响应,AI 回复实时增量显示,降低用户等待感知;海报生成 / 修改过程显示加载状态,提升交互透明度。
  3. 响应式设计:通过 SCSS 的@media查询适配多设备(PC / 平板 / 手机),模板卡片、输入区布局自动调整,确保移动端可用性。
  4. 数据安全隔离:所有用户数据(海报记录、对话)通过外键关联用户 ID,接口层强制过滤当前用户数据,防止越权访问。

4.3 存在的挑战和解决方案

问题一:图片资源访问限制与解决方案

一、问题背景

在使用“扣子工作流”处理图片时,系统对图片资源的访问存在明确限制:仅支持通过网络地址(URL)访问图片资源。然而,在开发环境中,由于开发者通常未部署正式服务器,上传的图片地址多为本地路径(如本地文件路径或本地服务地址),这些地址不具备公网访问能力,因此无法被“扣子工作流”识别和使用,从而影响业务流程的正常运行。

二、解决方案

为解决上述问题,可采取以下两种方案:

(一)临时过渡方案:使用第三方图片托管服务

在开发阶段,可临时采用第三方图片托管服务作为解决方案。例如,使用 freeimage.host 等服务,通过其提供的 API 接口,将本地图片上传至第三方服务器,由其托管并生成可公网访问的图片 URL。此方式可快速解决图片资源无法被“扣子工作流”识别的问题,保障开发与测试阶段的流程顺畅。

(二)项目化正式方案

根据项目规模和需求,可选择以下长期解决方案,以确保图片资源的稳定存储、高效访问及业务扩展性:

小型项目
采用 静态文件服务 + Nginx 方案,适合小型项目,满足基本的图片存储与访问需求。

中型项目
采用 云存储服务,如 AWS S3 或 阿里云 OSS,提供稳定、高效的存储与访问能力。

大型项目
采用 云存储 + CDN 加速方案,结合内容分发网络(CDN)提升访问速度与稳定性,适用于大规模项目。

问题二

  • 问题背景:
    前端需要上传图片到第三方服务(freeimage.host),但直接调用会遇到浏览器CORS跨域限制,严重影响用户体验。

  • 解决方案

①架构流程:

前端 ---> 本地代理服务器 ---> 第三方图片托管服务(freeimage.host) ---> 返回公网URL

②原理解释:

浏览器直接发送请求到freeimage存在跨域问题,改用浏览器发送请求到代理服务器,代理服务器和freeimage直接实现端对端连接,解决了跨越问题。

问题三

一、问题背景:

生成海报的记录以及聊天会话记录的用户隔离和长久保存,需要支持多轮对话,保持上下文信息,同时要高效管理大量的会话数据。

二、解决方案

①数据模型设计:

User和ChatSession以及ChatMessage的关联设计,UUID确保会话唯一性,软删除和数据归档策略。

问题四

  • 问题背景:

需要同时集成Coze智能体和Coze工作流和豆包两个不同的AI平台,它们的API调用方式、参数格式、响应结构都完全不同。

  • 解决方案

①模块化设计架构

为每个AI服务创建独立工具类,CozeTool.py:封装Coze工作流和聊天机器人,doubaoTool.py:封装豆包图像编辑API。

问题五

  • 问题背景:

AI生成海报和聊天对话都需要实时反馈,传统的请求-响应模式无法满足用户体验要求。

二、解决方案

①流式响应架构:

使用StreamingHttpResponse实现流式输出,Server-Sent Events (SSE) 数据格式。

②连接管理优化:

连接超时和心跳机制,客户端断线检测,资源自动清理。

问题一:图片资源访问限制与解决方案

一、问题背景

在使用“扣子工作流”处理图片时,系统对图片资源的访问存在明确限制:仅支持通过网络地址(URL)访问图片资源。然而,在开发环境中,由于开发者通常未部署正式服务器,上传的图片地址多为本地路径(如本地文件路径或本地服务地址),这些地址不具备公网访问能力,因此无法被“扣子工作流”识别和使用,从而影响业务流程的正常运行。

二、解决方案

为解决上述问题,可采取以下两种方案:

(一)临时过渡方案:使用第三方图片托管服务

在开发阶段,可临时采用第三方图片托管服务作为解决方案。例如,使用 freeimage.host 等服务,通过其提供的 API 接口,将本地图片上传至第三方服务器,由其托管并生成可公网访问的图片 URL。此方式可快速解决图片资源无法被“扣子工作流”识别的问题,保障开发与测试阶段的流程顺畅。

(二)项目化正式方案

根据项目规模和需求,可选择以下长期解决方案,以确保图片资源的稳定存储、高效访问及业务扩展性:

小型项目
采用 静态文件服务 + Nginx 方案,适合小型项目,满足基本的图片存储与访问需求。

中型项目
采用 云存储服务,如 AWS S3 或 阿里云 OSS,提供稳定、高效的存储与访问能力。

大型项目
采用 云存储 + CDN 加速方案,结合内容分发网络(CDN)提升访问速度与稳定性,适用于大规模项目。

问题二

  • 问题背景:
    前端需要上传图片到第三方服务(freeimage.host),但直接调用会遇到浏览器CORS跨域限制,严重影响用户体验。

  • 解决方案

①架构流程:

前端 ---> 本地代理服务器 ---> 第三方图片托管服务(freeimage.host) ---> 返回公网URL

②原理解释:

浏览器直接发送请求到freeimage存在跨域问题,改用浏览器发送请求到代理服务器,代理服务器和freeimage直接实现端对端连接,解决了跨越问题。

问题三

一、问题背景:

生成海报的记录以及聊天会话记录的用户隔离和长久保存,需要支持多轮对话,保持上下文信息,同时要高效管理大量的会话数据。

二、解决方案

①数据模型设计:

User和ChatSession以及ChatMessage的关联设计,UUID确保会话唯一性,软删除和数据归档策略。

问题四

  • 问题背景:

需要同时集成Coze智能体和Coze工作流和豆包两个不同的AI平台,它们的API调用方式、参数格式、响应结构都完全不同。

  • 解决方案

①模块化设计架构

为每个AI服务创建独立工具类,CozeTool.py:封装Coze工作流和聊天机器人,doubaoTool.py:封装豆包图像编辑API。

问题五

  • 问题背景:

AI生成海报和聊天对话都需要实时反馈,传统的请求-响应模式无法满足用户体验要求。

二、解决方案

①流式响应架构:

使用StreamingHttpResponse实现流式输出,Server-Sent Events (SSE) 数据格式。

②连接管理优化:

连接超时和心跳机制,客户端断线检测,资源自动清理。

5. 未来展望

5.1 功能扩展

  1. AI 风格推荐:基于用户历史生成记录,推荐相似风格的模板或提示词(如 “您之前喜欢科技感风格,推荐以下模板”)。
  2. 海报协作:支持多用户共同编辑一张海报(如设计师生成初稿,运营添加 Logo),通过 WebSocket 实现实时同步。
  3. 风格迁移:新增 “风格迁移” 功能(如 “将海报转换为梵高画风”),集成更多视觉大模型(如 Stable Diffusion)。
  4. 批量生成:支持批量上传提示词,一次性生成多张海报(如 “生成 10 张不同节日的促销海报”),提升效率。

5.2 性能与体验优化

  1. 缓存策略:对热门模板、用户常用比例的生成结果进行缓存(如 Redis),减少 AI 接口调用次数,提升响应速度。
  2. 图片优化:生成的海报自动压缩(如使用pillow库),降低图片加载时间;支持 WebP 格式,平衡画质与大小。
  3. 离线体验:通过 PWA 技术实现部分离线功能(如查看历史记录、编辑提示词),提升弱网环境可用性。
  4. 操作引导:新增新手引导流程(如 “点击模板→输入提示词→生成海报”),降低新用户学习成本。

5.3 生态和商业化

  1. 模板市场:推出付费模板(如设计师定制模板),支持模板创作者入驻,平台抽成,形成生态闭环。
  2. 会员体系:免费用户限制生成次数,会员用户解锁高清下载、批量生成、高级 AI 模型(如豆包 Pro)等特权。
  3. 企业版功能:针对企业用户推出 “品牌模板库”(统一企业 VI 风格)、“团队协作”、“海报数据统计”(如曝光量、下载量)。
  4. API 开放:将海报生成 / 修改能力封装为开放 API,供第三方平台调用(如电商平台集成海报生成功能),实现商业化变现。

5.4 技术探索

  1. 端侧 AI 集成:探索在前端集成轻量化 AI 模型(如 TensorFlow.js),实现简单的海报风格预览(如 “本地预览科技感风格”),减少服务器依赖。

  2. 多模态输入:支持语音输入提示词(集成科大讯飞语音识别)、手绘草图生成海报(如用户手绘布局,AI 生成完整海报),扩展输入方式。
  3. AI 自动化:实现 “一键生成全套海报”,用户输入活动主题(如 “618 促销”),AI 自动生成不同平台(小红书、朋友圈、电商)的海报,无需人工调整。

6. 总结和收获

6.1 总结

本项目基于 Django+Vue3 构建了 “AI 驱动的海报创作平台”,聚焦海报 “生成→修改→管理” 的全流程需求,通过 Coze 和豆包 AI 服务降低创作门槛,通过响应式设计和流式交互提升用户体验,通过数据隔离确保用户数据安全。项目不仅实现了核心功能,还通过分层设计(如后端services、前端api)提升了代码可维护性,为后续扩展奠定基础。

6.2 收获

  1. 前后端协作能力:深入理解前后端分离架构下的数据流向(如前端请求→后端视图→AI 服务→数据存储→前端渲染),掌握 Axios 请求封装、DRF 视图设计的最佳实践。
  2. AI API 集成经验:熟悉 Coze、豆包等 AI 平台的 API 调用方式,理解工作流、智能体、视觉大模型的应用场景,学会处理 API 异常和跨域问题。
  3. 用户体验设计意识:从 “流式响应”“模板辅助”“错误提示” 等细节出发,体会 “技术服务于体验” 的理念,提升产品化思维。
  4. 问题解决能力:面对跨域、流式响应、图片上传等挑战,通过查阅文档(Django/Coze API)、调试代码(如流式响应的 SSE 格式),培养独立解决技术问题的能力。

通过本项目,不仅掌握了 AI 驱动的 Web 应用开发流程,还意识到 “功能实现” 与 “用户体验”“可扩展性” 的平衡,为后续复杂项目开发积累了宝贵经验。


文章转载自:

http://lqxZlnjq.ddqdL.cn
http://CeKO6UoZ.ddqdL.cn
http://WjM9dhmz.ddqdL.cn
http://vthUqmQR.ddqdL.cn
http://X2PLAFVe.ddqdL.cn
http://EzGEQvTu.ddqdL.cn
http://C6HeOuOq.ddqdL.cn
http://VMgtkyXm.ddqdL.cn
http://DK8wBiIT.ddqdL.cn
http://XGuwehkN.ddqdL.cn
http://gkSFQvzw.ddqdL.cn
http://AzsAfuWf.ddqdL.cn
http://zgrsoYxl.ddqdL.cn
http://MTsCajnw.ddqdL.cn
http://vpVnck6m.ddqdL.cn
http://swTTqYBP.ddqdL.cn
http://yFftEZ8m.ddqdL.cn
http://rWwx9z7W.ddqdL.cn
http://Ewu6jWES.ddqdL.cn
http://KWKffO78.ddqdL.cn
http://XRPDVyiU.ddqdL.cn
http://q7Ws3NNz.ddqdL.cn
http://JoMGbVcV.ddqdL.cn
http://JGTsEyYJ.ddqdL.cn
http://1mJNL2gU.ddqdL.cn
http://pERKv4RV.ddqdL.cn
http://wBJnf2jQ.ddqdL.cn
http://zE3603b6.ddqdL.cn
http://pPR8C6px.ddqdL.cn
http://3JLC9Yz3.ddqdL.cn
http://www.dtcms.com/a/372645.html

相关文章:

  • 机器学习-K-means聚类
  • 维度跃迁:当万物皆成电路,智能将从“拥有”变为“存在”
  • 前端:最新最全的JavaScript知识汇总,持续更新......
  • PO BAPI bapi_po_create1
  • 当前车载测试的难点分析
  • Pyhton基础之多继承、多态
  • AOSP Framework开发的一些超方便的快捷命令
  • 移动高清盒子CM311-5-内存大小区分参考指南
  • 在 VirtualBox 虚拟机中安装 Fedora CoreOS 操作系统
  • 【SLAM论文笔记】SplaTAM论文小结
  • shell编程之文本三剑客grep、sed、awk
  • 开始 ComfyUI 的 AI 绘图之旅-文生图(一)
  • 有哪些任务可以使用无监督的方式训练深度学习模型?
  • 从零开始构建图注意力网络:GAT算法原理与数值实现详解
  • FastAPI基础
  • 通过SSH来推送本地文件夹到Github
  • 风锐统计——让数据像风一样自由!(十)——关联研究全自动分析
  • AutoGen快速入门
  • v$lock 查找锁 locked objects ORA-54 dblink
  • Daily算法刷题【面试经典150题-2️⃣】
  • Ucloud技术支持问题
  • 调试 cuda kernel
  • OpenLayers常用控件 -- 章节九:比例尺控件教程
  • 李沐深度学习论文精读(一)AlexNet + ResNet
  • CMake构建C++项目,报错“CMake Error CMAKE_C_COMPILER not set, after EnableLanguage”
  • 2025最新超详细FreeRTOS入门教程:第五章 FreeRTOS信号量
  • 安卓逆向(二)相关问题及解决方案
  • 自学嵌入式第37天:MQTT协议
  • daily notes[11]
  • Qt中QProxyStyledrawControl函数4个参数的意义