一句话解释
图智绘是一个 AI 信息图生成平台。用户输入一句需求,或者上传一份文档,系统会自动分析内容, 生成时间线、流程图、SWOT、四象限、路线图等可编辑的信息图。
从零学习一个 AI 全栈项目
这份文档用编程小白也能理解的方式,讲清楚图智绘是什么、代码放在哪里、前后端如何协作、 AI 生成信息图的核心流程,以及你应该按什么顺序开始读代码。
输入主题、上传文档或选择模板
NestJS 校验登录、解析文档、调用 AI
Vue 将结构化 JSON 渲染成信息图
作品保存到数据库,可导出 PNG/PDF/PPTX
先从产品视角理解,再进入代码。
图智绘是一个 AI 信息图生成平台。用户输入一句需求,或者上传一份文档,系统会自动分析内容, 生成时间线、流程图、SWOT、四象限、路线图等可编辑的信息图。
很多人会写内容,但不会设计图。这个项目把“整理内容、选择图表、排版展示、导出交付”串成一条流程, 让用户不用懂设计也能做出专业可视化。
自然语言、文档、模板、已有作品。
登录鉴权、额度判断、文档解析、AI 生成、数据保存。
可编辑信息图、多页演示文稿、图片、PDF、PPTX、分享链接。
把技术先翻译成人话。
负责浏览器里看到的页面、按钮、表单、编辑器和信息图预览。
apps/web
负责接口、登录、数据库读写、AI 调用、文档解析和管理后台数据。
apps/server
保存用户、作品、模板、收藏、分享等业务数据。
apps/server/data/chartwiz.db
根据用户输入生成结构化图表数据,不直接生成一张不可编辑图片。
apps/server/src/ai
保存当前用户、token、登录弹窗状态、作品编辑状态。
apps/web/src/stores
把浏览器里渲染出的图转成图片、PDF 或 PPTX 文件。
apps/web/src/views/editor
看懂系统如何分层,后面读代码会轻很多。
用户看到的页面
接收请求,判断权限,调用业务服务
数据库、上传文件、第三方服务
不知道从哪里看代码时,先看这一张表。
| 路径 | 作用 | 适合什么时候看 |
|---|---|---|
apps/web/src/router |
前端页面地址和登录拦截 | 想知道页面从哪里进入 |
apps/web/src/api |
前端请求后端接口的封装 | 想知道按钮点击后请求哪个接口 |
apps/web/src/stores |
用户状态、作品状态、主题状态 | 想知道登录信息怎么保存 |
apps/web/src/views/generate |
AI 生成入口页面 | 想学习“输入内容生成图”的前端流程 |
apps/web/src/views/editor |
编辑器、保存、导出 | 想学习信息图如何编辑和导出 |
apps/server/src/auth |
登录、注册、JWT、微信 SSO | 想学习账号系统 |
apps/server/src/ai |
AI 提示词、生成逻辑、额度扣减 | 想学习核心生成能力 |
apps/server/src/database/entities |
数据库表结构 | 想知道系统保存了哪些数据 |
用“用户登录”做例子理解前后端协作。
用户在登录页输入邮箱和密码,页面调用 useUserStore.login()。
apps/web/src/api/auth.ts 调用 POST /auth/login。
AuthService 找到用户,用 bcrypt 比较密码和数据库里的哈希。
密码正确后,后端返回 token 和用户信息。
Pinia 把 token 和 user 写进 localStorage,刷新页面也能保持登录。
从产品动作拆到代码模块。
前端把用户输入发给后端。后端先判断用户是否有权限和 Credits,再把需求整理成 Prompt 发给 AI。 AI 返回结构化 JSON,前端拿 JSON 渲染成信息图。
apps/server/src/aiapps/web/src/views/generate用户上传 PDF、DOCX、Markdown 或 TXT。后端先把文件变成纯文本,再让 AI 提炼重点并选择适合的图表类型。
apps/server/src/documentapps/server/src/ai信息图不是一张死图片,而是一份可编辑的数据。编辑器修改标题、节点、颜色后,把最新配置保存到 works 表。
apps/server/src/workapps/web/src/views/editor模板是一批预设好的图表配置和分类。用户可浏览、收藏、套用;管理员可从作品发布模板。
apps/server/src/templateapps/web/src/views/templates生成 AI 内容会消耗 Credits。后端负责判断余额、扣减额度、记录累计消耗,避免前端绕过限制。
apps/server/src/ai/ai.service.tsapps/server/src/pay后台接口也走 JWT,但额外检查用户角色是否为 admin。管理员可以看统计、管用户、管模板和订单。
apps/server/src/adminapps/web/src/views/admin当前项目的 AI 模块采用“多 Agent 协作 + 类型专属结构化生成”的设计。
后端 AI 能力集中在 apps/server/src/ai。其中
ai.controller.ts 负责鉴权、额度预检查和扣费;
ai.service.ts 负责模型调用、Agent 编排、Prompt、JSON 解析和 fallback。
项目用 OpenAI SDK 的 Chat Completions 接口形态,兼容 DeepSeek 和通义千问 Qwen。
通过 AI_PROVIDER、DEEPSEEK_API_KEY、QWEN_API_KEY
等环境变量切换服务商。
来自生成页或文档解析结果。
识别主体、要点、摘要、建议图表类型。
按 timeline、swot、process 等格式生成 JSON。
前端根据 type 渲染对应图表组件。
它不直接生成图表,而是把用户输入变成后续 Agent 能理解的上下文。
输出包括 suggestedTypes、title、summary、
subject、keyPoints、contentBrief。
如果用户已选模板类型或输入里有“SWOT、时间线、流程图”等关键词,系统会先用代码确定类型, 再让 Agent 1 只做内容分析,避免 AI 把用户指定的图表类型改掉。
它接收 Agent 1 的分析结果和最终图表类型,使用 getTypeSpecificInstruction()
中的类型专属 Prompt,生成严格 JSON。
每种类型都有不同数据结构:多数类型用 data.items,
SWOT、四象限、对比分析这类分区图用 data.sections。
这里的 Agent 不是两个独立进程,而是同一个 AiService 内部的两次模型调用和一次数据传递。
Agent 1 的返回值会作为 Agent 2 的输入上下文,这就是它们实现共同目标的“通信协议”。
ContentAnalysis {
suggestedTypes: string[] // 推荐图表类型
title: string // 信息图标题
summary: string // 用户意图摘要
subject?: string // 核心分析对象
keyPoints: string[] // 关键要点
contentBrief?: string // 简短输入时补充的内容素材
}
GenerateResult {
config: InfographicConfig // 前端最终渲染的数据
title: string
templateType: string
agentLog?: object // 前端展示“AI 分析过程”
}
generateFromText() 或 generateFromDocument():
先确定类型来源,再调用 Agent 1 分析,最后 Agent 2 生成一个配置。
generateMultiple() 会先用 Agent 1 分析一次,再选出多个类型,
通过 Promise.allSettled() 并行生成不同方案,失败的方案用 fallback 补位。
generatePresentation() 先让规划 Agent 输出演示标题和每页 brief、suggestedType,
再把每页当作一个小信息图并行生成。
iterateWork() 把当前 InfographicConfig 和用户修改指令发给模型,
要求保持原有 type 和结构,只按指令改内容。
模型调用使用 response_format: { type: 'json_object' },减少非 JSON 文本干扰。
System Prompt 定义角色、格式和约束;User Prompt 放用户请求、文档内容、Agent 1 摘要。
extractExplicitType() 用代码识别“流程图、SWOT、路线图”等关键词,优先级高于 AI 推断。
Agent 1 提取 subject,Agent 2 再被要求所有条目都围绕该主体创作。
AsyncLocalStorage 统计一次请求内多次模型调用的总 token,用于 Credits 扣减。
JSON 解析失败、结构不匹配或某个并行方案失败时,使用类型对应 fallback,避免前端白屏。
先理解几张核心表,不需要一开始背 SQL。
用户表:邮箱、密码哈希、昵称、角色、Credits、微信 openid。
作品表:标题、类型、图表数据、缩略图、所属用户。
模板表:模板名称、分类、预设配置、是否发布。
分享表:作品对应的公开访问 token 和过期时间。
第一次运行项目时按这个顺序来。
pnpm install
pnpm dev:web
pnpm dev:server
pnpm build
http://localhost:5173,后端接口通常是
http://localhost:3000/api,Swagger 文档是 /api/docs。
不要从最复杂的 AI 代码开始。
启动前端和后端,体验登录、生成、编辑、保存、后台管理。
从 router/index.ts 找页面,再去对应的 views 看模板。
找到页面调用的 API,再去后端 controller 里找对应接口。
理解 user、work、template 的字段,知道数据最终存在哪里。
AI 生成逻辑涉及 Prompt、JSON 结构、额度扣减,适合在理解基础流程后再读。
先知道每个页面负责什么,再去看对应代码。
负责产品展示、模板浏览和公开作品预览。分享页不需要登录,适合给外部用户查看作品。
apps/web/src/views/home
apps/web/src/views/templates
apps/web/src/views/share
用户输入主题、选择生成数量或上传文档。这里是前端调用 AI 接口的主要入口。
apps/web/src/views/generate
负责渲染 AI 返回的数据、编辑内容、保存作品、上传缩略图、导出文件。
apps/web/src/views/editor
apps/web/src/views/presentation
登录页处理账号密码登录;微信回调页处理 SSO token;个人中心展示用户作品和权益信息。
apps/web/src/views/login
apps/web/src/views/auth/callback.vue
apps/web/src/views/profile
只有 admin 角色能访问,包含概览、用户、订单、模板、系统配置等管理能力。
apps/web/src/views/admin
router/index.ts 找 URL 对应的组件,再看该页面调用了哪个 api 文件,
最后去后端找同名 controller。这样不会在项目里迷路。
本地分为开发运行和生产构建预览两种方式。
适合写代码和调试。前端 Vite 开热更新,后端 NestJS watch 编译。
pnpm install
pnpm dev:server
pnpm dev:web
http://localhost:5173http://localhost:3000/api/api 和 /uploads 代理到后端。适合上线前验证构建产物。先构建,再用预览命令检查前端页面。
pnpm build
pnpm --filter @chart-wiz/web run preview
pnpm --filter @chart-wiz/server run start
apps/web/dist。VITE_API_URL。| 变量 | 作用 | 建议 |
|---|---|---|
PORT |
后端监听端口 | 本地可用 3000,生产可用 3006。 |
DB_PATH |
SQLite 数据库文件路径 | 开发可放 apps/server/data/chartwiz.db。 |
DEEPSEEK_API_KEY |
DeepSeek API Key | 至少配置 DeepSeek 或 Qwen 中一个。 |
JWT_SECRET |
JWT 签名密钥 | 生产环境必须换成长随机字符串。 |
FRONTEND_URL |
CORS 允许的前端地址 | 本地通常是 http://localhost:5173。 |
当前项目已经提供一套脚本化部署方案。
安装 Node.js 20、Nginx,开放 80/443/SSH 端口。PM2 可由部署脚本自动处理。
编辑 deploy/deploy.config.sh,设置服务器地址、部署目录、域名、后端端口、AI Key、JWT 密钥。
首次执行 deploy/setup-ssh.sh,之后部署不需要反复输入服务器密码。
执行 deploy/deploy.sh,脚本会构建前端、上传文件、写入 Nginx 配置、重启后端服务。
访问域名、检查 /api/health,并用 pm2 logs 查看后端日志。
/www/chartswiz/
├── backend/ # 后端源码与构建产物
├── frontend/dist/ # 前端静态文件
├── data/ # SQLite 数据库
├── uploads/ # 上传缩略图等文件
└── chartswiz.mvtable.com_nginx/ # SSL 证书
/ 返回前端 dist/index.html。/api 反向代理到 NestJS 后端端口。/uploads 返回上传资源或代理后端静态资源。synchronize 在正式长期运营时建议改成迁移方案。
用这套规则维护 Vue 工程,会更容易扩展。
views 放页面,components 放可复用组件,api 放接口封装,stores 放状态。
所有请求都从 api/http.ts 走,统一处理 token、错误提示、401 退出登录。
用户信息、token、当前作品这类跨页面数据放 Pinia;页面内临时表单留在组件内部。
需要登录或管理员权限的页面,在路由 meta 里标记,由路由守卫统一处理。
例如登录弹窗只处理登录体验;图表渲染组件只处理数据到画面的展示。
大型依赖如 Ant Design Vue、PPTX 导出库可以用 Vite/Rollup manualChunks 分离。
NestJS 工程最重要的是模块边界、鉴权和配置管理。
auth、ai、work、template、admin 各管一块业务,避免所有逻辑堆在一个文件。
Controller 负责接收参数和返回结果,复杂业务放 Service,数据库操作通过 Repository。
前端隐藏按钮只是体验优化,真正的权限判断必须放在后端 Guard 或接口内部。
AI Key、支付密钥、JWT 密钥都应该从 .env 或服务器环境读取,不写死在业务代码里。
通过拦截器统一响应格式,通过异常类表达错误,前端才能稳定处理各种状态。
SQLite、uploads、部署配置都要备份。上线后删除用户、改表结构、重置数据都要谨慎。
遇到陌生词先查这里。
前端负责页面,后端负责数据和业务。两者通过 HTTP API 沟通。
JWT 是登录凭证。用户登录成功后拿到 token,以后请求接口时带上它,后端就知道你是谁。
ORM 把数据库表映射成 TypeScript 类,让代码能用对象方式读写数据库。
JSON 可以继续编辑、保存和导出;图片只能看,不能方便地改结构和文字。