From e442296757b60741a2ab4908f889a9f1945bcbe7 Mon Sep 17 00:00:00 2001 From: liuziting Date: Thu, 22 Jan 2026 08:50:54 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E6=9B=B4=E6=96=B0README=E6=96=87?= =?UTF-8?q?=E6=A1=A3=E5=86=85=E5=AE=B9=E4=B8=8E=E7=BB=93=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit refactor(useThinkFlow): 改进节点布局算法以支持动态尺寸计算 style(i18n): 修改"deepDive"翻译为"回答"以更准确表达功能 --- README.md | 203 ++++++++++++------------------- README.zh-CN.md | 206 ++++++++++++-------------------- src/composables/useThinkFlow.ts | 102 ++++++++++++++-- src/i18n/locales/en.json | 2 +- src/i18n/locales/zh.json | 6 +- 5 files changed, 248 insertions(+), 271 deletions(-) diff --git a/README.md b/README.md index 26ac50e..68eb111 100644 --- a/README.md +++ b/README.md @@ -2,164 +2,115 @@ English | [中文](./README.zh-CN.md) -ThinkFlow AI is a lightweight, local-first idea-to-structure workspace. You type a core idea, and the app expands it into a navigable knowledge graph (modules/submodules). Each node supports follow-up expansion, deep-dive details, and optional image generation. +ThinkFlow AI is a lightweight, local-first, AI-driven mind mapping workspace. It automatically transforms a simple idea into a structured and highly visual mind map using the divergent thinking power of AI. -This repository currently uses the package name `thinkflow` (historical) while the product name is **ThinkFlow AI**. +This project aims to provide a smooth, zero-backend-config thinking assistant that offers deep analytical capabilities, supporting users during brainstorming, knowledge organization, and creative expansion. -## Highlights +--- -- **Idea expansion to graph**: generate a root node and expand into structured child nodes. -- **Context-aware follow-up**: expand a selected node with an additional requirement (follow-up input). -- **Deep dive**: generate detailed explanations for a node and show them inline. -- **Image generation (per node)**: generate/regenerate a visual for a node and preview it fullscreen. -- **Export to Markdown**: export the current graph as a Markdown outline (including deep-dive content). -- **Local-first settings**: API mode and endpoints are stored in `localStorage` (no backend needed). -- **Bilingual UI**: built-in English/Chinese UI with a one-click toggle. +## 🌟 Key Highlights -## Tech Stack +- **🚀 Idea to Graph**: Just enter a core concept, and the AI will automatically generate a root node and expand into multiple insightful child nodes. +- **🧠 Context-Aware Follow-up**: Support for follow-up questions on any node. The AI considers the "thinking path" from root to the current node to ensure logical consistency. +- **📖 Deep Answer (Deep Dive)**: More than just keywords—click "Answer" to have the AI generate detailed analysis, background, and applications for a node, rendered in Markdown. +- **🎨 Intelligent Visual Aid**: Integrated AI image generation creates realistic visuals based on node content, enhancing the visual impact and memory retention of your mind map. +- **📊 Session Summary**: One-click summary of the entire canvas, extracting core logic, main dimensions, and final insights. +- **📂 Structured Export**: Export the entire mind map as a standard Markdown outline, including node descriptions, answers, and hierarchical structure. +- **🔐 Local-First Configuration**: All API configurations (Key, Base URL, etc.) and language preferences are stored in the browser's `localStorage`, ensuring privacy and security. -- **Vue 3** (Composition API) -- **Vite 5** -- **TypeScript** -- **Tailwind CSS** -- **VueFlow** (`@vue-flow/core`, `background`, `controls`, `minimap`) -- **vue-i18n** -- **lucide-vue-next** (icons) +--- -## Project Structure +## 🛠️ Tech Stack -Key files you will touch most often: +- **Framework**: [Vue 3](https://vuejs.org/) (Composition API) +- **Build Tool**: [Vite 5](https://vitejs.dev/) +- **Language**: [TypeScript](https://www.typescriptlang.org/) +- **Styling**: [Tailwind CSS](https://tailwindcss.com/) +- **Graph Engine**: [@vue-flow/core](https://vueflow.dev/) +- **I18n**: [vue-i18n](https://vue-i18n.intlify.dev/) +- **Icon Library**: [lucide-vue-next](https://lucide.dev/) +- **Markdown Rendering**: [markdown-it](https://github.com/markdown-it/markdown-it) -- `src/App.vue`: app shell, composes the layout and wires UI to business actions. -- `src/composables/useThinkFlow.ts`: core business logic (graph operations, API calls, persistence). -- `src/components/TopNav.vue`: top toolbar (layout, export, summary, settings, language toggle). -- `src/components/BottomBar.vue`: bottom input bar (core idea input + execute). -- `src/components/WindowNode.vue`: custom VueFlow node UI (expand/deep-dive/image/follow-up). -- `src/components/SettingsModal.vue`: API mode and custom endpoints configuration UI. -- `src/i18n/index.ts`: i18n bootstrap (default English; persists language in `localStorage`). +--- -## How It Works (High-Level) +## 📂 Code Structure Guide -ThinkFlow AI is built around a single composable: +```text +src/ +├── components/ # UI Components +│ ├── TopNav.vue # Top toolbar: Handles fit, layout, export, summary, and language toggle. +│ ├── SideNav.vue # Left side nav: Controls MiniMap, edge styles, background, and settings entry. +│ ├── BottomBar.vue # Bottom input bar: Initial entry for core ideas. +│ ├── WindowNode.vue # Custom Node: Core UI for expanding, answers, image generation, and follow-ups. +│ ├── SettingsModal.vue # API Settings: Configuration for Text and Image generation endpoints. +│ ├── SummaryModal.vue # Modal for displaying the session summary. +│ ├── ImagePreviewModal.vue # Modal for fullscreen node image preview. +│ └── ResetConfirmModal.vue # Confirmation modal for canvas reset. +├── composables/ # Core Logic Layer +│ └── useThinkFlow.ts # Core Business Hook: Manages node state, API calls, layout algorithms, and persistence. +├── i18n/ # Internationalization +│ ├── locales/ # Language packs (zh.json, en.json) +│ └── index.ts # I18n initialization +├── App.vue # App Entry: Composes components and configures the VueFlow environment. +└── main.ts # Program Entry Point +``` -- `useThinkFlow` owns all reactive state for nodes/edges and UI flags. -- UI components are “thin”: they render and forward events (expand, deep-dive, image, export). -- The graph is rendered with VueFlow using a custom node type (`window`). -- Settings are stored in `localStorage`: - - language (`language`) - - API mode + chat/image endpoints/models/keys +### Core Design Principles -## Getting Started +- **State Management**: Uses `useThinkFlow` composable to centralize management of nodes, edges, and UI states, distributed to child components via `App.vue`. +- **Layout Algorithm**: Implements a horizontal tree layout algorithm based on dynamic subtree height calculations, automatically adapting to node size changes. +- **API Communication**: Compatible with OpenAI-style endpoints, supporting custom model names and Base URLs. -### Prerequisites +--- -- Node.js **18+** (required by Vite 5) -- npm (or pnpm/yarn; examples use npm) +## 🚀 Quick Start -### Install +### 1. Prerequisites + +- Node.js 18+ +- npm or pnpm + +### 2. Install Dependencies ```bash npm install ``` -### Run Dev Server +### 3. Run Development Server ```bash npm run dev ``` -Then open the URL printed by Vite (usually `http://localhost:5173`). +Access `http://localhost:5173` to start. -### Build +--- -```bash -npm run build -``` +## ⚙️ Configuration -### Preview Production Build +This project does not provide a backend; users must configure their own API endpoints: -```bash -npm run preview -``` +1. Click the **Settings** icon at the bottom of the left sidebar. +2. **Default Mode**: Uses pre-configured trial endpoints (subject to rate limits). +3. **Custom Mode**: + - **Text Gen**: Enter OpenAI-compatible `Base URL`, `Model Name`, and `API Key`. + - **Image Gen**: Enter configuration for `dall-e` or other image generation APIs. -## Configuration +--- -### Custom Mode (Bring Your Own Endpoint) +## 📖 Usage Manual -Open **Settings** in the UI: +1. **Start a Session**: Enter your idea in the bottom input (e.g., "Future of Urban Transportation") and press Enter. +2. **Node Actions**: + - **Expand**: Click the `+` on a node or enter a follow-up requirement to generate child nodes. + - **Answer**: Click the book icon for a deep analysis of that node. + - **Image**: Click the image icon to generate a visual reference for the idea. +3. **Organize Canvas**: + - **Layout**: Click the "Layout" button at the top to automatically organize all nodes. + - **Export**: Click the "Export" button at the top to get a Markdown copy of your work. -- Switch to **Custom** -- Configure **Text Generation** (chat completion) - - `baseUrl` (POST endpoint) - - `model` - - `apiKey` -- Configure **Image Generation** - - `baseUrl` (POST endpoint) - - `model` - - `apiKey` +--- -These fields are saved into `localStorage` automatically. +## 📄 License -## Features Guide - -### 1) Expand From a Core Idea - -1. Type a core idea in the bottom input. -2. Press Enter or click **Execute**. -3. A root node appears and the app generates child nodes. - -### 2) Expand a Specific Node (Follow-Up) - -1. Click into a node’s follow-up input. -2. Type an additional requirement. -3. Press Enter to expand using the context path (root → current node). - -### 3) Deep Dive a Node - -Click **Deep Dive** on a node to generate a detailed explanation. The content will be stored on the node and can be reopened without re-requesting (unless you expand further). - -### 4) Generate/Preview Node Image - -- Click **IMG** to generate an image for a node. -- Click the image to open fullscreen preview. -- Use the regenerate action to request a new image. - -### 5) Export Markdown - -Use **Export** in the top toolbar: - -- Root becomes the Markdown title -- Child nodes become an indented list -- Deep-dive text is exported as blockquote content under the node - -## Third-Party Integrations - -- **Microsoft Clarity**: included in `index.html` for analytics. -- **VueFlow plugins**: - - Background (Dots/Lines) - - Controls (zoom/fit) - - MiniMap (overview) - -## Internationalization (i18n) - -- Default locale: **English** -- Supported: `en`, `zh` -- Language choice is stored in `localStorage` key `language` - -To add a new language: - -1. Add a JSON file in `src/i18n/locales/` -2. Register it in `src/i18n/index.ts` -3. Add a toggle option in the UI (currently a simple EN/ZH switch) - -## Common Troubleshooting - -- **CORS / Failed to fetch**: if you use a custom endpoint, ensure it allows browser requests and supports proper CORS headers. -- **401/403**: verify the API key and `Authorization: Bearer ...` format. -- **429**: rate limited by the provider; retry later. - -## Scripts - -- `npm run dev`: start Vite dev server -- `npm run build`: production build -- `npm run preview`: preview the build output locally +MIT License diff --git a/README.zh-CN.md b/README.zh-CN.md index 974d5b9..b12f33b 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -2,165 +2,115 @@ [English](./README.md) | 中文 -ThinkFlow AI 是一个轻量、偏本地化(Local-first)的“从想法到结构化图谱”的工作台:输入一个核心想法,应用会把它扩展为可浏览的知识图谱(模块/子模块)。每个节点支持继续追问扩展、深挖详情,以及可选的配图生成。 +ThinkFlow AI 是一个轻量级、Local-first(本地优先)的 AI 驱动思维导图工作台。它能够将你的一个简单想法,通过 AI 的发散性思维,自动化地扩展为结构清晰、可视化程度高的思维图谱。 -## 亮点功能 +本项目旨在提供一个极致流畅、无需复杂后端配置、且具备深度解析能力的思维助手,帮助用户在头脑风暴、知识梳理和创意发散时获得持续的灵感支持。 -- **想法扩展为图谱**:生成根节点并扩展出结构化子节点。 -- **上下文追问扩展**:对选中节点追加需求(follow-up 输入)并基于路径上下文扩展。 -- **深挖详情**:为节点生成更详细的解释/补充内容并在节点内展开展示。 -- **节点配图(可重试)**:为单个节点生成/重新生成图片,并支持全屏预览。 -- **导出 Markdown**:将当前图谱导出为 Markdown 大纲(包含深挖内容)。 -- **本地配置**:API 模式与配置保存到 `localStorage`,无需额外后端。 -- **中英双语**:内置英文/中文 UI,一键切换。 +--- -## 技术栈 +## 🌟 核心亮点 -- **Vue 3**(Composition API) -- **Vite 5** -- **TypeScript** -- **Tailwind CSS** -- **VueFlow**(`@vue-flow/core` + background/controls/minimap) -- **vue-i18n** -- **lucide-vue-next**(图标) +- **🚀 从想法到图谱**:只需输入一个核心概念,AI 会自动生成根节点并向外发散多个具有深度的子节点。 +- **🧠 上下文关联追问**:支持针对任意节点进行追问,AI 在生成时会参考“从根到当前节点”的思考路径,确保生成的逻辑一致性。 +- **📖 深度回答(Deep Dive)**:不再仅仅是关键词,点击“回答”即可让 AI 针对该节点生成详尽的解析、背景及应用场景,支持 Markdown 渲染。 +- **🎨 智能视觉辅助**:集成 AI 生图能力,可根据节点内容生成写实风格的配图,提升思维导图的视觉冲击力与记忆点。 +- **📊 全篇智能总结**:一键梳理整张画布的所有想法,提取核心逻辑、主要维度和最终洞察,生成精炼的全局总结。 +- **📂 结构化导出**:支持将整个思维图谱导出为标准的 Markdown 大纲,包含节点描述、回答内容及层级结构。 +- **🔐 本地化配置**:所有的 API 配置(Key、Base URL 等)和语言偏好均保存在浏览器 `localStorage` 中,隐私且安全。 -## 项目结构 +--- -你最常关注的文件: +## 🛠️ 技术栈 -- `src/App.vue`:应用壳层,组合布局与事件转发。 -- `src/composables/useThinkFlow.ts`:核心业务逻辑(节点/边操作、API 调用、持久化)。 -- `src/components/TopNav.vue`:顶部工具栏(布局、导出、总结、设置、语言切换)。 -- `src/components/BottomBar.vue`:底部输入条(核心想法输入 + 执行)。 -- `src/components/WindowNode.vue`:自定义节点 UI(扩展/深挖/配图/follow-up)。 -- `src/components/SettingsModal.vue`:API 模式与自定义端点配置 UI。 -- `src/i18n/index.ts`:i18n 初始化(默认英文;语言写入 `localStorage`)。 +- **框架**: [Vue 3](https://vuejs.org/) (Composition API) +- **构建工具**: [Vite 5](https://vitejs.dev/) +- **语言**: [TypeScript](https://www.typescriptlang.org/) +- **样式**: [Tailwind CSS](https://tailwindcss.com/) +- **画布引擎**: [@vue-flow/core](https://vueflow.dev/) +- **国际化**: [vue-i18n](https://vue-i18n.intlify.dev/) +- **图标库**: [lucide-vue-next](https://lucide.dev/) +- **Markdown 渲染**: [markdown-it](https://github.com/markdown-it/markdown-it) -## 核心原理(高层) +--- -应用围绕一个 composable 构建: +## 📂 代码结构指南 -- `useThinkFlow` 统一持有:节点/边数据、UI 状态、网络请求、错误处理、导出能力。 -- 组件尽量“轻”:负责渲染与事件转发(expand、deep-dive、image、export 等)。 -- 画布由 VueFlow 渲染,节点使用自定义类型 `window`。 -- 配置持久化到 `localStorage`: - - 语言:`language` - - API 模式与 chat/image 的 baseUrl/model/apiKey +```text +src/ +├── components/ # UI 组件库 +│ ├── TopNav.vue # 顶部工具栏:处理适配、布局、导出、总结、语言切换等全局动作 +│ ├── SideNav.vue # 左侧配置栏:控制小地图、连线样式、背景网格及 API 设置入口 +│ ├── BottomBar.vue # 底部输入框:核心想法的初始入口 +│ ├── WindowNode.vue # 自定义节点:核心 UI,包含扩展、回答、生图及追问逻辑 +│ ├── SettingsModal.vue # API 配置弹窗:支持文本/图片生成的 Base URL 和 Key 设置 +│ ├── SummaryModal.vue # 全篇总结展示弹窗 +│ ├── ImagePreviewModal.vue # 节点配图全屏预览弹窗 +│ └── ResetConfirmModal.vue # 画布重置确认弹窗 +├── composables/ # 核心逻辑层 +│ └── useThinkFlow.ts # 核心业务 Hook:管理节点状态、API 调用、布局算法、持久化逻辑等 +├── i18n/ # 国际化 +│ ├── locales/ # 语言包 (zh.json, en.json) +│ └── index.ts # i18n 初始化 +├── App.vue # 应用入口:组合各组件并配置 VueFlow 画布环境 +└── main.ts # 程序起点 +``` -## 快速开始 +### 核心逻辑设计 -### 环境要求 +- **状态管理**: 采用 `useThinkFlow` 组合式函数统一管理画布节点、连线及 UI 状态。通过解构方式在 `App.vue` 中分发给各子组件。 +- **布局算法**: 实现了基于子树高度动态计算的“横向树形”排版算法,能够自动适配节点展开后的尺寸变化,确保图谱整齐。 +- **API 通信**: 适配 OpenAI 格式接口,支持自定义模型名称及 Base URL。 -- Node.js **18+**(Vite 5 要求) -- npm(也可以用 pnpm/yarn;示例使用 npm) +--- -### 安装依赖 +## 🚀 快速开始 + +### 1. 环境准备 + +- Node.js 18+ +- npm 或 pnpm + +### 2. 安装依赖 ```bash npm install ``` -### 启动开发环境 +### 3. 启动开发服务器 ```bash npm run dev ``` -打开 Vite 输出的地址(通常是 `http://localhost:5173`)。 +访问 `http://localhost:5173` 即可开始使用。 -### 构建 +--- -```bash -npm run build -``` +## ⚙️ 配置说明 -### 预览构建产物 +本项目不提供后端服务,需用户自行配置 API 接口: -```bash -npm run preview -``` +1. 点击左侧工具栏底部的 **设置** 图标。 +2. **默认模式**: 预设了部分体验接口(可能有请求限制)。 +3. **自定义模式**: + - **文本生成**: 填入 OpenAI 兼容格式的 `Base URL`、`Model Name` 和 `API Key`。 + - **图片生成**: 填入支持 `dall-e` 格式或其他生图 API 的配置。 -## 配置说明 +--- -### 自定义模式:自带端点(BYO Endpoint) +## 📖 功能使用手册 -在界面里打开 **Settings**: +1. **开启新会话**: 在底部输入框输入您的想法(如“未来城市的交通方式”),按回车。 +2. **节点操作**: + - **扩展**: 点击节点右侧的 `+` 或输入后续要求,AI 会继续在该分支下生成子节点。 + - **回答**: 点击书本图标,获取该节点的深度解析。 + - **生图**: 点击图片图标,为该想法生成视觉参考。 +3. **整理画布**: + - **布局**: 点击顶部“布局”按钮,自动按层级整理所有节点。 + - **导出**: 点击顶部“导出”按钮,获取 Markdown 格式的内容副本。 -- 切换到 **Custom** -- 配置 **文本生成(chat completion)** - - `baseUrl`(POST 接口地址) - - `model` - - `apiKey` -- 配置 **图片生成** - - `baseUrl`(POST 接口地址) - - `model` - - `apiKey` +--- -这些字段会自动保存到 `localStorage`。 +## 📄 开源协议 -## 功能使用说明 - -### 1)从核心想法生成图谱 - -1. 在底部输入框输入核心想法 -2. 回车或点击 **Execute** -3. 生成根节点并自动扩展出子节点 - -### 2)对某个节点继续扩展(Follow-Up) - -1. 在节点的 follow-up 输入框填写“追加需求” -2. 回车触发扩展 -3. 扩展时会携带“从根到当前节点”的上下文路径,保证更贴合当前分支 - -### 3)深挖节点详情 - -点击节点上的 **Deep Dive**: - -- 生成更长的解释/拓展内容 -- 内容会写回节点并可重复打开(不必每次都重新请求) - -### 4)节点配图与预览 - -- 点击节点上的 **IMG** 生成配图 -- 点击图片打开全屏预览 -- 支持在预览层或节点上进行重新生成 - -### 5)导出 Markdown - -顶部工具栏点击 **Export**: - -- 根节点作为一级标题 -- 子节点按缩进列表输出 -- 深挖内容作为引用块输出到对应节点下方 - -## 第三方集成与插件 - -- **Microsoft Clarity**:在 `index.html` 中引入,用于分析与统计。 -- **VueFlow 插件**: - - Background(Dots/Lines) - - Controls(缩放/适配) - - MiniMap(总览) - -## 国际化(i18n) - -- 默认语言:**英文** -- 已支持:`en`、`zh` -- 语言选择写入 `localStorage` 的 `language` - -新增语言建议步骤: - -1. 在 `src/i18n/locales/` 添加对应 JSON -2. 在 `src/i18n/index.ts` 注册 messages -3. 在 UI 中扩展语言切换逻辑(目前为 EN/ZH 双向切换) - -## 常见问题排查 - -- **CORS / Failed to fetch**:使用自定义端点时,确保支持浏览器跨域请求并正确返回 CORS 响应头。 -- **401/403**:检查 API Key 是否正确,以及是否使用 `Authorization: Bearer ...`。 -- **429**:触发限流,稍后重试。 - -## Scripts - -- `npm run dev`:启动开发服务器 -- `npm run build`:构建生产包 -- `npm run preview`:本地预览构建产物 +MIT License diff --git a/src/composables/useThinkFlow.ts b/src/composables/useThinkFlow.ts index 254546b..ba54311 100644 --- a/src/composables/useThinkFlow.ts +++ b/src/composables/useThinkFlow.ts @@ -510,35 +510,112 @@ export function useThinkFlow({ t, locale }: { t: Translate; locale: Ref /** * 布局:从根节点开始按“横向树形”重新排布节点位置 - * - 主要用于整理节点过多导致的视觉拥挤 + * - 动态计算节点宽高与子树高度,确保在节点展开(回答/生图)后仍能整齐排布 */ const resetLayout = () => { const rootNode = flowNodes.value.find(n => n.data.type === 'root') if (!rootNode) return + const nodeGapX = 150 // 节点层级间的横向间距 + const nodeGapY = 40 // 同级节点间的纵向间距 + + /** + * 获取节点的实际尺寸,优先使用已测量尺寸,否则使用默认值 + */ + const getNodeSize = (node: any) => ({ + width: node.dimensions?.width ?? node.measured?.width ?? 280, + height: node.dimensions?.height ?? node.measured?.height ?? 180 + }) + + // 存储每个节点及其子树所需的总高度 + const subtreeHeights = new Map() + + /** + * 第一遍遍历:递归计算每个节点及其子树占用的总高度 + */ + const calculateSubtreeHeight = (nodeId: string): number => { + const node = flowNodes.value.find(n => n.id === nodeId) + if (!node || node.hidden) return 0 + + const size = getNodeSize(node) + const children = flowEdges.value + .filter(e => e.source === nodeId) + .map(e => e.target) + .filter(id => { + const childNode = flowNodes.value.find(n => n.id === id) + return childNode && !childNode.hidden + }) + + if (children.length === 0) { + subtreeHeights.set(nodeId, size.height) + return size.height + } + + let childrenTotalHeight = 0 + children.forEach((childId, index) => { + childrenTotalHeight += calculateSubtreeHeight(childId) + if (index < children.length - 1) { + childrenTotalHeight += nodeGapY + } + }) + + // 节点自身高度与子树高度取较大值 + const totalHeight = Math.max(size.height, childrenTotalHeight) + subtreeHeights.set(nodeId, totalHeight) + return totalHeight + } + + // 开始计算 + calculateSubtreeHeight(rootNode.id) + const visited = new Set() - const layoutNode = (nodeId: string, x: number, y: number) => { + + /** + * 第二遍遍历:根据计算出的子树高度,递归设置节点位置 + * @param nodeId 当前节点 ID + * @param x 当前起始 X 坐标 + * @param ySubtreeTop 当前子树顶部的 Y 坐标 + */ + const layoutNode = (nodeId: string, x: number, ySubtreeTop: number) => { if (visited.has(nodeId)) return visited.add(nodeId) const node = flowNodes.value.find(n => n.id === nodeId) - if (node) { - node.position = { x, y } + if (!node || node.hidden) return - const childEdges = flowEdges.value.filter(e => e.source === nodeId) - childEdges.forEach((edge, index) => { - const offsetX = 450 - const totalHeight = (childEdges.length - 1) * 280 - const startY = y - totalHeight / 2 - const offsetY = index * 280 + const size = getNodeSize(node) + const subtreeHeight = subtreeHeights.get(nodeId) || size.height - layoutNode(edge.target, x + offsetX, startY + offsetY) + // 将节点放置在子树区域的垂直中心 + node.position = { + x, + y: ySubtreeTop + (subtreeHeight - size.height) / 2 + } + + const children = flowEdges.value + .filter(e => e.source === nodeId) + .map(e => e.target) + .filter(id => { + const childNode = flowNodes.value.find(n => n.id === id) + return childNode && !childNode.hidden + }) + + if (children.length > 0) { + const nextX = x + size.width + nodeGapX + let currentY = ySubtreeTop + + children.forEach(childId => { + const childSubtreeHeight = subtreeHeights.get(childId) || 0 + layoutNode(childId, nextX, currentY) + currentY += childSubtreeHeight + nodeGapY }) } } - layoutNode(rootNode.id, 50, 300) + // 从根节点开始排版 + layoutNode(rootNode.id, 50, 100) + // 延迟执行 fitView 确保位置更新已应用 setTimeout(() => { fitView({ padding: 0.2, duration: 800 }) }, 100) @@ -990,4 +1067,3 @@ export function useThinkFlow({ t, locale }: { t: Translate; locale: Ref expandIdea } } - diff --git a/src/i18n/locales/en.json b/src/i18n/locales/en.json index f94d2f7..7c6faa1 100644 --- a/src/i18n/locales/en.json +++ b/src/i18n/locales/en.json @@ -72,7 +72,7 @@ "coreIdea": "Core Idea", "followUp": "Ask a follow-up...", "imgAction": "IMG", - "deepDive": "Detail", + "deepDive": "Answer", "view": "View", "regenerate": "Regenerate", "mainTitle": "Root Node", diff --git a/src/i18n/locales/zh.json b/src/i18n/locales/zh.json index 98b4769..ebd7fd3 100644 --- a/src/i18n/locales/zh.json +++ b/src/i18n/locales/zh.json @@ -72,14 +72,14 @@ "coreIdea": "核心想法", "followUp": "输入后续问题...", "imgAction": "生图", - "deepDive": "详情", + "deepDive": "回答", "view": "查看", "regenerate": "重新生成", "mainTitle": "主节点", "moduleTitle": "子节点" }, "prompts": { - "system": "你是一个思维发散助手,帮助用户将想法逐层展开,构建思维树。\n\n工作流程:\n1. 用户给出一个初始想法(或选择一个已有节点继续追问)。\n2. 你需要根据【思考上下文路径】(即从根节点到当前节点的思考链路)来理解用户的意图。\n3. 生成 3-5 个更深层或相关维度的子想法。\n4. 每个子想法包含简短名称和极简描述。\n\n返回格式必须为严格 JSON:\n{'{'}\n \"nodes\": [\n {'{'} \"text\": \"子想法1名称\", \"description\": \"一句话描述\" {'}'},\n {'{'} \"text\": \"子想法2名称\", \"description\": \"一句话描述\" {'}'}\n ]\n{'}'}\n\n注意:只返回 JSON,不附加解释。", + "system": "你是一个思维发散助手,帮助用户将想法逐层展开,构建思维树。\n\n工作流程:\n1. 用户给出一个初始想法(或选择一个已有节点继续追问)。\n2. 你需要根据【思考上下文路径】(即从根节点到当前节点的思考链路)来理解用户的意图。\n3. 生成 3-5 个更深层或相关维度的子想法。\n4. 每个子想法包含简短名称和简单描述。\n\n返回格式必须为严格 JSON:\n{'{'}\n \"nodes\": [\n {'{'} \"text\": \"子想法1名称\", \"description\": \"一句话描述\" {'}'},\n {'{'} \"text\": \"子想法2名称\", \"description\": \"一句话描述\" {'}'}\n ]\n{'}'}\n\n注意:只返回 JSON,不附加解释。", "image": "这是一张高质量写实摄影风格的图片。上下文(从根到当前的概念链路):{context}。主体/概念:{topic}。详情/特征:{detail}。画面要求:真实材质与细节、准确透视与比例、自然光或电影级布光、干净背景与高级构图、色彩克制,适合作为思维导图的视觉核心。质量:超清、锐利、噪点控制自然、层次分明的景深。严禁:任何文字/水印/Logo;卡通、插画、绘本、手绘、漫画、动漫、3D 渲染感、过度滤镜、变形、模糊、低清。", "continue": "请继续深入发散", "coreIdeaPrefix": "核心想法", @@ -89,4 +89,4 @@ "deepDivePrompt": "请针对【{topic}】提供一个深度且详细的解析。要求:\n1. 结构清晰,包含背景、核心原理、关键要素和实际应用。\n2. 语言专业且易懂。\n3. 总字数控制在 300-500 字左右。\n4. 直接输出正文内容,不要包含 JSON 格式,也不要包含任何开场白或结束语。", "summaryPrompt": "你是一个思维总结专家。请根据以下提供的思维导图节点信息(包含核心想法及其发散出的所有子想法),生成一份结构化的全篇总结。\n\n节点数据如下:\n{nodes}\n\n要求:\n1. 提炼出核心主题及其背后的核心逻辑。\n2. 归纳出几个主要的维度或分支方向。\n3. 总结最终达成的洞察或结论。\n4. 语言要精炼、专业,富有启发性。\n5. 直接输出总结内容,不要包含 JSON 格式,不要有任何开场白。" } -} +} \ No newline at end of file