commit cfeabf2d374ab84fef32416a3131965dbc9e2b8d Author: 绝尘 <237809796@qq.com> Date: Sun Jul 12 13:12:09 2026 +0800 新增: u-ppt Vue 3 在线演示工具初始版本 - 核心架构: Vue 3 + Vite + TypeScript,零运行时依赖(仅 Vue) - 编辑器: 幻灯片增删排序、元素拖拽八向缩放、双击编辑、12 种元素类型 (标题/正文/列表/数据/金句/图片/形状/图表/卡片/表格/代码/公式) - 图表: 8 种 SVG 自绘(柱状/条形/折线/面积/饼图/环形/雷达/进度) - 富文本: 结构化 segments(加粗/斜体/颜色/高亮/上下标/代码/链接) - AI 能力: 对话编辑、生成整套、润色本页、大纲→逐页生成、一键美化、AI 配图 - 会话绑定: 每份 PPT 独立会话,切换 PPT 自动切换对话历史 - 模板系统: 7 个内置版式 + 用户自存模板 - 演示模式: 全屏播放、键盘/鼠标/滚轮导航、入场动画 - 持久化: localStorage 存 deck/文库/会话/模板/配置 - 支持多服务商: 智谱/DeepSeek/通义/Kimi/豆包/OpenAI/Anthropic/Gemini/Groq/Ollama diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..818ac86 --- /dev/null +++ b/.gitignore @@ -0,0 +1,34 @@ +# Dependencies +node_modules/ + +# Build output +dist/ +dist-ssr/ + +# Tauri (未来桌面版) +src-tauri/target/ + +# IDE +.vscode/* +!.vscode/extensions.json +.idea/ +*.swp +*.swo +*~ + +# OS +.DS_Store +Thumbs.db +desktop.ini + +# Logs +*.log +npm-debug.log* + +# Env +.env +.env.local +.env.*.local + +# Vite临时 +.vite/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..3c8cf64 --- /dev/null +++ b/README.md @@ -0,0 +1,254 @@ +# u-ppt · 在线演示工具 + +基于 **Vue 3 + Vite + TypeScript** 的在线 PPT 应用,无后端。支持编辑、全屏演示,以及 AI 对话式创作。 + +> 历史版本为纯 HTML/CSS/JS 无构建方案,已迁移至 Vue 3 组件化架构,便于长期迭代。 + +## ✨ 功能 + +| 模块 | 能力 | +|------|------| +| **编辑器** | 幻灯片增删/排序、元素拖拽与八向缩放、双击编辑文字、属性面板(字号/颜色/对齐/加粗/形状/层级)、5 套主题、页面背景、7 个内置页面模板 + 自存模板 | +| **演示** | 全屏播放、← →/Space/Home/End 翻页、F 切换全屏、B 黑屏、Esc 退出、左键下一页/右键上一页/滚轮翻页、页码与进度 | +| **AI 创作** | 一键生成整套 PPT、润色当前页、对话式连续编辑、流式打字机输出、随时中断 | +| **AI 深化** | 大纲→逐页生成(先出可编辑大纲,逐页填充)、AI 配图(接入图像模型)、AI 配色/主题推荐、一键美化整份(逐页排版优化) | +| **演示文库** | 命名保存多套 PPT;文库面板管理(打开/重命名/复制/删除)、首屏迷你预览;当前编辑自动保存不丢 | +| **持久化** | 自动保存到浏览器 localStorage,刷新不丢;一键重置为内置示例;Ctrl+Z/Y 撤销重做 | + +支持元素:标题 / 正文 / 列表 / 数据 / 金句 / 形状 / 图片 / 图表(柱状/条形/折线/面积/饼图/环形/雷达/进度 8 种)/ 卡片 / 表格 / 代码 / 公式。 + +## 🚀 使用 + +### 开发 +```bash +npm install +npm run dev +# 浏览器自动打开 http://localhost:8080 +``` + +### 构建 +```bash +npm run build # 产出 dist/,可部署到任意静态托管 +npm run preview # 本地预览构建结果 +``` + +### 起本地静态服务(构建后,便于 AI 跨域调试) +```bash +npm run build +python -m http.server 8080 --directory dist +``` + +## ⌨ 快捷键 + +**编辑模式** +- `Ctrl/Cmd + Z` 撤销 `Ctrl/Cmd + Shift + Z` 重做 `Delete` 删除选中元素 +- `Ctrl/Cmd + S` 触发保存提示(其实已自动保存) + +**演示模式** +- `→` `↓` `Space` `PageDown`:下一页 `←` `↑` `PageUp`:上一页 +- `Home` / `End`:首页 / 末页 `F`:切换全屏 `B`:黑屏 `Esc`:退出 + +## 📚 演示文库(多套 PPT) + +支持保存多份独立演示,随时切换编辑。 + +- **💾 保存**(工具栏):当前已从文库打开则直接更新该份;否则弹出文库让你命名。 +- **📁 文库**(工具栏):打开文库面板 + - 顶部输入名字 → **存入文库**(同名覆盖,不同名则新建一份) + - **+ 新建空白**:从空白演示开始创作 + - 列表每份支持:**打开** / **重命名** / **复制** / **删除**,左侧显示首屏迷你预览 +- 所有内容存浏览器本地(`u-ppt.library`),不上云,刷新不丢。 + +## 🤖 AI 配置 + +点击右上角 **⚙**,在「服务商」下拉选厂商,地址与模型自动填好,只需填 API Key: + +| 服务商 | 协议 | Base URL | 默认模型 | +|--------|------|----------|----------| +| 智谱 GLM(OpenAI) | OpenAI | `open.bigmodel.cn/api/paas/v4` | glm-4.6 | +| 智谱 GLM(Anthropic) | Anthropic | `open.bigmodel.cn/api/anthropic` | glm-4.6 | +| **DeepSeek** | OpenAI | `api.deepseek.com` | deepseek-chat | +| 通义千问(阿里) | OpenAI | `dashscope.aliyuncs.com/compatible-mode/v1` | qwen-plus | +| Kimi(月之暗面) | OpenAI | `api.moonshot.cn/v1` | moonshot-v1-8k | +| 豆包(火山引擎) | OpenAI | `ark.cn-beijing.volces.com/api/v3` | doubao-pro-32k¹ | +| OpenAI | OpenAI | `api.openai.com/v1` | gpt-4o-mini | +| Anthropic Claude | Anthropic | `api.anthropic.com` | claude-sonnet-5 | +| Google Gemini | OpenAI | `generativelanguage.googleapis.com/v1beta/openai` | gemini-2.0-flash | +| Groq(极速) | OpenAI | `api.groq.com/openai/v1` | llama-3.3-70b-versatile | +| Ollama(本地) | OpenAI | `localhost:11434/v1` | llama3.1² | + +¹ 豆包实际需填你在火山方舟创建的**接入点 endpoint id**(`ep-xxx`)。 +² 本地服务(localhost / 127.0.0.1)无需填 Key;Ollama 需设环境变量 `OLLAMA_ORIGINS=*` 允许浏览器跨端口访问。 + +选「**自定义**」可手填任意 OpenAI / Anthropic 兼容服务(如自建网关、LiteLLM、one-api 等)。改字段后保存即可,配置全部存本地 localStorage。 + +> **协议差异**:OpenAI 走 `/chat/completions` + `Authorization: Bearer`;Anthropic 走 `/v1/messages` + `x-api-key` + `anthropic-version`,system 提示置于顶层,流式解析 `content_block_delta`。厂商选错协议会报错,按表格对应即可。 + +### ⚠ 跨域 (CORS) 说明 + +浏览器直连 LLM API 可能被跨域策略拦截(因服务方而异)。若控制台报 CORS 错: +1. 改用本地起服务(见上)再试; +2. 仍不行,在「代理 URL」填一个转发地址(如 Cloudflare Worker / 自建简易代理),请求会改走该代理,Base URL 与 Key 不变。 + +## 🧠 AI 深化能力 + +在原有「一键生成整套」基础上,新增四个可控、渐进式的 AI 创作能力。入口在右侧 **🤖 AI 助手** 面板的顶部按钮区。 + +### 📋 大纲→逐页生成 + +原「生成整套」是一次性出结果,不可干预。深化后的工作流: + +1. 点 **📋 大纲** → 面板展开,输入主题 → **✨ 生成大纲** +2. AI 先出一份可编辑大纲(5-8 页),每页含:页类型(封面/目录/内容/金句/结尾)、标题、要点、补充指令 +3. 你可以自由编辑:改标题、增删要点、调页类型、删页、补 hint(如「数据页:用 stat+chart」「对比页:双 card」) +4. 点单条 **生成此页** 预览效果,或点 **全部生成** 串行生成(带进度 N/M,可中断) +5. 满意后 **应用到文稿** —— 把已生成的页面替换整份 deck + +这样你完全控制节奏与内容结构,不满意可只重生成某一条。 + +### 🎨 美化整份 + +遍历当前文稿的所有页,逐页调 AI 优化**排版**(位置/尺寸/字号/对齐/装饰),**文字内容不变**。适合内容已经到位但版式粗糙的场景。流式气泡实时显示进度「正在美化 3/8 页…」,可中断。 + +### 🎨 AI 配图 + +选中画布上的 **图片元素** 后,右侧属性面板会出现「**🎨 AI 配图**」按钮: + +1. 点击后输入图片描述(如「现代办公室协作场景,俯拍,柔和光线」) +2. 调用图像模型生成图片并自动填入该元素 + +需在 **⚙ 设置** 的「图像模型(可选)」区配置(DALL-E 协议 `/images/generations`): +- 图像 Base URL:留空则复用主配置的 Base URL +- 图像 API Key:留空则复用主配置的 Key +- 图像模型:默认 `dall-e-3`,智谱可用 `cogview-3`,其他兼容服务填对应模型名 + +### AI 配色/主题推荐 + +在对话中输入「给这套演示换个配色」「推荐一个适合科技主题的主题」等,AI 会返回 6 色配色方案 + 推荐背景,确认后应用为新主题(自动存入自定义主题库)。 + +## 📐 元素与图表 + +### 图表(8 种) + +选中图表元素后,右侧属性面板「图表类型」下拉可切换: + +| 类型 | 代号 | 适用场景 | +|------|------|----------| +| 柱状图 | `bar` | 离散类型对比(默认) | +| 条形图 | `hbar` | 标签较长的横向对比 | +| 折线图 | `line` | 时间序列/趋势变化 | +| 面积图 | `area` | 累计趋势/体量对比 | +| 饼图 | `pie` | 占比构成 | +| 环形图 | `doughnut` | 轻量占比 | +| 雷达图 | `radar` | 多维度能力对比(≥3 维) | +| 进度图 | `progress` | 完成率/百分比 | + +属性面板还可切换「图例」与「网格线」显示。 + +**数据格式(两种):** + +单系列(向后兼容): +```json +[ {"label":"配图","value":65}, {"label":"文字","value":10} ] +``` + +多系列(用于柱状/折线/面积/雷达对比): +```json +{ + "series": ["Q1", "Q2"], + "items": [ + {"label":"华东", "values":[120, 150]}, + {"label":"华南", "values":[80, 95]} + ] +} +``` + +全部用 SVG 自绘,零运行时依赖。修改 content 后图表自动重绘。 + +### 表格(table) + +content 为 **Markdown 管道表格**字符串: + +``` +| 指标 | Q1 | Q2 | +|------|----|----| +| 营收 | 120 | 150 | +| 利润 | 30 | 45 | +``` + +属性面板可切换「首行表头」。 + +### 代码(code) + +content 为代码原文,等宽字体渲染,保留缩进与换行。属性面板可选填语言(仅作右上角徽标提示,不做语法高亮)。 + +### 公式(formula) + +content 为 **LaTeX 子集**字符串(不含 `$$`)。支持: + +- 上下标:`E = mc^2`、`x_1`、`a^{bc}`、`a_{ij}` +- 分数:`\frac{a}{b}` +- 根号:`\sqrt{x}`、`\sqrt[n]{x}` +- 求和/积分:`\sum_{i=1}^n x_i`、`\int_0^1 f(x)dx` +- 希腊字母与运算符:`\alpha \beta \pi \infty \leq \geq \neq \times \pm \cdot \to \rightarrow \forall \exists \partial \nabla` 等 + +渲染由内置极简渲染器处理(纯 HTML/CSS,不引入 KaTeX)。未识别的 `\xxx` 会去掉反斜杠后原样显示。 + +## 📋 页面模板 + +点工具栏 **📋 模板** 打开模板面板: + +- **内置模板**(7 个):空白页 / 标题页 / 章节页 / 三卡片 / 对比页 / 金句页 / 数据页,点击即基于模板新建一页 +- **存为模板**:输入名称 → 把当前页的元素结构(含背景)保存为用户模板,下次可复用版式 +- 自存模板可删除,内置不可删 + +模板只记录「版式 + 占位内容」,应用到新页时会重新生成 id,不会与原页发生关联。 + +## 📁 文件结构 + +``` +u-ppt/ +├── index.html # 入口(挂载点 + 模块脚本) +├── package.json # Vue 3 + Vite + TypeScript +├── vite.config.ts +├── tsconfig.json +├── src/ +│ ├── main.ts # createApp 挂载 +│ ├── App.vue # 根组件:编辑/演示模式切换 +│ ├── core/ # 纯逻辑层(无 Vue 依赖,可单测) +│ │ ├── types.ts # Deck/Slide/Element/Style 类型 +│ │ ├── store.ts # 响应式状态/localStorage/CRUD/undo-redo +│ │ ├── ai.ts # AI 引擎:流式 SSE/JSON 解析/prompt +│ │ └── sample.ts # 主题预设/元素工厂/内置 8 页示例 +│ ├── composables/ +│ │ └── useEditor.ts # 画布拖拽/缩放/选中逻辑 +│ ├── components/ +│ │ ├── editor/ +│ │ │ ├── Toolbar.vue # 顶部工具栏 +│ │ │ ├── ThumbBar.vue # 左侧缩略图 +│ │ │ ├── Canvas.vue # 中间画布 +│ │ │ ├── ElementView.vue # 单元素渲染(9 种类型) +│ │ │ ├── PropsPanel.vue # 右侧属性面板 +│ │ │ └── AddGrid.vue # 添加元素网格 +│ │ ├── present/ +│ │ │ └── PresentMode.vue # 全屏演示 +│ │ ├── ai/ +│ │ │ └── AiPanel.vue # AI 聊天面板 +│ │ └── modals/ +│ │ ├── SettingsModal.vue +│ │ └── LibraryModal.vue +│ └── styles/ # 全局 CSS(由原 css/ 平移) +│ ├── base.css +│ ├── editor.css +│ ├── present.css +│ └── chat.css +└── README.md +``` + +## 🧱 数据模型 + +元素用**百分比坐标**存储,编辑画布与全屏演示共用一份数据,自动等比缩放。可 `store.exportJSON()` 导出 / `importJSON()` 导入,便于备份与迁移。 + +## 📌 范围说明 + +纯前端工具,不含:多人协作、云同步、复杂图表(折线/饼图)、音视频嵌入、导出 PPTX/PDF。后续可扩展。 diff --git a/index.html b/index.html new file mode 100644 index 0000000..6853df7 --- /dev/null +++ b/index.html @@ -0,0 +1,16 @@ + + +
+ + +| {{ c }} |
|---|
| {{ c }} | +
+ {{ el.content }}
+ {{ s.lang }}
+
+
+
+
+
+
+
+
+
+
+
+
+ 点击画布元素以编辑样式
或在下方添加新元素
保存多套演示文稿到本地,随时切换。
+ +配置大模型服务商。数据仅保存在本地浏览器。
+ +$1')
+ // 下标 ~text~(与删除线区分:单个 ~)
+ s = s.replace(/(?$1')
+ // 上标 ^text^
+ s = s.replace(/\^([^\^\s][^\^]*?)\^/g, '$1')
+
+ return s
+}
+
+/**
+ * 渲染多行文本:逐行 renderInline,用 ${html}`
+ if (seg.sup) html = `${html}`
+ if (seg.sub) html = `${html}`
+ if (seg.strike) html = `