diff --git a/README.md b/README.md index a362dfb..55d3ae1 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,13 @@ +

+ + GitHub + +  |  + + Gitee + +

+

中文 | English @@ -60,7 +70,23 @@ Toonflow 是一款 AI 工具,能够利用 AI 技术将小说自动转化为剧 --- -# 🚀 安装与使用指南 +# 🔰 使用指南 + +## 📺 视频教程 + +https://www.bilibili.com/video/BV1na6wB6Ea2 +[![Toonflow 8 分钟快速上手 AI 视频](./docs/videoCover.png)](https://www.bilibili.com/video/BV1na6wB6Ea2) + +**Toonflow 8 分钟快速上手 AI 视频** +👉 [点击观看](https://www.bilibili.com/video/BV1na6wB6Ea2/?share_source=copy_web&vd_source=5b718c25439a901a34c7bc0c1d35b38e) + +📱 手机微信扫码观看 + +微信扫码观看 + +--- + +# 🚀 安装 ## 前置条件 @@ -74,11 +100,11 @@ Toonflow 是一款 AI 工具,能够利用 AI 技术将小说自动转化为剧 ### 1. 下载与安装 -| 操作系统 | 下载链接 | 说明 | -| :------: | :------------------------------------------------------- | :----------------------- | -| Windows | [Release](https://github.com/HBAI-Ltd/Toonflow-app/releases) | 官方发布安装包,点击下载 | -| Linux | ⚙️ 敬请期待 | 即将发布,请持续关注 | -| macOS | ⚙️ 敬请期待 | 即将发布,请持续关注 | +| 操作系统 | GitHub 下载 | Gitee 下载(国内推荐) | 说明 | +| :------: | :----------------------------------------------------------- | :---------------------------------------------------------- | :------------- | +| Windows | [Release](https://github.com/HBAI-Ltd/Toonflow-app/releases) | [Release](https://gitee.com/HBAI-Ltd/Toonflow-app/releases) | 官方发布安装包 | +| Linux | ⚙️ 敬请期待 | ⚙️ 敬请期待 | 即将发布 | +| macOS | ⚙️ 敬请期待 | ⚙️ 敬请期待 | 即将发布 | > 注意:目前仅支持 Windows 版本,其他系统将陆续开放。 @@ -86,9 +112,106 @@ Toonflow 是一款 AI 工具,能够利用 AI 技术将小说自动转化为剧 安装完成后,启动程序即可开始使用本服务。 +> ⚠️ **首次登录** +> 账号:`admin` +> 密码:`admin123` + ## 云端部署 -云端安装及部署教程正在整理中,敬请期待。 +### 一、服务器环境要求 + +- **系统**:Ubuntu 20.04+ / CentOS 7+ +- **Node.js**:23.11.1+ +- **内存**:1GB+ + +### 二、服务器部署 + +#### 1. 安装环境 + +```bash +# 安装 Node.js +curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash +source ~/.bashrc +nvm install 24 +# 安装 Yarn 和 PM2 +npm install -g yarn pm2 +``` + +#### 2. 部署项目 + +**从 GitHub 克隆:** + +```bash +cd /opt +git clone https://github.com/HBAI-Ltd/Toonflow-app.git +cd Toonflow-app +yarn install +yarn build +``` + +**从 Gitee 克隆(国内推荐):** + +```bash +cd /opt +git clone https://gitee.com/HBAI-Ltd/Toonflow-app.git +cd Toonflow-app +yarn install +yarn build +``` + +#### 3. 配置 PM2 + +创建 `pm2.json` 文件: + +```json +{ + "name": "toonflow-app", + "script": "build/app.js", + "instances": "max", + "exec_mode": "cluster", + "env": { + "NODE_ENV": "prod", + "PORT": 60000, + "OSSURL": "http://127.0.0.1:60000/" + } +} +``` + +**环境变量说明:** + +| 变量 | 说明 | +| ---------- | ---------------------------------- | +| `NODE_ENV` | 运行环境,`prod` 表示生产环境 | +| `PORT` | 服务监听端口 | +| `OSSURL` | 文件存储访问地址,用于静态资源访问 | + +--- + +#### 4. 启动服务 + +```bash +pm2 start pm2.json +pm2 startup +pm2 save +``` + +#### 5. 常用命令 + +```bash +pm2 list # 查看进程 +pm2 logs toonflow-app # 查看日志 +pm2 restart all # 重启服务 +pm2 monit # 监控面板 +``` + +#### 6. 部署前端网站 + +如需单独部署或定制前端界面,请参考前端仓库: + +- **GitHub**:[Toonflow-web](https://github.com/HBAI-Ltd/Toonflow-web) +- **Gitee**:[Toonflow-web](https://gitee.com/HBAI-Ltd/Toonflow-web) + +> 💡 **说明**:本仓库已内置编译好的前端资源,普通用户无需单独部署前端。前端仓库仅供需要二次开发的开发者使用。 --- @@ -101,7 +224,23 @@ Toonflow 是一款 AI 工具,能够利用 AI 技术将小说自动转化为剧 ## 快速启动项目 -1. **安装依赖** +1. **克隆项目** + + **从 GitHub 克隆:** + + ```bash + git clone https://github.com/HBAI-Ltd/Toonflow-app.git + cd Toonflow-app + ``` + + **从 Gitee 克隆(国内推荐):** + + ```bash + git clone https://gitee.com/HBAI-Ltd/Toonflow-app.git + cd Toonflow-app + ``` + +2. **安装依赖** 请先在项目根目录下执行以下命令以安装依赖项: @@ -109,7 +248,7 @@ Toonflow 是一款 AI 工具,能够利用 AI 技术将小说自动转化为剧 yarn install ``` -2. **启动开发环境** +3. **启动开发环境** - 使用 Node.js 运行开发服务: @@ -123,7 +262,7 @@ Toonflow 是一款 AI 工具,能够利用 AI 技术将小说自动转化为剧 yarn bun:dev #端口60000 ``` -3. **项目打包** +4. **项目打包** - 编译并生成 TypeScript 文件: @@ -137,7 +276,7 @@ Toonflow 是一款 AI 工具,能够利用 AI 技术将小说自动转化为剧 yarn dist:win ``` -4. **代码质量检查** +5. **代码质量检查** - 进行全局语法和规范检查: @@ -145,11 +284,21 @@ Toonflow 是一款 AI 工具,能够利用 AI 技术将小说自动转化为剧 yarn lint ``` +## 前端开发 + +如需修改前端界面,请前往前端仓库进行开发: + +- **GitHub**:[Toonflow-web](https://github.com/HBAI-Ltd/Toonflow-web) +- **Gitee**:[Toonflow-web](https://gitee.com/HBAI-Ltd/Toonflow-web) + +前端构建后,将 `dist` 目录内容复制到本项目的 `scripts/web` 目录即可集成。 + ## 项目结构 ``` 📂 docs/ # 文档资源 📂 scripts/ # 构建脚本与静态资源 +│ └─ 📂 web/ # 前端编译产物(内置) 📂 src/ ├─ 📂 agents/ # AI Agent 模块 ├─ 📂 lib/ # 公共库(数据库初始化、响应格式) @@ -186,6 +335,17 @@ Toonflow 是一款 AI 工具,能够利用 AI 技术将小说自动转化为剧 --- +# 🔗 相关仓库 + +| 仓库 | 说明 | GitHub | Gitee | +| ---------------- | ---------------------------------- | -------------------------------------------------- | ------------------------------------------------ | +| **Toonflow-app** | 完整客户端(本仓库,推荐普通用户) | [GitHub](https://github.com/HBAI-Ltd/Toonflow-app) | [Gitee](https://gitee.com/HBAI-Ltd/Toonflow-app) | +| **Toonflow-web** | 前端源代码(适合前端开发者) | [GitHub](https://github.com/HBAI-Ltd/Toonflow-web) | [Gitee](https://gitee.com/HBAI-Ltd/Toonflow-web) | + +> 💡 **提示**:如果您只是想使用 Toonflow,直接下载本仓库的客户端即可。前端仓库仅供需要二次开发或定制前端界面的开发者使用。 + +--- + # 📝 开发计划 我们正持续优化产品,以下为近期开发重点: @@ -207,6 +367,31 @@ Toonflow 是一款 AI 工具,能够利用 AI 技术将小说自动转化为剧 --- +# 👨‍👩‍👧‍👦 微信交流群 + +~~交流群 1~~ + +~~交流群 2~~ + +~~交流群 3~~ + +~~交流群 4~~ + +~~交流群 5~~ + +交流群 6: + +Toonflow Logo +

使用微信扫码添加,二维码过期可提交 Issues 提醒更新

+ +--- + +# 💌 联系我们 + +📧 邮箱:[ltlctools@outlook.com](mailto:ltlctools@outlook.com?subject=Toonflow咨询) + +--- + # 📜 许可证 Toonflow 基于 AGPL-3.0 协议开源发布,许可证详情:https://www.gnu.org/licenses/agpl-3.0.html @@ -217,16 +402,37 @@ Toonflow 基于 AGPL-3.0 协议开源发布,许可证详情:https://www.gnu. --- -# 💌 联系我们 +# ⭐️ 星标历史 -📧 邮箱:[ltlctools@outlook.com](mailto:ltlctools@outlook.com?subject=Toonflow咨询) +[![Star History Chart](https://api.star-history.com/svg?repos=HBAI-Ltd/Toonflow-app&type=date&legend=top-left)](https://www.star-history.com/#HBAI-Ltd/Toonflow-app&type=date&legend=top-left) --- -# ⭐️ 星标历史 +# 🙏 致谢 -[![Star History Chart](https://api.star-history.com/svg?repos=HBAI-Ltd/Toonflow-app&type=Date)](https://star-history.com/#HBAI-Ltd/Toonflow-app&Date) +感谢以下开源项目为 Toonflow 提供强大支持: -# 第三方依赖清单 +- [Express](https://expressjs.com/) - 快速、开放、极简的 Node.js Web 框架 +- [LangChain](https://js.langchain.com/) - 构建 LLM 应用的开发框架 +- [Better-SQLite3](https://github.com/WiseLibs/better-sqlite3) - 高性能 SQLite3 绑定库 +- [Sharp](https://sharp.pixelplumbing.com/) - 高性能 Node.js 图像处理库 +- [Axios](https://axios-http.com/) - 基于 Promise 的 HTTP 客户端 +- [Zod](https://zod.dev/) - TypeScript 优先的模式验证库 +- [Aigne](https://github.com/aigne-com/aigne) - LLM API 统一管理与接入中间件 +- [Electron](https://www.electronjs.org/) - 跨平台桌面应用开发框架 -请查阅`NOTICES.txt` +感谢以下组织/单位/个人为 Toonflow 提供支持: + + + + + + +
+ 算能云 Logo + + 算能云 提供算力赞助 + [官网] +
+ +完整的第三方依赖清单请查阅 `NOTICES.txt` diff --git a/docs/README.en.md b/docs/README.en.md index 87420ae..ddc867a 100644 --- a/docs/README.en.md +++ b/docs/README.en.md @@ -1,3 +1,13 @@ +

+ + GitHub + +  |  + + Gitee + +

+

中文 | English @@ -13,9 +23,9 @@ AI Short Drama Factory
- Turn novels into episodes with just a tap! + Turn novels into episodes with a tap!
- AI Script × AI Visuals × Rapid Generation 🔥 + AI Script × AI Imagery × Lightning-fast Generation 🔥

@@ -30,100 +40,229 @@

- > 🚀 **One-stop Short Drama Production**: From text to characters, from storyboards to videos, zero-barrier full-process AI automation, boosting creative efficiency by 10x+! + > 🚀 **One-stop Short Drama Workflow**: From text to character, storyboard to video, a full AI-powered process with zero threshold, boosting creative efficiency by 10x+! --- # 🌟 Main Features -Toonflow is an AI tool that leverages AI technology to automatically convert novels into scripts, combined with AI-generated images and videos for efficient short drama creation. With Toonflow, you can easily complete the entire workflow from text to visuals, making short drama production smarter and more convenient. +Toonflow is an AI tool that leverages AI technology to automatically turn novels into scripts, then uses AI to generate images and videos for efficient short drama production. With Toonflow, you can easily accomplish the entire workflow from text to visuals, making short drama creation more intelligent and convenient. - ✅ **Character Generation** - Automatically analyzes original novel text, intelligently identifies and generates character settings including appearance, personality, identity, and other detailed information, providing a reliable foundation for subsequent script and visual creation. + Automatically analyzes the original novel text, intelligently recognizes and generates character profiles, including appearance, personality, identity, etc., providing a reliable foundation for subsequent script and image creation. - ✅ **Script Generation** - Based on selected events and chapters, the system automatically generates structured scripts covering dialogue, scene descriptions, and plot progression, achieving efficient conversion from literary text to film scripts. -- ✅ **Storyboard Production** - Based on script content, intelligently generates storyboard prompts and visual designs, detailing foreground, midground, background, character dynamics, prop settings, and scene layouts. Automatically generates storyboards from scripts, providing a complete blueprint for video production. + Based on selected events and chapters, the system automatically generates structured scripts, covering dialogue, scene descriptions, and plot direction, enabling an efficient transition from literary text to screenplay. +- ✅ **Storyboard Creation** + According to the script content, it intelligently generates storyboard prompts and visual designs, detailing foreground, middle ground, background, character movements, props, and scene layouts. Automatically produces storyboards from the script, providing a comprehensive blueprint for video production. - ✅ **Video Synthesis** - Integrates AI image and video technology, enabling AI-generated video clips. Incorporates online editing with support for personalized output adjustments, making film production efficient and streamlined. + Integrates AI image and video techniques, supporting generation of video clips via AI. With built-in online editing, supports personalized adjustments and outputs, making filmmaking highly collaborative and efficient. --- # 📦 Application Scenarios -- Short video content creation -- Novel-to-film experimentation +- Short video content production +- Novel-to-film experiments - AI Literary Adaptation Tools - Script development and rapid prototyping - Video material generation --- -# 🚀 Installation and Usage Guide +# 🔰 User Guide + +## 📺 Video Tutorial + +https://www.bilibili.com/video/BV1na6wB6Ea2 +[![Toonflow 8-minute Quick Start AI Video](./videoCover.png)](https://www.bilibili.com/video/BV1na6wB6Ea2) + +**Toonflow 8-Minute Quick Start AI Video** +👉 [Click to watch](https://www.bilibili.com/video/BV1na6wB6Ea2/?share_source=copy_web&vd_source=5b718c25439a901a34c7bc0c1d35b38e) + +📱 Watch via WeChat QR scan + +Watch on WeChat + +--- + +# 🚀 Installation ## Prerequisites Before installing and using this software, please prepare the following: -- ✅ Large Language Model AI service API endpoint. -- ✅ Sora or Doubao video service API endpoint -- ✅ Nano Banana Pro image generation model service API endpoint +- ✅ Large Language Model AI service endpoint. +- ✅ Sora or Doubao video service endpoint +- ✅ Nano Banana Pro image generation model service endpoint ## Local Installation -### 1. Download and Install +### 1. Download & Install -| Operating System | Download Link | Description | -| :--------------: | :------------------------------------------------------------ | :------------------------------ | -| Windows | [Release](https://github.com/HBAI-Ltd/Toonflow-app/releases) | Official release package, click to download | -| Linux | ⚙️ Coming Soon | Coming soon, stay tuned | -| macOS | ⚙️ Coming Soon | Coming soon, stay tuned | +| Operating System | GitHub Download | Gitee Download (Recommended for China) | Note | +| :--------------: | :------------------------------------------------------ | :---------------------------------------------------------- | :----------------- | +| Windows | [Release](https://github.com/HBAI-Ltd/Toonflow-app/releases) | [Release](https://gitee.com/HBAI-Ltd/Toonflow-app/releases) | Official installer | +| Linux | ⚙️ Coming soon | ⚙️ Coming soon | To be released | +| macOS | ⚙️ Coming soon | ⚙️ Coming soon | To be released | -> Note: Currently only Windows version is supported, other systems will be available soon. +> Note: Currently, only Windows is supported. Other systems will be gradually supported. -### 2. Start Service +### 2. Launch the Service -After installation, launch the program to start using the service. +After installation, start the program to use the service. + +> ⚠️ **First login** +> Account: `admin` +> Password: `admin123` ## Cloud Deployment -Cloud installation and deployment tutorials are being prepared, stay tuned. +### I. Server Requirements + +- **OS**: Ubuntu 20.04+ / CentOS 7+ +- **Node.js**: 23.11.1+ +- **RAM**: 1GB+ + +### II. Server Deployment + +#### 1. Install the Environment + +```bash +# Install Node.js +curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash +source ~/.bashrc +nvm install 24 +# Install Yarn & PM2 +npm install -g yarn pm2 +``` + +#### 2. Deploy the Project + +**Clone from GitHub:** + +```bash +cd /opt +git clone https://github.com/HBAI-Ltd/Toonflow-app.git +cd Toonflow-app +yarn install +yarn build +``` + +**Clone from Gitee (recommended in China):** + +```bash +cd /opt +git clone https://gitee.com/HBAI-Ltd/Toonflow-app.git +cd Toonflow-app +yarn install +yarn build +``` + +#### 3. Configure PM2 + +Create a `pm2.json` file: + +```json +{ + "name": "toonflow-app", + "script": "build/app.js", + "instances": "max", + "exec_mode": "cluster", + "env": { + "NODE_ENV": "prod", + "PORT": 60000, + "OSSURL": "http://127.0.0.1:60000/" + } +} +``` + +**Environment Variable Description:** + +| Variable | Description | +| ------------ | ------------------------------------------- | +| `NODE_ENV` | Runtime environment, `prod` means production| +| `PORT` | Service listening port | +| `OSSURL` | File storage access address for static files| --- -# 🔧 Development Process Guide +#### 4. Start the Service -## Development Environment Setup +```bash +pm2 start pm2.json +pm2 startup +pm2 save +``` -- **Node.js**: Version 23.11.1 or above required -- **Yarn**: Recommended as the project package manager +#### 5. Common Commands -## Quick Start +```bash +pm2 list # List processes +pm2 logs toonflow-app # View logs +pm2 restart all # Restart all services +pm2 monit # Monitoring panel +``` -1. **Install Dependencies** +#### 6. Deploy the Frontend Website - Please first run the following command in the project root directory to install dependencies: +To deploy or customize the frontend separately, refer to the frontend repo: + +- **GitHub**: [Toonflow-web](https://github.com/HBAI-Ltd/Toonflow-web) +- **Gitee**: [Toonflow-web](https://gitee.com/HBAI-Ltd/Toonflow-web) + +> 💡 **Note**: This repo includes pre-compiled frontend assets; regular users don’t need to deploy frontend separately. The frontend repo is for developers needing secondary development. + +--- + +# 🔧 Development Workflow Guide + +## Development Environment Preparation + +- **Node.js**: Version 23.11.1+ +- **Yarn**: Recommended package manager + +## Quick Project Startup + +1. **Clone the project** + + **From GitHub:** + + ```bash + git clone https://github.com/HBAI-Ltd/Toonflow-app.git + cd Toonflow-app + ``` + + **From Gitee (china):** + + ```bash + git clone https://gitee.com/HBAI-Ltd/Toonflow-app.git + cd Toonflow-app + ``` + +2. **Install Dependencies** + + Run the following in the root directory: ```bash yarn install ``` -2. **Start Development Environment** +3. **Start Development Server** - - Run development service with Node.js: + - Launch dev server with Node.js: ```bash yarn dev #port 60000 ``` - - Run development service quickly with Bun: + - Use Bun to quickly start dev server: ```bash yarn bun:dev #port 60000 ``` -3. **Project Build** +4. **Build the Project** - Compile and generate TypeScript files: @@ -131,32 +270,42 @@ Cloud installation and deployment tutorials are being prepared, stay tuned. yarn build ``` - - Package as Windows platform executable: + - Package as a Windows executable: ```bash yarn dist:win ``` -4. **Code Quality Check** +5. **Code Quality Check** - - Perform global syntax and standard checks: + - Lint globally for syntax and style: ```bash yarn lint ``` +## Frontend Development + +To modify the frontend, go to the frontend repo: + +- **GitHub**: [Toonflow-web](https://github.com/HBAI-Ltd/Toonflow-web) +- **Gitee**: [Toonflow-web](https://gitee.com/HBAI-Ltd/Toonflow-web) + +After building the frontend, copy the contents of the `dist` folder into this project’s `scripts/web` directory for integration. + ## Project Structure ``` -📂 docs/ # Documentation resources +📂 docs/ # Documentation 📂 scripts/ # Build scripts and static resources +│ └─ 📂 web/ # Embedded frontend build output 📂 src/ ├─ 📂 agents/ # AI Agent modules -├─ 📂 lib/ # Common libraries (database initialization, response format) +├─ 📂 lib/ # Shared libs (DB init, response format) ├─ 📂 middleware/ # Middleware -├─ 📂 routes/ # Route modules +├─ 📂 routes/ # Routing modules │ ├─ 📂 assets/ # Asset management -│ ├─ 📂 index/ # Homepage +│ ├─ 📂 index/ # Home page │ ├─ 📂 novel/ # Novel management │ ├─ 📂 other/ # Other features │ ├─ 📂 outline/ # Outline management @@ -170,63 +319,121 @@ Cloud installation and deployment tutorials are being prepared, stay tuned. │ └─ 📂 video/ # Video generation ├─ 📂 types/ # TypeScript type declarations ├─ 📂 utils/ # Utility functions -├─ 📄 app.ts # Application entry -├─ 📄 core.ts # Route core -├─ 📄 env.ts # Environment variable handling +├─ 📄 app.ts # App entry point +├─ 📄 core.ts # Routing core +├─ 📄 env.ts # Env variable handling ├─ 📄 err.ts # Error handling ├─ 📄 router.ts # Route registration -└─ 📄 utils.ts # General utilities -📂 uploads/ # Upload file directory +└─ 📄 utils.ts # Common tools +📂 uploads/ # Uploads 📄 LICENSE # License -📄 NOTICES.txt # Third-party dependency declarations -📄 package.json # Project configuration +📄 NOTICES.txt # 3rd-party notices +📄 package.json # Project config 📄 README.md # Project description -📄 tsconfig.json # TypeScript configuration +📄 tsconfig.json # TypeScript config ``` --- +# 🔗 Related Repos + +| Repository | Description | GitHub | Gitee | +| ----------------- | ------------------------------------- | -------------------------------------------------- | ------------------------------------------------ | +| **Toonflow-app** | Full client (this repo, for users) | [GitHub](https://github.com/HBAI-Ltd/Toonflow-app) | [Gitee](https://gitee.com/HBAI-Ltd/Toonflow-app) | +| **Toonflow-web** | Frontend source (for devs) | [GitHub](https://github.com/HBAI-Ltd/Toonflow-web) | [Gitee](https://gitee.com/HBAI-Ltd/Toonflow-web) | + +> 💡 **Tip**: If you just want to use Toonflow, download the client from this repo. The web repo is only for frontend customization/development. + +--- + # 📝 Development Roadmap -We are continuously optimizing the product. Here are the recent development priorities: +We continue to optimize the product. Key focuses for the near future: -1. Core Feature Upgrades +1. Core Function Upgrades -- `🧩 Prompt Enhancement Generation Agent` AI-powered intelligent video prompt enhancement, automatic storyboard script decomposition, supporting multi-shot intelligent fusion and smooth transitions -- `📄 Multi-format Text Support` Extending intelligent parsing beyond novels to scripts, comic scripts, game dialogue texts, and other formats +- `🧩 Prompt Refinement Agent` AI-enhanced prompt generation for videos, auto-parsing storyboards, intelligent multi-shot fusion and smooth transitions +- `📄 Multi-format Text Support` Extending to scripts, manga scripts, game dialogue text, and more formats beyond novels -2. Production Workflow Optimization +2. Production Flow Optimization -- `👗 Character Costume and Props Management` Strengthen costume, makeup, and prop consistency for long-form content, supporting multi-episode associated memory and automatic outfit generation -- `📦 Batch Processing/Task Queue` Support multi-chapter simultaneous processing, background task management, real-time progress monitoring, and interruption recovery +- `👗 Character Costume & Props Management` Improved consistency for costumes, makeup, props across long content, support for multi-episode memory and auto costume generation +- `📦 Batch Processing/Task Queues` Process multiple chapters at once, backend task management, real-time monitoring and resume-on-interrupt 3. Visual Generation Enhancement -- `🎭 Multi-style Template Library` Built-in multiple visual style packages, supporting one-click style conversion and user-defined style saving -- `⏱️ Intelligent Rhythm Analysis/Optimization` Analyze plot emotion curves, automatically suggest climax points and rhythm changes, optimize storyboard arrangement and production workflow +- `🎭 Multi-style Template Library` Bundled visual style packs, one-click style swap, user-defined style saving +- `⏱️ Intelligent Rhythm Analysis/Optimization` Analyze plot emotional arcs, auto-suggest climaxes and pace changes, optimized storyboard workflow --- -# 📜 License +# 👨‍👩‍👧‍👦 WeChat Discussion Groups -Toonflow is open-sourced under the AGPL-3.0 license. License details: https://www.gnu.org/licenses/agpl-3.0.html +~~Group 1~~ -You may use Toonflow for various purposes including commercial use, in compliance with the terms and conditions of AGPL-3.0. +~~Group 2~~ -For proprietary commercial licenses exempt from AGPL-3.0 restrictions, please contact us via email. +~~Group 3~~ + +~~Group 4~~ + +~~Group 5~~ + +Group 6: + +Toonflow Logo +

Scan with WeChat to join. If the QR expires, open an issue to request an update.

--- # 💌 Contact Us -📧 Email: [ltlctools@outlook.com](mailto:ltlctools@outlook.com?subject=Toonflow Inquiry) +📧 Email: [ltlctools@outlook.com](mailto:ltlctools@outlook.com?subject=Toonflow%20Inquiry) + +--- + +# 📜 License + +Toonflow is open source under the AGPL-3.0 license. Details: https://www.gnu.org/licenses/agpl-3.0.html + +You may use Toonflow for any purpose, including commercial, as long as you adhere to the AGPL-3.0 terms and conditions. + +For proprietary/commercial licensing exempt from AGPL-3.0, please contact us by email. --- # ⭐️ Star History -[![Star History Chart](https://api.star-history.com/svg?repos=HBAI-Ltd/Toonflow-app&type=Date)](https://star-history.com/#HBAI-Ltd/Toonflow-app&Date) +[![Star History Chart](https://api.star-history.com/svg?repos=HBAI-Ltd/Toonflow-app&type=date&legend=top-left)](https://www.star-history.com/#HBAI-Ltd/Toonflow-app&type=date&legend=top-left) -# Third-party Dependency List +--- + +# 🙏 Special Thanks + +Thanks to the following open-source projects for empowering Toonflow: + +- [Express](https://expressjs.com/) – Fast, open, minimal Node.js web framework +- [LangChain](https://js.langchain.com/) – Framework for building LLM apps +- [Better-SQLite3](https://github.com/WiseLibs/better-sqlite3) – High-performance SQLite3 bindings +- [Sharp](https://sharp.pixelplumbing.com/) – High-performance Node.js image processing +- [Axios](https://axios-http.com/) – Promise-based HTTP client +- [Zod](https://zod.dev/) – TypeScript-first schema validation +- [Aigne](https://github.com/aigne-com/aigne) – Unified LLM API middleware +- [Electron](https://www.electronjs.org/) – Cross-platform desktop app framework + +Thanks to the following organizations/individuals for supporting Toonflow: + + + + + + +
+ Sophnet Cloud Logo + + Sophnet Cloud provided compute sponsorship + [Official Site] +
+ +For the full list of third-party dependencies, see `NOTICES.txt` -Please refer to `NOTICES.txt` \ No newline at end of file diff --git a/docs/chat6QR.jpg b/docs/chat6QR.jpg new file mode 100644 index 0000000..be531c3 Binary files /dev/null and b/docs/chat6QR.jpg differ diff --git a/docs/sponsored/sophnet.png b/docs/sponsored/sophnet.png new file mode 100644 index 0000000..53db918 Binary files /dev/null and b/docs/sponsored/sophnet.png differ diff --git a/docs/videoCover.png b/docs/videoCover.png new file mode 100644 index 0000000..a6aa056 Binary files /dev/null and b/docs/videoCover.png differ diff --git a/docs/videoQR.png b/docs/videoQR.png new file mode 100644 index 0000000..83aa151 Binary files /dev/null and b/docs/videoQR.png differ diff --git a/package.json b/package.json index 291bfa8..5a2ac46 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "toonflow-serve", - "version": "1.0.0", + "version": "1.0.1", "description": "ToonFlow Serve - Electron Application", "main": "build/main.js", "author": "ToonFlow Team", diff --git a/scripts/web/index.html b/scripts/web/index.html index 509c738..b6af47a 100644 --- a/scripts/web/index.html +++ b/scripts/web/index.html @@ -5,40 +5,40 @@ Toonflow - - +In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}function x(ze){return b(ze)||C(ze)||f(ze)||y()}var M=s("a352"),W=s.n(M);function S(ze){ze.parentElement!==null&&ze.parentElement.removeChild(ze)}function H(ze,Ke,Re){var ot=Re===0?ze.children[0]:ze.children[Re-1].nextSibling;ze.insertBefore(Ke,ot)}var O=s("dbf1");s("13d5"),s("4fad"),s("ac1f"),s("5319");function D(ze){var Ke=Object.create(null);return function(ot){var ut=Ke[ot];return ut||(Ke[ot]=ze(ot))}}var z=/-(\w)/g,V=D(function(ze){return ze.replace(z,function(Ke,Re){return Re.toUpperCase()})});s("5db7"),s("73d9");var Z=["Start","Add","Remove","Update","End"],B=["Choose","Unchoose","Sort","Filter","Clone"],T=["Move"],E=[T,Z,B].flatMap(function(ze){return ze}).map(function(ze){return"on".concat(ze)}),F={manage:T,manageAndEmit:Z,emit:B};function X(ze){return E.indexOf(ze)!==-1}s("caad"),s("2ca0");var R=["a","abbr","address","area","article","aside","audio","b","base","bdi","bdo","blockquote","body","br","button","canvas","caption","cite","code","col","colgroup","data","datalist","dd","del","details","dfn","dialog","div","dl","dt","em","embed","fieldset","figcaption","figure","footer","form","h1","h2","h3","h4","h5","h6","head","header","hgroup","hr","html","i","iframe","img","input","ins","kbd","label","legend","li","link","main","map","mark","math","menu","menuitem","meta","meter","nav","noscript","object","ol","optgroup","option","output","p","param","picture","pre","progress","q","rb","rp","rt","rtc","ruby","s","samp","script","section","select","slot","small","source","span","strong","style","sub","summary","sup","svg","table","tbody","td","template","textarea","tfoot","th","thead","time","title","tr","track","u","ul","var","video","wbr"];function q(ze){return R.includes(ze)}function Y(ze){return["transition-group","TransitionGroup"].includes(ze)}function K(ze){return["id","class","role","style"].includes(ze)||ze.startsWith("data-")||ze.startsWith("aria-")||ze.startsWith("on")}function Q(ze){return ze.reduce(function(Ke,Re){var ot=L(Re,2),ut=ot[0],nt=ot[1];return Ke[ut]=nt,Ke},{})}function ee(ze){var Ke=ze.$attrs,Re=ze.componentData,ot=Re===void 0?{}:Re,ut=Q(Object.entries(Ke).filter(function(nt){var Pe=L(nt,2),Qe=Pe[0];return Pe[1],K(Qe)}));return g(g({},ut),ot)}function J(ze){var Ke=ze.$attrs,Re=ze.callBackBuilder,ot=Q(ne(Ke));Object.entries(Re).forEach(function(nt){var Pe=L(nt,2),Qe=Pe[0],Xe=Pe[1];F[Qe].forEach(function(ht){ot["on".concat(ht)]=Xe(ht)})});var ut="[data-draggable]".concat(ot.draggable||"");return g(g({},ot),{},{draggable:ut})}function ne(ze){return Object.entries(ze).filter(function(Ke){var Re=L(Ke,2),ot=Re[0];return Re[1],!K(ot)}).map(function(Ke){var Re=L(Ke,2),ot=Re[0],ut=Re[1];return[V(ot),ut]}).filter(function(Ke){var Re=L(Ke,2),ot=Re[0];return Re[1],!X(ot)})}s("c740");function le(ze,Ke){if(!(ze instanceof Ke))throw new TypeError("Cannot call a class as a function")}function oe(ze,Ke){for(var Re=0;Re{const e=_([]),n=_([]),i=_(null),o=_(null);let l=null,r=0;const s=P(()=>i.value?e.value.filter(W=>W.scriptId===i.value):[]),a=P(()=>n.value.filter(W=>W.state===0).map(W=>W.id));function c(W){return n.value.filter(S=>S.configId===W)}function d(W){const S=e.value.find(H=>H.id===W);return!S||!S.selectedResultId?null:n.value.find(H=>H.id===S.selectedResultId)||null}async function u(W,S){i.value=W,o.value=S,await Promise.all([v(W),h(W)])}async function h(W,S=[]){try{const H={scriptId:W,specifyIds:S},{data:O}=await Di.post("/video/getVideo",H);if(S.length>0){if(O.length===0)return;const D=n.value.map(z=>{const V=O.find(Z=>Z.id===z.id);return V?{...z,state:V.state,filePath:V.filePath||z.filePath,firstFrame:V.firstFrame||z.firstFrame,duration:V.duration||z.duration}:z});n.value=D}else g(O,W)}catch(H){console.error("获取视频数据失败:",H)}}function g(W,S){const H=e.value.filter(D=>D.scriptId===S).map(D=>D.id);n.value=n.value.filter(D=>!H.includes(D.configId));const O=W.map(D=>({id:D.id,configId:D.configId||0,state:D.state,filePath:D.filePath||"",firstFrame:D.firstFrame||"",duration:D.duration||D.time||0,prompt:D.prompt||"",createdAt:new Date().toISOString()}));O.sort((D,z)=>D.id-z.id),n.value=[...n.value,...O]}async function v(W){try{const{data:S}=await Di.post("/video/getVideoConfigs",{scriptId:W});S&&Array.isArray(S)&&(e.value=e.value.filter(H=>H.scriptId!==W),S.forEach(H=>{const O={id:H.id,scriptId:H.scriptId,projectId:H.projectId,manufacturer:H.manufacturer,mode:H.mode,startFrame:H.startFrame,endFrame:H.endFrame,images:H.images||[],resolution:H.resolution,duration:H.duration,prompt:H.prompt||"",selectedResultId:H.selectedResultId,createdAt:H.createdAt||new Date().toISOString()};e.value.push(O),O.id>r&&(r=O.id)}))}catch(S){console.error("获取视频配置失败:",S)}}function m(W){const S={id:W.id,scriptId:W.scriptId,projectId:W.projectId,manufacturer:W.manufacturer,mode:W.mode,startFrame:W.startFrame||null,endFrame:W.endFrame||null,images:W.images||[],resolution:W.resolution,duration:W.duration,prompt:W.prompt||"",selectedResultId:W.selectedResultId||null,createdAt:W.createdAt||new Date().toISOString()};return e.value.push(S),S.id>r&&(r=S.id),S}function k(W){const S={...W,startFrame:W.startFrame||null,endFrame:W.endFrame||null,images:W.images||[],id:++r,selectedResultId:null,createdAt:new Date().toISOString()};return e.value.push(S),S}async function f(W){try{await Di.post("/video/deleteVideoConfig",{id:W})}catch(H){throw console.error("删除配置失败:",H),H}const S=e.value.findIndex(H=>H.id===W);S!==-1&&(e.value.splice(S,1),n.value=n.value.filter(H=>H.configId!==W))}async function w(W){const S=e.value.find(D=>D.id===W);if(!S)throw new Error("配置不存在");const H=[];S.mode==="startEnd"?(S.startFrame&&H.push(S.startFrame.filePath),S.endFrame&&H.push(S.endFrame.filePath)):S.mode==="single"?S.startFrame&&H.push(S.startFrame.filePath):S.images.forEach(D=>H.push(D.filePath));const{data:O}=await Di.post("/video/generateVideo",{projectId:S.projectId,scriptId:S.scriptId,configId:W,type:S.manufacturer,resolution:S.resolution,filePath:H,duration:S.duration,prompt:S.prompt});if(O&&O.id){const D={id:O.id,configId:W,state:0,filePath:"",firstFrame:"",duration:S.duration,prompt:S.prompt,createdAt:new Date().toISOString()};n.value=[...n.value,D],y(!0)}}function L(W,S){const H=e.value.find(O=>O.id===W);H&&(H.selectedResultId=S)}function b(W,S){const H=e.value.find(O=>O.id===W);H&&(S.prompt!==void 0&&(H.prompt=S.prompt),S.resolution!==void 0&&(H.resolution=S.resolution),S.duration!==void 0&&(H.duration=S.duration))}function C(W,S){const H=e.value.find(O=>O.id===W);H&&(S.prompt!==void 0&&(H.prompt=S.prompt),S.resolution!==void 0&&(H.resolution=S.resolution),S.duration!==void 0&&(H.duration=S.duration),S.startFrame!==void 0&&(H.startFrame=S.startFrame),S.endFrame!==void 0&&(H.endFrame=S.endFrame),S.images!==void 0&&(H.images=[...S.images]))}function y(W=!1){if(l){if(!W)return;x()}Be(()=>{a.value.length!==0&&(l=window.setInterval(async()=>{if(a.value.length===0){x();return}i.value&&await h(i.value,a.value)},1e4))})}function x(){l&&(clearInterval(l),l=null)}Ve(a,W=>{W.length>0?y():x()});function M(){x()}return{videoConfigs:e,videoResults:n,currentScriptId:i,currentProjectId:o,currentConfigs:s,pendingResultIds:a,setCurrentScript:u,fetchVideoData:h,fetchVideoConfigs:v,addConfig:k,addConfigFromBackend:m,removeConfig:f,updateConfig:b,updateConfigFull:C,generateVideo:w,selectResult:L,getResultsByConfigId:c,getSelectedResult:d,startPolling:y,stopPolling:x,cleanup:M}},{persist:!1}),OWn={class:"selector-footer"},VWn={class:"selected-count"},BWn=_e({__name:"ImageSelector",props:Ql({scriptId:{},mode:{},maxImages:{},initialImages:{}},{visible:{type:Boolean,default:!1},visibleModifiers:{}}),emits:Ql(["confirm","cancel"],["update:visible"]),setup(e,{emit:n}){const i=Qr(),{currentScriptId:o}=zr(i),l=e,r=n,s=Mr(e,"visible"),a=_(),c=_([]),d=_([]),u=P(()=>l.mode==="multi"),h=P(()=>({start:"选择首帧图片",end:"选择尾帧图片",single:"选择图片",multi:"选择图片序列(可多选)"})[l.mode]||"选择图片");Ve(s,f=>{f&&(l.scriptId&&l.scriptId!==-1&&(o.value=l.scriptId),l.initialImages&&l.initialImages.length>0?(c.value=[...l.initialImages],d.value=l.initialImages.map(w=>w.id)):(c.value=[],d.value=[]))});function g(f,w){if(w!=="storyboard")return;const L=l.maxImages||999;if(f.checked){if(u.value)f.records.forEach(b=>{!d.value.includes(b.id)&&c.value.length0){const b=f.records[0];d.value=[b.id],c.value=[{id:b.id,filePath:b.filePath,prompt:b.prompt}]}}else f.records.forEach(b=>{const C=d.value.indexOf(b.id);C>-1&&(d.value.splice(C,1),c.value.splice(C,1))})}function v(f){const w=l.maxImages||999;if(f.checked){if(!u.value)d.value=[f.row.id],c.value=[{id:f.row.id,filePath:f.row.filePath,prompt:f.row.prompt}];else if(!d.value.includes(f.row.id)){if(c.value.length>=w){Sn.warning(`最多只能选择${w}张图片`);return}d.value.push(f.row.id),c.value.push({id:f.row.id,filePath:f.row.filePath,prompt:f.row.prompt})}}else{const L=d.value.indexOf(f.row.id);L>-1&&(d.value.splice(L,1),c.value.splice(L,1))}}function m(){r("confirm",[...c.value]),s.value=!1}function k(){r("cancel"),s.value=!1}return(f,w)=>{const L=nl,b=Zo;return ie(),kt(b,{open:s.value,"onUpdate:open":w[0]||(w[0]=C=>s.value=C),title:h.value,onOk:m,onCancel:k,width:"80%",bodyStyle:{maxHeight:"70vh",overflow:"auto"}},{footer:De(()=>[p("div",OWn,[p("span",VWn,"已选择 "+jt(c.value.length)+" 张",1),p("div",null,[t(L,{onClick:k},{default:De(()=>[...w[1]||(w[1]=[cn("取消",-1)])]),_:1}),t(L,{type:"primary",onClick:m},{default:De(()=>[...w[2]||(w[2]=[cn("确定",-1)])]),_:1})])])]),default:De(()=>[s.value?(ie(),kt(tW,{key:0,way:u.value?"checkbox":"radio",radio:"storyboard",ref_key:"mainElementRef",ref:a,onCheckChange:v,onCheckAll:g},null,8,["way"])):et("",!0)]),_:1},8,["open","title"])}}}),IWn=Xo(BWn,[["__scopeId","data-v-d2f6e206"]]),EE={volcengine:{label:"火山引擎(豆包)",value:"volcengine",modes:[{label:"首尾帧",value:"startEnd"}],defaultMode:"startEnd",resolutions:[{label:"480p",value:"480p"},{label:"720p",value:"720p"},{label:"1080p",value:"1080p"}],defaultResolution:"720p",resolutionLabel:"分辨率",durationRange:{min:4,max:12,step:1},durationTip:"4-12秒",maxImages:2},runninghub:{label:"RunningHub(Sora)",value:"runninghub",modes:[{label:"多图模式",value:"multi"}],defaultMode:"multi",resolutions:[{label:"16:9 横屏",value:"16:9"},{label:"9:16 竖屏",value:"9:16"}],defaultResolution:"16:9",resolutionLabel:"画面比例",durationOptions:[{label:"10秒",value:10},{label:"15秒",value:15}],maxImages:4},apimart:{label:"Apimart(Sora)",value:"apimart",modes:[{label:"多图模式",value:"multi"}],defaultMode:"multi",resolutions:[{label:"16:9 横屏",value:"16:9"},{label:"9:16 竖屏",value:"9:16"}],defaultResolution:"16:9",resolutionLabel:"画面比例",durationOptions:[{label:"10秒",value:10},{label:"15秒",value:15}],maxImages:4}},NWn={volcengine:"火山引擎(豆包)",runninghub:"RunningHub(Sora)",openAi:"OpenAI(Sora)"},RWn={startEnd:"首尾帧模式",multi:"多图模式",single:"单图模式"};function qd(e){return EE[e]||EE.volcengine}function FWn(e){return NWn[e]||e}function ZWn(e){return RWn[e]||e}function N8e(e){return qd(e).modes}function R8e(e){return qd(e).resolutionLabel}function OE(e){return qd(e).resolutions}function XWn(e){return qd(e).defaultResolution}function UWn(e){return qd(e).defaultMode}function VE(e){var i;const n=qd(e);return n.durationOptions&&n.durationOptions.length>0?n.durationOptions[0].value:((i=n.durationRange)==null?void 0:i.min)||5}function Sy(e){return qd(e).durationOptions||[]}function ov(e){return qd(e).durationRange||{min:5,max:20,step:1}}function F8e(e){return qd(e).durationTip||""}function Uk(e){return qd(e).maxImages}const GWn={class:"video-config-form"},YWn={key:0,class:"form-row"},qWn={key:1,class:"form-row"},KWn={class:"value"},JWn={key:2,class:"form-row"},QWn={key:3,class:"form-row"},$Wn={class:"value"},_Wn={key:4,class:"form-row frame-row"},pWn={class:"frame-group"},eSn=["src"],tSn=["src"],nSn={class:"form-row"},iSn={class:"multi-images"},oSn={class:"drag-image-item"},lSn={class:"drag-handle"},rSn=["src"],sSn={class:"image-order"},aSn={key:0,class:"form-row"},cSn={class:"tip"},dSn={key:6,class:"form-row frame-row"},uSn={class:"frame-group"},hSn=["src"],kSn={class:"form-row"},fSn={key:1,class:"value"},vSn={class:"form-row"},gSn={key:1,class:"value"},mSn={class:"tip"},wSn={key:1,class:"value"},LSn={class:"form-row prompt-row"},bSn={class:"prompt-header"},CSn=_e({__name:"VideoConfigForm",props:{config:{},scriptId:{},editable:{type:Boolean,default:!0},manufacturerDisabled:{type:Boolean,default:!1},availableManufacturers:{default:()=>[{label:"火山引擎(豆包)",value:"volcengine"},{label:"RunningHub(Sora)",value:"runninghub"},{label:"Apimart(Sora)",value:"apimart"}]}},emits:["update:config","change"],setup(e,{emit:n}){const i=e,o=n,l=dn({...i.config}),r=_(!1),s=_(!1),a=_("start");Ve(()=>i.config,w=>{Object.assign(l,w)},{deep:!0});function c(w,L){const C=OE(w).find(y=>y.value===L);return(C==null?void 0:C.label)||L}const d=P(()=>a.value==="start"||a.value==="single"?l.startFrame?[l.startFrame]:[]:a.value==="end"?l.endFrame?[l.endFrame]:[]:l.images||[]);function u(){const w=qd(l.manufacturer);l.mode=w.defaultMode,l.resolution=w.defaultResolution,l.duration=VE(l.manufacturer),l.startFrame=null,l.endFrame=null,l.images=[],f()}function h(){l.startFrame=null,l.endFrame=null,l.images=[],f()}function g(w){a.value=w,s.value=!0}function v(w){a.value==="start"||a.value==="single"?l.startFrame=w[0]||null:a.value==="end"?l.endFrame=w[0]||null:l.images=[...w],f()}function m(w){l.images.splice(w,1),f()}async function k(){const w=[];if(l.mode==="startEnd"?(l.startFrame&&w.push(l.startFrame),l.endFrame&&w.push(l.endFrame)):l.mode==="single"?l.startFrame&&w.push(l.startFrame):w.push(...l.images),w.length===0){Sn.warning("请先选择图片");return}r.value=!0;try{const L=await Di.post("/video/generatePrompt",{prompt:l.prompt||"生成视频",images:w.map(b=>({filePath:b.filePath,prompt:b.prompt})),duration:l.duration,type:l.mode});l.prompt=L.data,f(),Sn.success("提示词生成成功")}catch(L){Sn.error((L==null?void 0:L.message)||"生成失败")}finally{r.value=!1}}function f(){const w={...l};o("update:config",w),o("change",w)}return(w,L)=>{var O;const b=Xm,C=Gr,y=pa,x=$x,M=nl,W=A8,S=nn("i-magic"),H=Bs;return ie(),be("div",GWn,[e.editable?(ie(),be("div",YWn,[L[15]||(L[15]=p("label",null,"厂商",-1)),t(C,{value:l.manufacturer,"onUpdate:value":L[0]||(L[0]=D=>l.manufacturer=D),onChange:u,disabled:e.manufacturerDisabled,size:"small"},{default:De(()=>[(ie(!0),be(Gt,null,Qn(e.availableManufacturers,D=>(ie(),kt(b,{key:D.value,value:D.value},{default:De(()=>[cn(jt(D.label),1)]),_:2},1032,["value"]))),128))]),_:1},8,["value","disabled"])])):(ie(),be("div",qWn,[L[16]||(L[16]=p("label",null,"厂商",-1)),p("span",KWn,jt(A(FWn)(l.manufacturer)),1)])),e.editable?(ie(),be("div",JWn,[L[17]||(L[17]=p("label",null,"模式",-1)),t(x,{value:l.mode,"onUpdate:value":L[1]||(L[1]=D=>l.mode=D),onChange:h,size:"small"},{default:De(()=>[(ie(!0),be(Gt,null,Qn(A(N8e)(l.manufacturer),D=>(ie(),kt(y,{key:D.value,value:D.value},{default:De(()=>[cn(jt(D.label),1)]),_:2},1032,["value"]))),128))]),_:1},8,["value"])])):(ie(),be("div",QWn,[L[18]||(L[18]=p("label",null,"模式",-1)),p("span",$Wn,jt(A(ZWn)(l.mode)),1)])),l.mode==="startEnd"?(ie(),be("div",_Wn,[L[23]||(L[23]=p("label",null,"帧选择",-1)),p("div",pWn,[p("div",{class:Ae(["frame-box",{"has-image":l.startFrame}]),onClick:L[3]||(L[3]=D=>g("start"))},[l.startFrame?(ie(),be(Gt,{key:0},[p("img",{src:l.startFrame.filePath},null,8,eSn),e.editable?(ie(),kt(M,{key:0,class:"remove-btn",type:"text",size:"small",onClick:L[2]||(L[2]=Fn(D=>l.startFrame=null,["stop"]))},{default:De(()=>[t(A(Kr))]),_:1})):et("",!0),L[19]||(L[19]=p("span",{class:"frame-label"},"首帧",-1))],64)):(ie(),be(Gt,{key:1},[t(A(xd)),L[20]||(L[20]=p("span",null,"首帧",-1))],64))],2),p("div",{class:Ae(["frame-box",{"has-image":l.endFrame}]),onClick:L[5]||(L[5]=D=>g("end"))},[l.endFrame?(ie(),be(Gt,{key:0},[p("img",{src:l.endFrame.filePath},null,8,tSn),e.editable?(ie(),kt(M,{key:0,class:"remove-btn",type:"text",size:"small",onClick:L[4]||(L[4]=Fn(D=>l.endFrame=null,["stop"]))},{default:De(()=>[t(A(Kr))]),_:1})):et("",!0),L[21]||(L[21]=p("span",{class:"frame-label"},"尾帧",-1))],64)):(ie(),be(Gt,{key:1},[t(A(xd)),L[22]||(L[22]=p("span",null,"尾帧",-1))],64))],2)])])):et("",!0),l.mode==="multi"?(ie(),be(Gt,{key:5},[p("div",nSn,[L[24]||(L[24]=p("label",null,"图片",-1)),p("div",iSn,[l.images&&l.images.length>0?(ie(),kt(A(I8e),{key:0,modelValue:l.images,"onUpdate:modelValue":L[6]||(L[6]=D=>l.images=D),"item-key":"id",class:"image-drag-list","ghost-class":"ghost",animation:200,disabled:!e.editable,handle:".drag-handle"},{item:De(({element:D,index:z})=>[p("div",oSn,[p("div",lSn,[p("img",{class:"image",src:D.filePath,draggable:"false"},null,8,rSn),p("div",sSn,jt(z+1),1)]),e.editable?(ie(),kt(M,{key:0,class:"remove-btn",type:"text",size:"small",onClick:V=>m(z)},{default:De(()=>[t(A(Kr))]),_:1},8,["onClick"])):et("",!0)])]),_:1},8,["modelValue","disabled"])):et("",!0),e.editable&&(!l.images||l.images.lengthg("multi"))},[t(A(xd))])):et("",!0)])]),e.editable?(ie(),be("div",aSn,[L[25]||(L[25]=p("label",null,null,-1)),p("span",cSn,"拖拽调整顺序 | "+jt(((O=l.images)==null?void 0:O.length)||0)+"/"+jt(A(Uk)(l.manufacturer))+"张",1)])):et("",!0)],64)):et("",!0),l.mode==="single"?(ie(),be("div",dSn,[L[27]||(L[27]=p("label",null,"图片",-1)),p("div",uSn,[p("div",{class:Ae(["frame-box single-frame",{"has-image":l.startFrame}]),onClick:L[9]||(L[9]=D=>g("single"))},[l.startFrame?(ie(),be(Gt,{key:0},[p("img",{src:l.startFrame.filePath},null,8,hSn),e.editable?(ie(),kt(M,{key:0,class:"remove-btn",type:"text",size:"small",onClick:L[8]||(L[8]=Fn(D=>l.startFrame=null,["stop"]))},{default:De(()=>[t(A(Kr))]),_:1})):et("",!0)],64)):(ie(),be(Gt,{key:1},[t(A(xd)),L[26]||(L[26]=p("span",null,"选择图片",-1))],64))],2)])])):et("",!0),p("div",kSn,[p("label",null,jt(A(R8e)(l.manufacturer)),1),e.editable?(ie(),kt(C,{key:0,value:l.resolution,"onUpdate:value":L[10]||(L[10]=D=>l.resolution=D),size:"small",style:{flex:"1"},onChange:f},{default:De(()=>[(ie(!0),be(Gt,null,Qn(A(OE)(l.manufacturer),D=>(ie(),kt(b,{key:D.value,value:D.value},{default:De(()=>[cn(jt(D.label),1)]),_:2},1032,["value"]))),128))]),_:1},8,["value"])):(ie(),be("span",fSn,jt(c(l.manufacturer,l.resolution)),1))]),p("div",vSn,[L[29]||(L[29]=p("label",null,"时长",-1)),A(Sy)(l.manufacturer).length>0?(ie(),be(Gt,{key:0},[e.editable?(ie(),kt(C,{key:0,value:l.duration,"onUpdate:value":L[11]||(L[11]=D=>l.duration=D),size:"small",style:{width:"100px"},onChange:f},{default:De(()=>[(ie(!0),be(Gt,null,Qn(A(Sy)(l.manufacturer),D=>(ie(),kt(b,{key:D.value,value:D.value},{default:De(()=>[cn(jt(D.label),1)]),_:2},1032,["value"]))),128))]),_:1},8,["value"])):(ie(),be("span",gSn,jt(l.duration)+"秒",1))],64)):(ie(),be(Gt,{key:1},[e.editable?(ie(),be(Gt,{key:0},[t(W,{value:l.duration,"onUpdate:value":L[12]||(L[12]=D=>l.duration=D),min:A(ov)(l.manufacturer).min,max:A(ov)(l.manufacturer).max,step:A(ov)(l.manufacturer).step,size:"small",style:{width:"70px"},onChange:f},null,8,["value","min","max","step"]),L[28]||(L[28]=p("span",{class:"unit"},"秒",-1)),p("span",mSn,jt(A(F8e)(l.manufacturer)),1)],64)):(ie(),be("span",wSn,jt(l.duration)+"秒",1))],64))]),p("div",LSn,[p("div",bSn,[L[31]||(L[31]=p("label",null,"提示词",-1)),t(M,{type:"link",size:"small",loading:r.value,onClick:k,class:"magic-btn"},{icon:De(()=>[t(S)]),default:De(()=>[L[30]||(L[30]=cn(" 润色 ",-1))]),_:1},8,["loading"])]),t(H,{value:l.prompt,"onUpdate:value":L[13]||(L[13]=D=>l.prompt=D),rows:3,placeholder:"描述视频内容、运动方式等",size:"small",onChange:f},null,8,["value"])]),t(IWn,{visible:s.value,"onUpdate:visible":L[14]||(L[14]=D=>s.value=D),"script-id":e.scriptId,mode:a.value,"max-images":A(Uk)(l.manufacturer),"initial-images":d.value,onConfirm:v},null,8,["visible","script-id","mode","max-images","initial-images"])])}}}),ySn=Xo(CSn,[["__scopeId","data-v-6b17ed24"]]),xSn={class:"newStoryboard"},jSn={class:"configPanel"},MSn={class:"configHeader"},ASn={key:0,class:"configList"},WSn={class:"cardHeader"},SSn={class:"cardTitle"},DSn={class:"cardBody"},HSn={class:"formRow"},TSn={class:"formRow"},zSn={key:0,class:"formRow frameRow"},PSn={class:"frameGroup"},ESn=["onClick"],OSn=["src"],VSn=["onClick"],BSn=["src"],ISn={class:"formRow"},NSn={class:"multiImages"},RSn={class:"dragImageItem"},FSn={class:"dragHandle"},ZSn=["src"],XSn={class:"imageOrder"},USn=["onClick"],GSn={class:"formRow"},YSn={class:"tip"},qSn={key:2,class:"formRow frameRow"},KSn={class:"frameGroup"},JSn=["onClick"],QSn=["src"],$Sn={class:"formRow"},_Sn={class:"formRow"},pSn={class:"tip"},eDn={class:"formRow promptRow"},tDn={class:"promptWrapper"},nDn={class:"selectorFooter"},iDn={class:"selectedCount"},oDn=_e({__name:"newVideo",props:Ql({scriptId:{}},{modelValue:{type:Boolean},modelModifiers:{}}),emits:["update:modelValue"],setup(e){const n=Qr(),{project:i,currentScriptId:o}=zr(n),l=iW(),r=e,s=Mr(e,"modelValue"),a=_(!1),c=_(!1),d=_([]);let u=0;const h=_(!1),g=_("选择分镜图片"),v=_("start"),m=_(null),k=_([]),f=_([]),w=_([]),L=Object.values(EE).map(B=>({label:B.label,value:B.value})),b=P(()=>w.value.length===0?L:L.filter(B=>w.value.some(T=>T.manufacturer===B.value)));un(async()=>{const B=await Di.post("/video/getManufacturer",{userId:Number(localStorage.getItem("userId"))});w.value=B.data,c.value=w.value.length===0}),Ve(s,B=>{B&&(d.value=[])});function C(){var E;const B=((E=b.value[0])==null?void 0:E.value)||"volcengine",T={id:++u,manufacturer:B,mode:UWn(B),startFrame:null,endFrame:null,images:[],resolution:XWn(B),duration:VE(B),prompt:"",promptLoading:!1};d.value.push(T)}function y(B){d.value.splice(B,1)}function x(B){const T=qd(B.manufacturer);B.mode=T.defaultMode,B.resolution=T.defaultResolution,B.duration=VE(B.manufacturer),B.startFrame=null,B.endFrame=null,B.images=[]}function M(B){B.startFrame=null,B.endFrame=null,B.images=[]}function W(B,T){r.scriptId&&r.scriptId!==-1&&(o.value=r.scriptId),m.value=B,v.value=T;const E={start:B.mode==="single"?"选择图片":"选择首帧图片",end:"选择尾帧图片",multi:"选择图片序列(可多选)"};g.value=E[T],T==="start"&&B.startFrame?(k.value=[B.startFrame],f.value=[B.startFrame.id]):T==="end"&&B.endFrame?(k.value=[B.endFrame],f.value=[B.endFrame.id]):T==="multi"?(k.value=[...B.images],f.value=B.images.map(F=>F.id)):(k.value=[],f.value=[]),h.value=!0}function S(B,T){var X;if(T!=="storyboard")return;const E=v.value!=="multi",F=Uk(((X=m.value)==null?void 0:X.manufacturer)||"");if(B.checked)if(E){if(B.records.length>0){const R=B.records[0];f.value=[R.id],k.value=[{id:R.id,filePath:R.filePath,prompt:R.prompt}]}}else B.records.forEach(R=>{!f.value.includes(R.id)&&k.value.length{const q=f.value.indexOf(R.id);q>-1&&(f.value.splice(q,1),k.value.splice(q,1))})}function H(B){var F;const T=v.value!=="multi",E=Uk(((F=m.value)==null?void 0:F.manufacturer)||"");if(B.checked){if(T)f.value=[B.row.id],k.value=[{id:B.row.id,filePath:B.row.filePath,prompt:B.row.prompt}];else if(!f.value.includes(B.row.id)){if(k.value.length>=E){Sn.warning(`最多只能选择${E}张图片`);return}f.value.push(B.row.id),k.value.push({id:B.row.id,filePath:B.row.filePath,prompt:B.row.prompt})}}else{const X=f.value.indexOf(B.row.id);X>-1&&(f.value.splice(X,1),k.value.splice(X,1))}}function O(){m.value&&(v.value==="start"?m.value.startFrame=k.value[0]||null:v.value==="end"?m.value.endFrame=k.value[0]||null:m.value.images=[...k.value],h.value=!1)}function D(B,T){B.images.splice(T,1)}async function z(B){const T=[];if(B.mode==="startEnd"?(B.startFrame&&T.push(B.startFrame),B.endFrame&&T.push(B.endFrame)):B.mode==="single"?B.startFrame&&T.push(B.startFrame):T.push(...B.images),T.length===0){Sn.warning("请先选择图片");return}B.promptLoading=!0;try{const E=await Di.post("/video/generatePrompt",{prompt:B.prompt||"生成视频",images:T.map(F=>({filePath:F.filePath,prompt:F.prompt})),duration:B.duration,type:B.mode});B.prompt=E.data,Sn.success("提示词生成成功")}catch(E){Sn.error((E==null?void 0:E.message)||"生成失败")}finally{B.promptLoading=!1}}async function V(){var B;if(d.value.length===0){Sn.warning("请至少添加一个视频配置");return}for(let T=0;T{const E=nl,F=Xm,X=Gr,R=pa,q=$x,Y=A8,K=Bs,Q=nn("i-magic"),ee=x2,J=Zo;return ie(),be("div",xSn,[t(J,{width:"80vw",style:{top:"20px"},open:s.value,"onUpdate:open":T[0]||(T[0]=ne=>s.value=ne),title:"添加视频配置",okText:"保存配置",onOk:V,onCancel:Z,confirmLoading:a.value},{default:De(()=>[p("div",jSn,[p("div",MSn,[T[5]||(T[5]=p("h3",null,"视频生成配置",-1)),t(E,{type:"primary",onClick:C},{default:De(()=>[t(A(xd)),T[4]||(T[4]=cn(" 添加配置 ",-1))]),_:1})]),d.value.length>0?(ie(),be("div",ASn,[(ie(!0),be(Gt,null,Qn(d.value,(ne,le)=>{var oe;return ie(),be("div",{key:ne.id,class:"configCard"},[p("div",WSn,[p("span",SSn,"配置 "+jt(le+1),1),t(E,{type:"text",danger:"",size:"small",onClick:$=>y(le)},{default:De(()=>[t(A(dj))]),_:1},8,["onClick"])]),p("div",DSn,[p("div",HSn,[T[6]||(T[6]=p("label",null,"厂商",-1)),t(X,{value:ne.manufacturer,"onUpdate:value":$=>ne.manufacturer=$,onChange:$=>x(ne),disabled:c.value,size:"small"},{default:De(()=>[(ie(!0),be(Gt,null,Qn(b.value,$=>(ie(),kt(F,{key:$.value,value:$.value},{default:De(()=>[cn(jt($.label),1)]),_:2},1032,["value"]))),128))]),_:1},8,["value","onUpdate:value","onChange","disabled"])]),p("div",TSn,[T[7]||(T[7]=p("label",null,"模式",-1)),t(q,{value:ne.mode,"onUpdate:value":$=>ne.mode=$,onChange:$=>M(ne),size:"small"},{default:De(()=>[(ie(!0),be(Gt,null,Qn(A(N8e)(ne.manufacturer),$=>(ie(),kt(R,{key:$.value,value:$.value},{default:De(()=>[cn(jt($.label),1)]),_:2},1032,["value"]))),128))]),_:2},1032,["value","onUpdate:value","onChange"])]),ne.mode==="startEnd"?(ie(),be("div",zSn,[T[12]||(T[12]=p("label",null,"帧选择",-1)),p("div",PSn,[p("div",{class:Ae(["frameBox",{hasImage:ne.startFrame}]),onClick:$=>W(ne,"start")},[ne.startFrame?(ie(),be(Gt,{key:0},[p("img",{src:ne.startFrame.filePath},null,8,OSn),t(E,{class:"removeBtn",type:"text",size:"small",onClick:Fn($=>ne.startFrame=null,["stop"])},{default:De(()=>[t(A(Kr))]),_:1},8,["onClick"]),T[8]||(T[8]=p("span",{class:"frameLabel"},"首帧",-1))],64)):(ie(),be(Gt,{key:1},[t(A(xd)),T[9]||(T[9]=p("span",null,"首帧",-1))],64))],10,ESn),p("div",{class:Ae(["frameBox",{hasImage:ne.endFrame}]),onClick:$=>W(ne,"end")},[ne.endFrame?(ie(),be(Gt,{key:0},[p("img",{src:ne.endFrame.filePath},null,8,BSn),t(E,{class:"removeBtn",type:"text",size:"small",onClick:Fn($=>ne.endFrame=null,["stop"])},{default:De(()=>[t(A(Kr))]),_:1},8,["onClick"]),T[10]||(T[10]=p("span",{class:"frameLabel"},"尾帧",-1))],64)):(ie(),be(Gt,{key:1},[t(A(xd)),T[11]||(T[11]=p("span",null,"尾帧",-1))],64))],10,VSn)])])):et("",!0),ne.mode==="multi"?(ie(),be(Gt,{key:1},[p("div",ISn,[T[13]||(T[13]=p("label",null,"图片",-1)),p("div",NSn,[ne.images&&ne.images.length>0?(ie(),kt(A(I8e),{key:0,modelValue:ne.images,"onUpdate:modelValue":$=>ne.images=$,"item-key":"id",class:"imageDragList","ghost-class":"ghost",animation:200,handle:".dragHandle"},{item:De(({element:$,index:se})=>[p("div",RSn,[p("div",FSn,[p("img",{class:"image",src:$.filePath,draggable:"false"},null,8,ZSn),p("div",XSn,jt(se+1),1)]),t(E,{class:"removeBtn",type:"text",size:"small",onClick:te=>D(ne,se)},{default:De(()=>[t(A(Kr))]),_:1},8,["onClick"])])]),_:2},1032,["modelValue","onUpdate:modelValue"])):et("",!0),!ne.images||ne.images.lengthW(ne,"multi")},[t(A(xd))],8,USn)):et("",!0)])]),p("div",GSn,[T[14]||(T[14]=p("label",null,null,-1)),p("span",YSn,"拖拽调整顺序 | "+jt(((oe=ne.images)==null?void 0:oe.length)||0)+"/"+jt(A(Uk)(ne.manufacturer))+"张",1)])],64)):et("",!0),ne.mode==="single"?(ie(),be("div",qSn,[T[16]||(T[16]=p("label",null,"图片",-1)),p("div",KSn,[p("div",{class:Ae(["frameBox singleFrame",{hasImage:ne.startFrame}]),onClick:$=>W(ne,"start")},[ne.startFrame?(ie(),be(Gt,{key:0},[p("img",{src:ne.startFrame.filePath},null,8,QSn),t(E,{class:"removeBtn",type:"text",size:"small",onClick:Fn($=>ne.startFrame=null,["stop"])},{default:De(()=>[t(A(Kr))]),_:1},8,["onClick"])],64)):(ie(),be(Gt,{key:1},[t(A(xd)),T[15]||(T[15]=p("span",null,"选择图片",-1))],64))],10,JSn)])])):et("",!0),p("div",$Sn,[p("label",null,jt(A(R8e)(ne.manufacturer)),1),t(X,{value:ne.resolution,"onUpdate:value":$=>ne.resolution=$,size:"small",style:{width:"140px"}},{default:De(()=>[(ie(!0),be(Gt,null,Qn(A(OE)(ne.manufacturer),$=>(ie(),kt(F,{key:$.value,value:$.value},{default:De(()=>[cn(jt($.label),1)]),_:2},1032,["value"]))),128))]),_:2},1032,["value","onUpdate:value"])]),p("div",_Sn,[T[18]||(T[18]=p("label",null,"时长",-1)),A(Sy)(ne.manufacturer).length>0?(ie(),kt(X,{key:0,value:ne.duration,"onUpdate:value":$=>ne.duration=$,size:"small",style:{width:"100px"}},{default:De(()=>[(ie(!0),be(Gt,null,Qn(A(Sy)(ne.manufacturer),$=>(ie(),kt(F,{key:$.value,value:$.value},{default:De(()=>[cn(jt($.label),1)]),_:2},1032,["value"]))),128))]),_:2},1032,["value","onUpdate:value"])):(ie(),be(Gt,{key:1},[t(Y,{value:ne.duration,"onUpdate:value":$=>ne.duration=$,min:A(ov)(ne.manufacturer).min,max:A(ov)(ne.manufacturer).max,step:A(ov)(ne.manufacturer).step,size:"small",style:{width:"70px"}},null,8,["value","onUpdate:value","min","max","step"]),T[17]||(T[17]=p("span",{class:"unit"},"秒",-1)),p("span",pSn,jt(A(F8e)(ne.manufacturer)),1)],64))]),p("div",eDn,[T[19]||(T[19]=p("label",null,"提示词",-1)),p("div",tDn,[t(K,{value:ne.prompt,"onUpdate:value":$=>ne.prompt=$,rows:2,placeholder:"描述视频内容、运动方式等",size:"small"},null,8,["value","onUpdate:value"]),t(E,{class:"magicBtn",type:"link",size:"small",loading:ne.promptLoading,onClick:$=>z(ne),style:{"margin-right":"20px"}},{default:De(()=>[t(Q)]),_:1},8,["loading","onClick"])])])])])}),128))])):(ie(),kt(ee,{key:1,description:"请点击上方按钮添加视频配置"}))])]),_:1},8,["open","confirmLoading"]),t(J,{open:h.value,"onUpdate:open":T[2]||(T[2]=ne=>h.value=ne),title:g.value,onOk:O,onCancel:T[3]||(T[3]=ne=>h.value=!1),width:"80%",bodyStyle:{maxHeight:"70vh",overflow:"auto"}},{footer:De(()=>[p("div",nDn,[p("span",iDn,"已选择 "+jt(k.value.length)+" 张",1),p("div",null,[t(E,{onClick:T[1]||(T[1]=ne=>h.value=!1)},{default:De(()=>[...T[20]||(T[20]=[cn("取消",-1)])]),_:1}),t(E,{type:"primary",onClick:O},{default:De(()=>[...T[21]||(T[21]=[cn("确定",-1)])]),_:1})])])]),default:De(()=>[h.value?(ie(),kt(tW,{key:0,way:v.value==="multi"?"checkbox":"radio",radio:"storyboard",ref:"mainElementRef",onCheckChange:H,onCheckAll:S},null,8,["way"])):et("",!0)]),_:1},8,["open","title"])])}}}),lDn=Xo(oDn,[["__scopeId","data-v-c39f3e14"]]),rDn={key:0,class:"video-detail"},sDn={class:"left-panel"},aDn={class:"config-section"},cDn={class:"action-section"},dDn={class:"right-panel"},uDn={class:"section-title"},hDn={key:0,class:"result-count"},kDn={key:0,class:"results-list"},fDn=["onClick"],vDn=["onClick"],gDn=["src"],mDn={class:"play-overlay"},wDn={key:0,class:"duration-badge"},LDn={class:"result-actions"},bDn={key:1,class:"selected-badge"},CDn={key:1,class:"status-cover generating"},yDn={key:2,class:"status-cover failed"},xDn={key:1,class:"empty-results"},jDn={class:"empty-icon"},MDn={class:"video-player-content"},ADn=["src"],WDn=_e({__name:"videoDetail",props:Ql({configId:{}},{modelValue:{type:Boolean},modelModifiers:{}}),emits:["update:modelValue"],setup(e){const n=e,i=Mr(e,"modelValue"),o=iW(),{videoConfigs:l,videoResults:r}=zr(o),s=_(!1),a=_(!1),c=_(null),d=_(null),u=_(null),h=P(()=>n.configId&&l.value.find(L=>L.id===n.configId)||null),g=P(()=>n.configId?o.getResultsByConfigId(n.configId):[]);Ve(h,L=>{L?u.value={id:L.id,manufacturer:L.manufacturer,mode:L.mode,startFrame:L.startFrame,endFrame:L.endFrame,images:L.images?[...L.images]:[],resolution:L.resolution,duration:L.duration,prompt:L.prompt}:u.value=null},{immediate:!0});async function v(L){if(!(!n.configId||!h.value)){u.value=L,o.updateConfigFull(n.configId,{resolution:L.resolution,duration:L.duration,prompt:L.prompt,startFrame:L.startFrame,endFrame:L.endFrame,images:L.images});try{await Di.post("/video/upDateVideoConfig",{id:n.configId,resolution:L.resolution,duration:L.duration,prompt:L.prompt,startFrame:L.startFrame,endFrame:L.endFrame,images:L.images})}catch(b){console.error("更新配置失败:",b)}}}function m(L){const b=Math.floor(L/60),C=Math.floor(L%60);return`${b}:${C.toString().padStart(2,"0")}`}async function k(){if(n.configId){s.value=!0;try{await o.generateVideo(n.configId),Sn.success("视频生成任务已提交")}catch(L){Sn.error((L==null?void 0:L.message)||"生成失败")}finally{s.value=!1}}}async function f(L){if(!(L.state!==1||!n.configId)){o.selectResult(n.configId,L.id);try{await Di.post("/video/upDateVideoConfig",{id:n.configId,selectedResultId:L.id}),Sn.success("已选择此视频")}catch(b){Sn.error("选择失败"),console.error("更新选中结果失败:",b)}}}function w(L){L.state!==1||!L.filePath||(c.value=L,a.value=!0)}return Ve(a,L=>{!L&&d.value&&(d.value.pause(),c.value=null)}),(L,b)=>{const C=nn("i-video-two"),y=nl,x=nn("i-play-one"),M=nn("i-check-one"),W=nn("i-close-one"),S=nn("i-film"),H=Zo;return ie(),kt(H,{open:i.value,"onUpdate:open":b[1]||(b[1]=O=>i.value=O),title:"视频详情",width:"90vw",style:{top:"20px"},footer:null,destroyOnClose:""},{default:De(()=>[h.value?(ie(),be("div",rDn,[p("div",sDn,[p("div",aDn,[b[2]||(b[2]=p("h3",{class:"section-title"},"配置信息",-1)),u.value?(ie(),kt(A(ySn),{key:0,config:u.value,"script-id":h.value.scriptId,editable:!0,"manufacturer-disabled":!0,onChange:v},null,8,["config","script-id"])):et("",!0)]),p("div",cDn,[t(y,{type:"primary",size:"large",block:"",loading:s.value,onClick:k},{icon:De(()=>[t(C)]),default:De(()=>[b[3]||(b[3]=cn(" 生成视频 ",-1))]),_:1},8,["loading"]),b[4]||(b[4]=p("p",{class:"action-hint"},"每次生成可能产生不同的结果,可多次尝试",-1))])]),p("div",dDn,[p("h3",uDn,[b[5]||(b[5]=cn(" 生成结果 ",-1)),g.value.length?(ie(),be("span",hDn,jt(g.value.length)+"个",1)):et("",!0)]),g.value.length?(ie(),be("div",kDn,[(ie(!0),be(Gt,null,Qn(g.value,O=>(ie(),be("div",{key:O.id,class:Ae(["result-card",{selected:h.value.selectedResultId===O.id,success:O.state===1,generating:O.state===0,failed:O.state===-1}]),onClick:D=>f(O)},[O.state===1?(ie(),be(Gt,{key:0},[p("div",{class:"video-cover",onClick:Fn(D=>w(O),["stop"])},[p("img",{src:O.firstFrame||O.filePath,alt:"视频封面"},null,8,gDn),p("div",mDn,[t(x,{theme:"filled",size:24,fill:"#fff"})]),O.duration?(ie(),be("div",wDn,jt(m(O.duration)),1)):et("",!0)],8,vDn),p("div",LDn,[h.value.selectedResultId!==O.id?(ie(),kt(y,{key:0,type:"primary",size:"small",onClick:Fn(D=>f(O),["stop"])},{default:De(()=>[...b[6]||(b[6]=[cn(" 选择此视频 ",-1)])]),_:1},8,["onClick"])):(ie(),be("span",bDn,[t(M,{theme:"filled",size:14}),b[7]||(b[7]=cn(" 已选择 ",-1))]))])],64)):O.state===0?(ie(),be("div",CDn,[...b[8]||(b[8]=[p("div",{class:"loading-spinner"},null,-1),p("span",null,"生成中...",-1)])])):(ie(),be("div",yDn,[t(W,{theme:"filled",size:24,fill:"#ef4444"}),b[9]||(b[9]=p("span",null,"生成失败",-1))]))],10,fDn))),128))])):(ie(),be("div",xDn,[p("div",jDn,[t(S,{size:48})]),b[10]||(b[10]=p("p",{class:"empty-title"},"暂无生成结果",-1)),b[11]||(b[11]=p("p",{class:"empty-desc"},"点击左侧按钮开始生成视频",-1))]))])])):et("",!0),t(H,{open:a.value,"onUpdate:open":b[0]||(b[0]=O=>a.value=O),title:null,footer:null,width:"800px",centered:"",destroyOnClose:"",wrapClassName:"video-player-modal"},{default:De(()=>[p("div",MDn,[c.value?(ie(),be("video",{key:0,ref_key:"videoRef",ref:d,src:c.value.filePath,controls:"",autoplay:"",class:"video-element"},null,8,ADn)):et("",!0)])]),_:1},8,["open"])]),_:1},8,["open"])}}}),SDn=Xo(WDn,[["__scopeId","data-v-f15d6c70"]]),DDn={class:"storyboard-video"},HDn={class:"header"},TDn={class:"title"},zDn={class:"icon-wrapper"},PDn={key:0,class:"count"},EDn=["disabled"],ODn={class:"content"},VDn={key:0,class:"video-grid"},BDn=["onClick"],IDn={class:"video-index"},NDn={class:"cover-wrapper"},RDn={key:0,class:"status-wrapper generating"},FDn={class:"status-hint"},ZDn=["src"],XDn={class:"play-overlay"},UDn={class:"play-button"},GDn={key:0,class:"duration-badge"},YDn={key:2,class:"status-wrapper pending"},qDn={class:"pending-icon"},KDn={class:"info-wrapper"},JDn={class:"config-info"},QDn={class:"manufacturer-tag"},$Dn={class:"resolution-tag"},_Dn={class:"duration-tag"},pDn={class:"prompt-text"},eHn=["onClick"],tHn={key:1,class:"empty-state"},nHn={class:"empty-icon"},iHn=_e({__name:"generateVideo",props:{scriptId:{},disableBtn:{type:Boolean},canGenerate:{type:Boolean}},setup(e){const n=iW(),{currentConfigs:i}=zr(n),o=_(!1),l=_(!1),r=_(null),s={volcengine:"豆包",runninghub:"Sora",openAi:"OpenAI"};function a(m){return s[m]||m}function c(m){const k=Math.floor(m/60),f=Math.floor(m%60);return`${k}:${f.toString().padStart(2,"0")}`}function d(m){return n.getSelectedResult(m)}function u(m){return n.getResultsByConfigId(m).some(f=>f.state===0)}function h(m){return n.getResultsByConfigId(m).length}function g(m){r.value=m.id,l.value=!0}function v(m){Zo.confirm({title:"确认删除",content:"删除配置后,关联的所有生成结果也会被删除,确定要删除吗?",okText:"确定",cancelText:"取消",onOk(){n.removeConfig(m),Sn.success("删除成功")}})}return(m,k)=>{const f=nn("i-pic"),w=nn("i-video-two"),L=nn("i-play-one"),b=nn("i-setting-config"),C=nn("i-delete");return ie(),be("div",DDn,[p("div",HDn,[p("div",TDn,[p("div",zDn,[t(f,{size:20,class:"icon"})]),k[3]||(k[3]=p("span",null,"视频配置",-1)),A(i).length?(ie(),be("span",PDn,jt(A(i).length),1)):et("",!0)]),e.canGenerate?(ie(),be("button",{key:0,disabled:!e.disableBtn,class:"generate-btn",onClick:k[0]||(k[0]=y=>o.value=!0)},[t(w,{size:18}),k[4]||(k[4]=p("span",null,"添加配置",-1))],8,EDn)):et("",!0)]),p("div",ODn,[A(i).length?(ie(),be("div",VDn,[(ie(!0),be(Gt,null,Qn(A(i),(y,x)=>{var M,W,S,H;return ie(),be("div",{key:y.id,class:"video-card",onClick:O=>g(y)},[p("div",IDn,"#"+jt(x+1),1),p("div",NDn,[u(y.id)?(ie(),be("div",RDn,[k[5]||(k[5]=p("div",{class:"loading-spinner"},null,-1)),k[6]||(k[6]=p("span",{class:"status-text"},"正在生成中...",-1)),p("span",FDn,jt(h(y.id))+"个结果",1)])):((M=d(y.id))==null?void 0:M.state)===1?(ie(),be(Gt,{key:1},[p("img",{src:((W=d(y.id))==null?void 0:W.firstFrame)||((S=d(y.id))==null?void 0:S.filePath),class:"cover-image",alt:"视频封面"},null,8,ZDn),p("div",XDn,[p("div",UDn,[t(L,{theme:"filled",size:32,fill:"#fff"})])]),(H=d(y.id))!=null&&H.duration?(ie(),be("div",GDn,jt(c(d(y.id).duration)),1)):et("",!0)],64)):(ie(),be("div",YDn,[p("div",qDn,[t(b,{size:32})]),k[7]||(k[7]=p("span",{class:"status-text"},"待生成",-1)),k[8]||(k[8]=p("span",{class:"status-hint"},"点击进入生成",-1))]))]),p("div",KDn,[p("div",JDn,[p("span",QDn,jt(a(y.manufacturer)),1),p("span",$Dn,jt(y.resolution),1),p("span",_Dn,jt(y.duration)+"s",1)]),p("p",pDn,jt(y.prompt||"暂无描述"),1)]),p("button",{class:"delete-btn",onClick:Fn(O=>v(y.id),["stop"])},[t(C,{size:16})],8,eHn)],8,BDn)}),128))])):(ie(),be("div",tHn,[p("div",nHn,[t(w,{size:48})]),k[9]||(k[9]=p("p",{class:"empty-title"},"暂无视频配置",-1)),k[10]||(k[10]=p("p",{class:"empty-desc"},"点击上方按钮添加视频配置",-1))]))]),o.value&&e.scriptId?(ie(),kt(lDn,{key:0,modelValue:o.value,"onUpdate:modelValue":k[1]||(k[1]=y=>o.value=y),scriptId:e.scriptId},null,8,["modelValue","scriptId"])):et("",!0),l.value?(ie(),kt(SDn,{key:1,modelValue:l.value,"onUpdate:modelValue":k[2]||(k[2]=y=>l.value=y),configId:r.value},null,8,["modelValue","configId"])):et("",!0)])}}}),oHn=Xo(iHn,[["__scopeId","data-v-372b7ae6"]]),lHn={class:"batch-download"},rHn={class:"header"},sHn={class:"title"},aHn={class:"icon-wrapper"},cHn={key:0,class:"count-badge"},dHn=["disabled"],uHn={class:"modal-content"},hHn={class:"modal-header"},kHn={class:"modal-title"},fHn={class:"action-bar"},vHn={class:"select-info"},gHn={class:"info-left"},mHn={class:"select-count"},wHn={key:0,class:"selected-hint"},LHn={class:"info-right"},bHn={class:"video-list"},CHn={key:0,class:"video-grid"},yHn=["onClick"],xHn={key:0,class:"select-indicator"},jHn={key:1,class:"unavailable-badge"},MHn={class:"thumb-wrapper"},AHn=["src"],WHn={class:"thumb-overlay"},SHn={class:"play-icon"},DHn={class:"video-info"},HHn={class:"video-title"},THn={class:"video-meta"},zHn={class:"meta-tag resolution"},PHn={class:"meta-tag model"},EHn={key:1,class:"empty-state"},OHn={class:"empty-icon"},VHn={class:"modal-footer"},BHn=["disabled"],IHn=_e({__name:"downVideo",props:{modelValue:{default:[]},modelModifiers:{}},emits:["update:modelValue"],setup(e){const n=Mr(e,"modelValue"),i=_(!1),o=_([]),l=P(()=>n.value.some(f=>f.filePath)),r=P(()=>n.value.filter(f=>f.filePath).length),s=P(()=>{const f=n.value.filter(w=>w.filePath);return o.value.length===f.length&&f.length>0}),a=P(()=>o.value.length*5*1024*1024),c=f=>o.value.includes(f),d=f=>{const w=o.value.indexOf(f);w>-1?o.value.splice(w,1):o.value.push(f)},u=()=>{s.value?o.value=[]:o.value=n.value.filter(f=>f.filePath).map(f=>f.id)};function h(f){return f<1024?f+" B":f<1024*1024?(f/1024).toFixed(1)+" KB":f<1024*1024*1024?(f/(1024*1024)).toFixed(1)+" MB":(f/(1024*1024*1024)).toFixed(1)+" GB"}function g(){i.value=!0,o.value=n.value.filter(f=>f.filePath).map(f=>f.id)}async function v(f,w){try{const L=await fetch(f);if(!L.ok)throw new Error("文件无法访问");const b=await L.blob(),C=URL.createObjectURL(b),y=document.createElement("a");y.href=C,y.download=w,y.style.display="none",document.body.appendChild(y),y.click(),setTimeout(()=>{URL.revokeObjectURL(C),document.body.removeChild(y)},100)}catch(L){throw console.error("下载失败:",L),L}}async function m(){if(o.value.length===0){Sn.warning("请至少选择一个视频");return}const f=n.value.filter(L=>o.value.includes(L.id)&&L.filePath);if(f.length===0){Sn.warning("选中的视频没有可下载的文件");return}const w="download";Sn.loading({content:`正在下载 ${f.length} 个视频...`,key:w,duration:0});try{for(let L=0;Lx.id===b.id)+1}.mp4`;await v(b.filePath,y),LsetTimeout(x,500))}Sn.success({content:"下载完成!",key:w}),i.value=!1}catch(L){console.error("下载错误:",L),Sn.error({content:"下载失败,请重试",key:w})}}function k(f){f.target.src="/default-thumb.png"}return(f,w)=>{const L=nn("i-download"),b=nn("i-check-correct"),C=nn("i-video-two"),y=nn("i-close"),x=nn("i-close-one"),M=nn("i-check"),W=nn("i-play"),S=nn("i-pic"),H=nn("i-cpu"),O=Zo;return ie(),be("div",lHn,[p("div",rHn,[p("div",sHn,[p("div",aHn,[t(L,{size:20,class:"icon"})]),w[3]||(w[3]=p("span",null,"批量下载",-1)),r.value?(ie(),be("span",cHn,jt(r.value)+" 个可下载",1)):et("",!0)]),p("button",{onClick:g,disabled:!l.value,class:"download-btn"},[t(b,{size:18}),w[4]||(w[4]=p("span",null,"选择视频",-1))],8,dHn)]),t(O,{open:i.value,"onUpdate:open":w[2]||(w[2]=D=>i.value=D),title:null,width:"85vw",centered:"",footer:null,wrapClassName:"download-modal"},{default:De(()=>[p("div",uHn,[p("div",hHn,[p("div",kHn,[t(C,{size:24}),w[5]||(w[5]=p("span",null,"选择要下载的视频",-1))]),p("button",{class:"close-btn",onClick:w[0]||(w[0]=D=>i.value=!1)},[t(y,{size:20})])]),p("div",fHn,[p("div",vHn,[p("div",gHn,[p("span",mHn,[w[6]||(w[6]=cn(" 已选择 ",-1)),p("strong",null,jt(o.value.length),1),cn(" / "+jt(n.value.length),1)]),o.value.length>0?(ie(),be("span",wHn,"(共 "+jt(h(a.value))+")",1)):et("",!0)]),p("div",LHn,[p("button",{class:"select-all-btn",onClick:u},[s.value?(ie(),kt(x,{key:1,size:16})):(ie(),kt(b,{key:0,size:16})),cn(" "+jt(s.value?"取消全选":"全选"),1)])])])]),p("div",bHn,[n.value.length?(ie(),be("div",CHn,[(ie(!0),be(Gt,null,Qn(n.value,(D,z)=>(ie(),be("div",{key:D.id,class:Ae(["video-card",{selected:c(D.id),disabled:!D.filePath}]),onClick:V=>D.filePath&&d(D.id)},[c(D.id)?(ie(),be("div",xHn,[t(M,{size:16})])):et("",!0),D.filePath?et("",!0):(ie(),be("div",jHn,"不可用")),p("div",MHn,[p("img",{src:D.firstFrame,alt:"视频封面",class:"video-thumb",onError:k},null,40,AHn),p("div",WHn,[p("div",SHn,[t(W,{size:24})])])]),p("div",DHn,[p("h4",HHn,"视频 #"+jt(z+1),1),p("div",THn,[p("span",zHn,[t(S,{size:12}),cn(" "+jt(D.resolution||"未知"),1)]),p("span",PHn,[t(H,{size:12}),cn(" "+jt(D.model||"未知"),1)])])])],10,yHn))),128))])):(ie(),be("div",EHn,[p("div",OHn,[t(C,{size:48})]),w[7]||(w[7]=p("p",{class:"empty-title"},"暂无视频",-1)),w[8]||(w[8]=p("p",{class:"empty-desc"},"没有可供下载的视频",-1))]))]),p("div",VHn,[p("button",{class:"cancel-btn",onClick:w[1]||(w[1]=D=>i.value=!1)},"取消"),p("button",{class:"confirm-btn",disabled:o.value.length===0,onClick:m},[t(L,{size:18}),p("span",null,"下载选中项 ("+jt(o.value.length)+")",1)],8,BHn)])])]),_:1},8,["open"])])}}}),NHn=Xo(IHn,[["__scopeId","data-v-570e8b38"]]),RHn={class:"scriptManager"},FHn={class:"data"},ZHn={class:"newStoryboard"},XHn={key:0,class:"noneScripts"},UHn={class:"smNoneIcon"},GHn={key:1,class:"scriptsList"},YHn={class:"storyboardImage"},qHn={class:"storyboardImage"},KHn={class:"storyboardImage"},JHn=_e({__name:"index",setup(e){const{project:n,currentScriptId:i}=zr(Qr()),o=iW(),{currentConfigs:l}=zr(o),r=_([]),s=_([]),a=_(-1),c=P(()=>l.value.filter(k=>k.selectedResultId).map(k=>{const f=o.getSelectedResult(k.id);return f?{id:f.id,filePath:f.filePath,firstFrame:f.firstFrame,duration:f.duration,prompt:f.prompt,state:f.state,time:f.duration,model:"",scriptId:k.scriptId,resolution:k.resolution,storyboardImgs:[]}:null}).filter(k=>k!==null)),d=P(()=>{var k;return Number((k=n.value)==null?void 0:k.id)}),u=P(()=>{var f;const k=r.value.find(w=>w.id===i.value);return(((f=k==null?void 0:k.content)==null?void 0:f.length)??0)>0}),h=P(()=>{if(!r.value.length)return!1;const k=r.value.find(f=>f.id===a.value);return!!(k!=null&&k.content)});function g(k){k!==void 0&&(i.value=k,m(k),o.setCurrentScript(k,d.value))}async function v(){try{const{data:k}=await Di.post("/script/geScriptApi",{projectId:d.value});r.value=k}catch{Sn.error("获取剧本列表失败")}}async function m(k){if(k===-1)return;const{data:f}=await Di.post("/storyboard/getStoryboard",{projectId:d.value,scriptId:k});s.value=f}return ii(()=>{o.cleanup()}),un(v),(k,f)=>{const w=nn("i-file-text");return ie(),be("div",RHn,[f[5]||(f[5]=p("div",{class:"smHead jb ac"},[p("div",null,[p("h2",{class:"smTitle"},"剧本管理"),p("p",{class:"smSub"},"管理和编辑分集剧本内容")])],-1)),p("div",FHn,[p("div",ZHn,[r.value.length===0?(ie(),be("div",XHn,[p("div",UHn,[t(w,{size:48,class:"icon"})]),f[4]||(f[4]=p("h3",{class:"smNoneTitle"},"暂无剧本",-1))])):(ie(),be("div",GHn,[t(IMn,{modelValue:r.value,"onUpdate:modelValue":f[0]||(f[0]=L=>r.value=L),scriptId:a.value,"onUpdate:scriptId":f[1]||(f[1]=L=>a.value=L),onGetScriptData:v,onChange:g},null,8,["modelValue","scriptId"])]))]),di(p("div",YHn,[t(JAn,{data:s.value,disableBtn:r.value.length,canGenerate:u.value,scriptId:a.value,projectId:d.value,onSave:f[2]||(f[2]=L=>m(A(i)))},null,8,["data","disableBtn","canGenerate","scriptId","projectId"])],512),[[Bi,r.value.length>0&&u.value]]),di(p("div",qHn,[t(oHn,{disableBtn:h.value,canGenerate:u.value,scriptId:a.value},null,8,["disableBtn","canGenerate","scriptId"])],512),[[Bi,r.value.length>0&&s.value.length>0]]),di(p("div",KHn,[t(NHn,{modelValue:c.value,"onUpdate:modelValue":f[3]||(f[3]=L=>c.value=L)},null,8,["modelValue"])],512),[[Bi,s.value.length>0&&c.value.length>0]])])])}}}),QHn=Xo(JHn,[["__scopeId","data-v-a2287823"]]),$Hn={class:"projectDetail"},_Hn={class:"detailHeader"},pHn={class:"headerBar"},eTn={class:"headerLeft"},tTn={class:"info ac"},nTn={class:"title"},iTn={class:"meta"},oTn={key:0},lTn={class:"nav"},rTn=["onClick"],sTn={class:"navLabel"},aTn={class:"main"},cTn=_e({__name:"index",setup(e){const{project:n}=zr(Qr()),i=B2t(),o=Number(i.query.id);un(async()=>{await Qr().setProjectById(o)});const l=i5(),r=[{id:"overview",label:"项目概览",icon:"i-more-app"},{id:"originalText",label:"小说原文",icon:"i-file-text"},{id:"outline",label:"大纲管理",icon:"i-mindmap-list"},{id:"assets",label:"资产管理",icon:"i-data-file"},{id:"script",label:"剧本管理",icon:"i-ad-product"}],s=_("overview");function a(d){s.value=d}function c(){l.push("/project")}return(d,u)=>{var g,v,m,k;const h=nn("i-left");return ie(),be("div",$Hn,[p("div",_Hn,[p("div",pHn,[p("div",eTn,[p("button",{class:"backBtn",onClick:c},[t(h,{size:20})]),p("div",tTn,[p("h1",nTn,jt((g=A(n))==null?void 0:g.name),1),p("p",iTn,[(v=A(n))!=null&&v.updatedAt&&((m=A(n))==null?void 0:m.updatedAt)>0?(ie(),be("span",oTn,"最后更新 "+jt(A(ri)((k=A(n))==null?void 0:k.updatedAt).format("YYYY-MM-DD HH:mm:ss")),1)):et("",!0)])])])]),p("div",lTn,[(ie(),be(Gt,null,Qn(r,f=>p("button",{key:f.id,class:Ae(["navBtn",{navActive:f.id===A(s)}]),onClick:w=>a(f.id)},[(ie(),kt(Ai(f.icon),{size:18})),p("span",sTn,jt(f.label),1)],10,rTn)),64))])]),p("div",aTn,[A(s)==="overview"?(ie(),kt(Emn,{key:0})):et("",!0),A(s)==="originalText"?(ie(),kt(iCn,{key:1})):et("",!0),A(s)==="outline"?(ie(),kt(hjn,{key:2})):et("",!0),A(s)==="assets"?(ie(),kt(_jn,{key:3})):et("",!0),A(s)==="script"?(ie(),kt(QHn,{key:4})):et("",!0)])])}}}),dTn=Xo(cTn,[["__scopeId","data-v-8a53c869"]]),uTn=Object.freeze(Object.defineProperty({__proto__:null,default:dTn},Symbol.toStringTag,{value:"Module"})),hTn={class:"manufacturerOption"},kTn={class:"priorityControl"},fTn={key:2,class:"formTip"},vTn={key:0,class:"formTip"},gTn={class:"formTip"},mTn=["href"],wTn={class:"formActions"},LTn=_e({__name:"configAddForm",props:Ql({data:{}},{modelValue:{type:Boolean},modelModifiers:{}}),emits:Ql(["save"],["update:modelValue"]),setup(e,{emit:n}){const i={volcengine:{label:"火山引擎",value:"volcengine",showModel:!1,showBaseUrl:!0,baseUrlPlaceholder:"https://ark.cn-beijing.volces.com/api/v3/contents/generations/tasks",baseUrlTip:"请填写完整路径,包括V3后面的Path",defaultBaseUrl:"https://ark.cn-beijing.volces.com/api/v3/contents/generations/tasks",apiKeyPlaceholder:"请输入火山引擎 API Key,注意不需要 Bearer 前缀",apiKeyTip:"在火山引擎控制台创建API Key",apiKeyLink:"https://console.volcengine.com/ark"},apimart:{label:"APIMart",value:"apimart",showModel:!1,showBaseUrl:!1,apiKeyPlaceholder:"请输入 APIMart 的 API Key",apiKeyTip:"在 APIMart 控制台获取",apiKeyLink:"https://apimart.ai/zh/keys"},runninghub:{label:"RunningHub",value:"runninghub",showModel:!1,showBaseUrl:!1,apiKeyPlaceholder:"请输入 RunningHub 的密钥,注意不需要 Bearer 前缀",apiKeyTip:"在 RunningHub 控制台获取",apiKeyLink:"https://runninghub.cn"},openAi:{label:"OpenAI",value:"openAi",disabled:!0,tag:"暂不支持",tagColor:"default",showModel:!0,showBaseUrl:!0,modelPlaceholder:"输入模型名称,如:gpt-4",modelTip:"OpenAI 目前暂不支持视频生成",baseUrlPlaceholder:"https://api.openai.com/v1",baseUrlTip:"OpenAI API 服务地址",defaultBaseUrl:"https://api.openai.com/v1",apiKeyPlaceholder:"sk-xxxx(无需 Bearer 前缀)",apiKeyTip:"您的 OpenAI API 密钥",apiKeyLink:"https://platform.openai.com/api-keys"}},o=P(()=>Object.values(i)),l=P(()=>i[h.value.manufacturer]||i.custom),r=P(()=>{const w=l.value,L={name:[{required:!0,message:"请输入配置名称",trigger:"blur"}],manufacturer:[{required:!0,message:"请选择厂商",trigger:"change"}],apiKey:[{required:!0,message:"请输入 API Key",trigger:"blur"}]};return w.showModel&&(L.model=[{required:!0,message:"请输入或选择模型",trigger:"blur"}]),w.showBaseUrl&&(L.baseUrl=[{required:!0,message:"请输入 Base URL",trigger:"blur"},{type:"url",message:"请输入有效的 URL 地址",trigger:"blur"}]),L}),s=n,a=Mr(e,"modelValue"),c=e,d=_(),u=_(!1),h=_({id:-1,name:"",manufacturer:"runninghub",index:0,model:"",baseUrl:"",apiKey:"",createTime:0});Ve(a,w=>{var L;w?h.value=JSON.parse(JSON.stringify(c.data)):((L=d.value)==null||L.resetFields(),h.value={id:-1,name:"",manufacturer:"runninghub",index:0,model:"",baseUrl:"",apiKey:"",createTime:0})});function g(w){const L=i[w];L&&(h.value.model="",h.value.baseUrl=L.defaultBaseUrl||"")}function v(){h.value.index>0&&h.value.index--}function m(){h.value.index++}async function k(){if(d.value)try{await d.value.validate(),u.value=!0,await new Promise(w=>setTimeout(w,300)),s("save",{...h.value}),a.value=!1}catch{}finally{u.value=!1}}function f(){a.value=!1}return(w,L)=>{const b=ql,C=qf,y=fu,x=Xm,M=Gr,W=nn("i-minus"),S=nl,H=A8,O=nn("i-plus"),D=lj,z=nn("i-link-one"),V=Nc,Z=Zo;return ie(),kt(Z,{open:a.value,"onUpdate:open":L[7]||(L[7]=B=>a.value=B),title:"配置视频模型",footer:null,width:"520px",maskClosable:!1,centered:"",class:"configModal"},{default:De(()=>[t(V,{model:h.value,rules:r.value,ref_key:"formRef",ref:d,layout:"vertical",autocomplete:"off",class:"configForm"},{default:De(()=>[t(C,{label:"配置名称",name:"name"},{default:De(()=>[t(b,{value:h.value.name,"onUpdate:value":L[0]||(L[0]=B=>h.value.name=B),placeholder:"请输入配置名称,如:默认配置"},null,8,["value"])]),_:1}),t(C,{label:"厂商",name:"manufacturer"},{default:De(()=>[t(M,{value:h.value.manufacturer,"onUpdate:value":L[1]||(L[1]=B=>h.value.manufacturer=B),placeholder:"选择AI服务提供商",onChange:g},{default:De(()=>[(ie(!0),be(Gt,null,Qn(o.value,B=>(ie(),kt(x,{disabled:B.disabled,key:B.value,value:B.value},{default:De(()=>[p("div",hTn,[p("span",null,jt(B.label),1),B.tag?(ie(),kt(y,{key:0,color:B.tagColor,size:"small"},{default:De(()=>[cn(jt(B.tag),1)]),_:2},1032,["color"])):et("",!0)])]),_:2},1032,["disabled","value"]))),128))]),_:1},8,["value"])]),_:1}),t(C,{label:"优先级",name:"index"},{default:De(()=>[p("div",kTn,[t(S,{class:"priorityBtn",onClick:v,disabled:h.value.index<=0},{default:De(()=>[t(W,{theme:"outline",size:"14",fill:"currentColor"})]),_:1},8,["disabled"]),t(H,{value:h.value.index,"onUpdate:value":L[2]||(L[2]=B=>h.value.index=B),min:0,controls:!1,class:"priorityInput"},null,8,["value"]),t(S,{class:"priorityBtn",onClick:m},{default:De(()=>[t(O,{theme:"outline",size:"14",fill:"currentColor"})]),_:1})]),L[8]||(L[8]=p("div",{class:"formTip"},"数值越小优先级越高",-1))]),_:1}),l.value.showModel?(ie(),kt(C,{key:0,label:"模型",name:"model"},{default:De(()=>{var B;return[(B=l.value.models)!=null&&B.length?(ie(),kt(M,{key:0,value:h.value.model,"onUpdate:value":L[3]||(L[3]=T=>h.value.model=T),placeholder:l.value.modelPlaceholder,"show-search":"","allow-clear":""},{default:De(()=>[(ie(!0),be(Gt,null,Qn(l.value.models,T=>(ie(),kt(x,{key:T.value,value:T.value},{default:De(()=>[cn(jt(T.label),1)]),_:2},1032,["value"]))),128))]),_:1},8,["value","placeholder"])):(ie(),kt(b,{key:1,value:h.value.model,"onUpdate:value":L[4]||(L[4]=T=>h.value.model=T),placeholder:l.value.modelPlaceholder},null,8,["value","placeholder"])),l.value.modelTip?(ie(),be("div",fTn,jt(l.value.modelTip),1)):et("",!0)]}),_:1})):et("",!0),l.value.showBaseUrl?(ie(),kt(C,{key:1,label:"Base URL",name:"baseUrl"},{default:De(()=>[t(b,{value:h.value.baseUrl,"onUpdate:value":L[5]||(L[5]=B=>h.value.baseUrl=B),placeholder:l.value.baseUrlPlaceholder},null,8,["value","placeholder"]),l.value.baseUrlTip?(ie(),be("div",vTn,jt(l.value.baseUrlTip),1)):et("",!0)]),_:1})):et("",!0),t(C,{label:"API Key",name:"apiKey"},{default:De(()=>[t(D,{value:h.value.apiKey,"onUpdate:value":L[6]||(L[6]=B=>h.value.apiKey=B),placeholder:l.value.apiKeyPlaceholder},null,8,["value","placeholder"]),p("div",gTn,[p("span",null,jt(l.value.apiKeyTip),1),l.value.apiKeyLink?(ie(),be("a",{key:0,href:l.value.apiKeyLink,target:"_blank",class:"tipLink"},[L[9]||(L[9]=cn(" 获取API Key ",-1)),t(z,{theme:"outline",size:"12",fill:"currentColor"})],8,mTn)):et("",!0)])]),_:1}),p("div",wTn,[t(S,{size:"large",onClick:f},{default:De(()=>[...L[10]||(L[10]=[cn("取消",-1)])]),_:1}),t(S,{type:"primary",size:"large",onClick:k,loading:u.value},{default:De(()=>[...L[11]||(L[11]=[cn("保存配置",-1)])]),_:1},8,["loading"])])]),_:1},8,["model","rules"])]),_:1},8,["open"])}}}),bTn=Xo(LTn,[["__scopeId","data-v-6e33cbf6"]]),CTn={class:"modelCardHeader"},yTn={class:"modelInfo"},xTn={class:"modelMeta"},jTn={class:"modelName"},MTn={class:"modelProvider"},ATn={class:"actionBtn danger"},WTn={class:"modelCardBody"},STn={class:"infoGrid"},DTn={class:"infoItem"},HTn={class:"infoValue url"},TTn={class:"infoItem"},zTn={class:"infoValue"},PTn={class:"priorityBadge"},ETn={class:"infoItem"},OTn={class:"infoValue"},VTn={class:"infoItem"},BTn={class:"infoValue secret"},ITn={class:"infoItem"},NTn={class:"infoValue"},RTn=_e({__name:"modalInfo",props:{config:{}},emits:["edit","delete"],setup(e,{emit:n}){const i=e,o=n,l={runninghub:"RunningHub",openAi:"OpenAI",volcengine:"火山引擎",apimart:"APIMart",gemini:"Gemini"};function r(d){return l[d]||d}function s(d){return d?ri(d).format("YYYY-MM-DD HH:mm"):"-"}function a(){o("edit",i.config)}function c(){o("delete",i.config)}return(d,u)=>{var k;const h=nn("i-edit"),g=ku,v=nn("i-delete"),m=$m;return ie(),be("div",{class:"modelCard",onClick:a},[p("div",CTn,[p("div",yTn,[p("div",xTn,[p("h4",jTn,jt(e.config.name),1),p("span",MTn,jt(r(e.config.manufacturer)),1)])]),p("div",{class:"modelActions",onClick:u[0]||(u[0]=Fn(()=>{},["stop"]))},[t(g,{title:"编辑"},{default:De(()=>[p("button",{class:"actionBtn",onClick:a},[t(h,{theme:"outline",size:"16",fill:"currentColor"})])]),_:1}),t(m,{title:"确定要删除这个配置吗?",onConfirm:c,placement:"topRight"},{default:De(()=>[t(g,{title:"删除"},{default:De(()=>[p("button",ATn,[t(v,{theme:"outline",size:"16",fill:"currentColor"})])]),_:1})]),_:1})])]),p("div",WTn,[p("div",STn,[p("div",DTn,[u[1]||(u[1]=p("span",{class:"infoLabel"},"Base URL",-1)),p("span",HTn,jt(e.config.baseUrl||"-"),1)]),p("div",TTn,[u[2]||(u[2]=p("span",{class:"infoLabel"},"优先级",-1)),p("span",zTn,[p("span",PTn,jt(e.config.index),1)])]),p("div",ETn,[u[3]||(u[3]=p("span",{class:"infoLabel"},"模型",-1)),p("span",OTn,jt(e.config.model?e.config.model:"-"),1)]),p("div",VTn,[u[4]||(u[4]=p("span",{class:"infoLabel"},"API Key",-1)),p("span",BTn,"****"+jt((k=e.config.apiKey)==null?void 0:k.slice(-4)),1)]),p("div",ITn,[u[5]||(u[5]=p("span",{class:"infoLabel"},"创建时间",-1)),p("span",NTn,jt(s(e.config.createTime)),1)])])])])}}}),FTn=Xo(RTn,[["__scopeId","data-v-8777372c"]]),ZTn={class:"promptEditorContainer"},XTn={class:"promptSidebar"},UTn={class:"typeHeader"},GTn=["onClick"],YTn={class:"promptName"},qTn={class:"promptCode"},KTn={key:0,class:"emptyList"},JTn={class:"promptEditor"},QTn={class:"editorHeader"},$Tn={class:"editorInfo"},_Tn={class:"titleRow"},pTn={class:"editorTitle"},ezn={key:0,class:"customBadge"},tzn={key:1,class:"defaultBadge"},nzn={class:"editorMeta"},izn={class:"promptCodeBadge"},ozn={key:0,class:"parentInfo"},lzn={class:"editorActions"},rzn={class:"editorBody"},szn={class:"promptEditSection"},azn={class:"editorFooter"},czn={class:"editorTip"},dzn={key:0},uzn={key:1},hzn={key:1,class:"emptyEditor"},kzn=_e({__name:"promptEditor",props:{modelValue:{type:Boolean,default:!1},modelModifiers:{}},emits:["update:modelValue"],setup(e){const n=Mr(e,"modelValue"),i=_([]),o=_(null),l=_(""),r=_(!1),s=P(()=>{const k={};return i.value.forEach(w=>{k[w.type]||(k[w.type]=[]),k[w.type].push(w)}),["system","mainAgent","subAgent"].filter(w=>k[w]).map(w=>({type:w,items:k[w]}))}),a=P(()=>{if(!o.value)return!1;const k=u(o.value.defaultValue||"");return l.value.trim()!==""&&l.value!==k});function c(k){return{mainAgent:"主Agent",subAgent:"子Agent",system:"系统提示词"}[k]||k}function d(k){return{mainAgent:"purple",subAgent:"blue",system:"green"}[k]||"default"}function u(k){return k?k.replace(/\\n/g,` +`):""}function h(k){o.value=k;const f=k.customValue||k.defaultValue||"";l.value=u(f)}function g(){o.value&&(l.value=u(o.value.defaultValue||""),Sn.info("已重置为默认值,点击保存生效"))}async function v(){if(o.value){r.value=!0;try{const k=u(o.value.defaultValue||""),f=l.value===k?"":l.value.trim();await Di.post("/prompt/updatePrompt",{id:o.value.id,code:o.value.code,customValue:f});const w=i.value.findIndex(L=>{var b;return L.code===((b=o.value)==null?void 0:b.code)});w!==-1&&(i.value[w].customValue=f),Sn.success("保存成功")}catch{Sn.error("保存失败")}finally{r.value=!1}}}async function m(){try{const k=await Di.get("/prompt/getPrompts");i.value=k.data||[],i.value.length>0&&!o.value&&h(i.value[0])}catch{Sn.error("获取提示词列表失败")}}return Ve(n,k=>{k?m():(o.value=null,l.value="")}),(k,f)=>{const w=nn("i-tag-one"),L=nn("i-inbox"),b=fu,C=nn("i-redo"),y=nl,x=nn("i-check"),M=Bs,W=nn("i-info"),S=nn("i-edit"),H=Pre;return ie(),kt(H,{top:"3vh",modelValue:n.value,"onUpdate:modelValue":f[1]||(f[1]=O=>n.value=O),title:"提示词管理",width:"80vw",footer:null,maskClosable:!1,centered:"",class:"promptEditorModal"},{default:De(()=>[p("div",ZTn,[p("div",XTn,[(ie(!0),be(Gt,null,Qn(s.value,O=>(ie(),be("div",{class:"promptTypeGroup",key:O.type},[p("div",UTn,[t(w,{theme:"outline",size:"14",fill:"currentColor"}),p("span",null,jt(c(O.type)),1)]),(ie(!0),be(Gt,null,Qn(O.items,D=>{var z;return ie(),be("div",{class:Ae(["promptItem",{active:((z=o.value)==null?void 0:z.code)===D.code}]),key:D.code,onClick:V=>h(D)},[p("span",YTn,jt(D.name),1),p("span",qTn,jt(D.code),1)],10,GTn)}),128))]))),128)),i.value.length===0?(ie(),be("div",KTn,[t(L,{theme:"outline",size:"32",fill:"#d1d5db"}),f[2]||(f[2]=p("span",null,"暂无提示词",-1))])):et("",!0)]),p("div",JTn,[o.value?(ie(),be(Gt,{key:0},[p("div",QTn,[p("div",$Tn,[p("div",_Tn,[p("h3",pTn,jt(o.value.name),1),a.value?(ie(),be("span",ezn,"已自定义")):(ie(),be("span",tzn,"默认值"))]),p("div",nzn,[t(b,{color:d(o.value.type)},{default:De(()=>[cn(jt(c(o.value.type)),1)]),_:1},8,["color"]),p("span",izn,jt(o.value.code),1),o.value.parentCode?(ie(),be("span",ozn,"父级: "+jt(o.value.parentCode),1)):et("",!0)])]),p("div",lzn,[t(y,{onClick:g},{default:De(()=>[t(C,{theme:"outline",size:"14",fill:"currentColor"}),f[3]||(f[3]=cn(" 一键重置 ",-1))]),_:1}),t(y,{type:"primary",onClick:v,loading:r.value},{default:De(()=>[t(x,{theme:"outline",size:"14",fill:"currentColor"}),f[4]||(f[4]=cn(" 保存 ",-1))]),_:1},8,["loading"])])]),p("div",rzn,[p("div",szn,[t(M,{value:l.value,"onUpdate:value":f[0]||(f[0]=O=>l.value=O),placeholder:"请输入提示词内容",autoSize:{minRows:18,maxRows:26},class:"promptTextarea"},null,8,["value"])]),p("div",azn,[p("div",czn,[t(W,{theme:"outline",size:"14",fill:"currentColor"}),a.value?(ie(),be("span",dzn,'当前使用自定义提示词,点击"一键重置"可恢复默认值')):(ie(),be("span",uzn,"当前使用默认提示词,编辑后将保存为自定义值"))])])])],64)):(ie(),be("div",hzn,[t(S,{theme:"outline",size:"48",fill:"#d1d5db"}),f[5]||(f[5]=p("p",null,"请从左侧选择一个提示词进行编辑",-1))]))])])]),_:1},8,["modelValue"])}}}),fzn=Xo(kzn,[["__scopeId","data-v-4964a2f4"]]),vzn={class:"settingContainer"},gzn={class:"settingInner"},mzn={key:1,class:"settingCard"},wzn={class:"cardHeader"},Lzn={class:"cardIcon purple"},bzn={class:"cardContent"},Czn={class:"formItem"},yzn={class:"settingCard"},xzn={class:"cardHeader"},jzn={class:"cardIcon blue"},Mzn={class:"cardContent"},Azn={class:"formGrid"},Wzn={class:"formItem"},Szn={class:"formItem"},Dzn={class:"cardHeader"},Hzn={class:"cardHeaderLeft"},Tzn={class:"cardTitle"},zzn={class:"cardContent"},Pzn={key:0,class:"modelList"},Ezn={key:0,class:"emptyState"},Ozn={key:1,class:"modelForm"},Vzn={class:"formItem"},Bzn={class:"formItem"},Izn={key:0,class:"formItem"},Nzn={class:"formItem"},Rzn={class:"settingCard"},Fzn={class:"cardHeader"},Zzn={class:"cardHeaderLeft"},Xzn={class:"cardIcon cyan"},Uzn={class:"settingCard danger"},Gzn={class:"cardHeader"},Yzn={class:"cardIcon red"},qzn={class:"cardContent"},Kzn={class:"dangerActions"},Jzn={class:"settingCard about"},Qzn={class:"cardHeader"},$zn={class:"cardIcon purple"},_zn={class:"cardContent"},pzn={class:"aboutInfo"},ePn={class:"aboutLinks"},tPn={class:"linkIcon"},nPn={class:"linkIcon"},iPn={class:"linkIcon"},oPn={class:"linkIcon"},lPn={class:"linkIcon"},rPn={class:"licenseBadge"},sPn={class:"pageFooter"},ST="https://github.com/HBAI-Ltd/Toonflow-app",mte="https://gitee.com/HBAI-Ltd/Toonflow-app",aPn=_e({__name:"index",setup(e){const n=_([]),i=_(!1),o=_(""),l=_(!1);async function r(){try{await Di.post("",{sql:o.value}),Sn.success("执行成功")}catch(E){E instanceof Error&&Sn.error(E.message)}}const s=_(!1),a=_({id:-1,name:"",manufacturer:"",index:0,model:"",baseUrl:"",apiKey:"",createTime:0});function c(E){if(E.id===-1)E.id=ri().valueOf(),n.value.push(E);else{const F=n.value.findIndex(X=>X.id===E.id);F!==-1&&(n.value[F]=E)}z()}function d(){a.value={id:-1,name:"",manufacturer:"runninghub",index:0,model:"",baseUrl:"",apiKey:"",createTime:0},s.value=!0}function u(E){a.value=E,s.value=!0}function h(E){n.value=n.value.filter(F=>F.id!==E.id),z()}function g(E){}function v(E){return{languageModel:"purple",imageModel:"green",videoModel:"orange"}[E]||"purple"}const m=[{label:"OpenAI请求格式",value:"openAi"}],k=[{label:"OpenAI",value:"openAi"},{label:"火山引擎",value:"volcengine"},{label:"APIMart",value:"apimart"},{label:"RunningHub",value:"runninghub"}];function f(E){return E==="languageModel"?m:E==="imageModel"?k:[]}const w={languageModel:"语言生成模型",imageModel:"图像生成模型",videoModel:"视频生成模型"};un(async()=>{await O(),D()});const L={model:"",apiKey:"",baseURL:"",manufacturer:""},b=_({id:null,apiKey:"",modalType:1,languageModel:{...L},imageModel:{...L},videoModel:{...L},audioModel:{...L},name:"",password:""}),C=i5();function y(){C.push("/project")}function x(){window.open(ST,"_blank")}function M(){window.open(mte,"_blank")}function W(){window.open(`${ST}/releases`,"_blank")}function S(){window.open(`${mte}/releases`,"_blank")}function H(){window.open(`${ST}/blob/master/LICENSE`,"_blank")}async function O(){var X,R,q;const F=(await Di.post("/setting/getSetting",{userId:Number(localStorage.getItem("userId"))})).data[0];n.value=F.videoModel,b.value={id:(F==null?void 0:F.id)??null,modalType:1,apiKey:(F==null?void 0:F.apiKey)??"",languageModel:{...L,...F==null?void 0:F.languageModel,manufacturer:((X=F==null?void 0:F.languageModel)==null?void 0:X.manufacturer)||"openAi"},imageModel:{...L,...F==null?void 0:F.imageModel,manufacturer:((R=F==null?void 0:F.imageModel)==null?void 0:R.manufacturer)||"openAi"},videoModel:{...L,...F==null?void 0:F.videoModel,manufacturer:((q=F==null?void 0:F.videoModel)==null?void 0:q.manufacturer)||"openAi"}}}function D(){Di.get("/user/getUser").then(E=>{b.value.name=E.data.name??"",b.value.password=E.data.password??""})}function z(){Di.post("/setting/updateSetting",{userId:Number(localStorage.getItem("userId")),id:b.value.id??null,type:b.value.modalType,languageModel:b.value.languageModel,imageModel:b.value.imageModel,videoModel:n.value,name:b.value.name,password:b.value.password}).then(()=>{Sn.success("设置更新成功")}).catch(()=>{Sn.error("设置更新失败")})}function V(E=1){return new Promise(F=>{const X=E===1?{title:"危险操作!确认要清空所有数据表吗?",content:"此操作会删除所有数据表的数据,且不可恢复。请谨慎操作!",okText:"继续操作"}:{title:"请再次确认",content:"真的要清空所有数据表吗?数据将无法恢复!",okText:"确认删除"};Zo.confirm({...X,cancelText:"取消",centered:!0,onOk:async()=>{F(E===1?await V(2):!0)},onCancel:()=>F(!1)})})}function Z(E=1){return new Promise(F=>{const X=E===1?{title:"危险操作!确认要删除所有数据表吗?",content:"此操作会删除所有数据表,且不可恢复。请谨慎操作!",okText:"继续操作"}:{title:"请再次确认",content:"真的要删除所有数据表吗?数据将无法恢复!",okText:"确认删除"};Zo.confirm({...X,cancelText:"取消",centered:!0,onOk:async()=>{F(E===1?await Z(2):!0)},onCancel:()=>F(!1)})})}async function B(){if(!await V()){Sn.info("操作已取消");return}try{await Di.post("/other/deleteAllData"),Sn.success("所有数据表已清空")}catch{Sn.error("操作失败,请重试")}}async function T(){if(!await Z()){Sn.info("操作已取消");return}try{await Di.post("/other/clearDatabase"),Sn.success("所有数据表已删除,3秒后自动退出,请重新打开")}catch{Sn.error("操作失败,请重试")}}return(E,F)=>{const X=nn("i-left"),R=nn("i-brain"),q=nn("i-key"),Y=lj,K=nn("i-lock"),Q=ql,ee=nn("i-pic"),J=nn("i-video"),ne=nn("i-plus"),le=nl,oe=nn("i-inbox"),$=Xm,se=Gr,te=nn("i-text"),G=nn("i-edit"),re=nn("i-delete"),ue=nn("i-clear"),ce=nn("i-info"),he=nn("i-github"),ke=nn("i-right"),ye=nn("i-code"),me=nn("i-refresh"),xe=nn("i-file-text"),Ce=nn("i-certificate"),Se=nn("i-check"),Te=Bs,Ee=Zo;return ie(),be(Gt,null,[p("div",vzn,[p("div",gzn,[p("div",{class:"backBtn",onClick:y},[t(X,{theme:"outline",size:"16",fill:"currentColor"}),F[9]||(F[9]=p("span",null,"返回",-1))]),F[42]||(F[42]=p("div",{class:"pageHeader"},[p("h1",{class:"pageTitle"},"设置"),p("p",{class:"pageDesc"},"配置API密钥和模型选项")],-1)),et("",!0),b.value.modalType==2?(ie(),be("section",mzn,[p("div",wzn,[p("div",Lzn,[t(q,{theme:"outline",size:"20",fill:"currentColor"})]),F[13]||(F[13]=p("span",{class:"cardTitle"},"API密钥配置",-1))]),p("div",bzn,[p("div",Czn,[F[14]||(F[14]=p("label",{class:"formLabel"},"API Key",-1)),t(Y,{value:b.value.apiKey,"onUpdate:value":F[1]||(F[1]=Oe=>b.value.apiKey=Oe),placeholder:"请输入API Key",class:"formInput"},null,8,["value"])])])])):et("",!0),p("section",yzn,[p("div",xzn,[p("div",jzn,[t(K,{theme:"outline",size:"20",fill:"currentColor"})]),F[15]||(F[15]=p("span",{class:"cardTitle"},"访问控制",-1))]),p("div",Mzn,[p("div",Azn,[p("div",Wzn,[F[16]||(F[16]=p("label",{class:"formLabel"},"访问账号",-1)),t(Q,{value:b.value.name,"onUpdate:value":F[2]||(F[2]=Oe=>b.value.name=Oe),placeholder:"请输入访问账号",class:"formInput"},null,8,["value"])]),p("div",Szn,[F[17]||(F[17]=p("label",{class:"formLabel"},"访问密码",-1)),t(Y,{value:b.value.password,"onUpdate:value":F[3]||(F[3]=Oe=>b.value.password=Oe),placeholder:"请输入访问密码",class:"formInput"},null,8,["value"])])])])]),(ie(!0),be(Gt,null,Qn(Object.keys(w),Oe=>(ie(),be("section",{class:"settingCard",key:Oe},[p("div",Dzn,[p("div",Hzn,[p("div",{class:Ae(["cardIcon",v(Oe)])},[Oe==="languageModel"?(ie(),kt(R,{key:0,theme:"outline",size:"20",fill:"currentColor"})):Oe==="imageModel"?(ie(),kt(ee,{key:1,theme:"outline",size:"20",fill:"currentColor"})):(ie(),kt(J,{key:2,theme:"outline",size:"20",fill:"currentColor"}))],2),p("span",Tzn,jt(w[Oe])+"配置",1)]),Oe==="videoModel"?(ie(),kt(le,{key:0,type:"primary",class:"addBtn",onClick:d},{default:De(()=>[t(ne,{theme:"outline",size:"14",fill:"currentColor"}),F[18]||(F[18]=cn(" 新增配置 ",-1))]),_:1})):et("",!0)]),p("div",zzn,[Oe==="videoModel"?(ie(),be("div",Pzn,[n.value.length===0?(ie(),be("div",Ezn,[t(oe,{theme:"outline",size:"48",fill:"#d1d5db"}),F[19]||(F[19]=p("p",null,"暂无配置,点击上方按钮添加",-1))])):et("",!0),(ie(!0),be(Gt,null,Qn(n.value.sort((it,ze)=>it.index-ze.index),it=>(ie(),kt(FTn,{key:it.id,config:it,onEdit:u,onDelete:h},null,8,["config"]))),128))])):(ie(),be("div",Ozn,[p("div",Vzn,[F[20]||(F[20]=p("label",{class:"formLabel"},"模型名称",-1)),t(Q,{value:b.value[Oe].model,"onUpdate:value":it=>b.value[Oe].model=it,placeholder:`请输入${w[Oe]}名称`,class:"formInput"},null,8,["value","onUpdate:value","placeholder"])]),p("div",Bzn,[F[21]||(F[21]=p("label",{class:"formLabel"},"厂商",-1)),t(se,{value:b.value[Oe].manufacturer,"onUpdate:value":it=>b.value[Oe].manufacturer=it,placeholder:"请选择厂商",class:"formSelect",onChange:it=>void 0},{default:De(()=>[(ie(!0),be(Gt,null,Qn(f(Oe),it=>(ie(),kt($,{key:it.value,value:it.value},{default:De(()=>[cn(jt(it.label),1)]),_:2},1032,["value"]))),128))]),_:2},1032,["value","onUpdate:value","onChange"])]),Oe!=="imageModel"||b.value[Oe].manufacturer==="openAi"?(ie(),be("div",Izn,[F[22]||(F[22]=p("label",{class:"formLabel"},"BaseURL",-1)),t(Q,{value:b.value[Oe].baseURL,"onUpdate:value":it=>b.value[Oe].baseURL=it,placeholder:`请输入${w[Oe]}的BaseURL`,class:"formInput"},null,8,["value","onUpdate:value","placeholder"])])):et("",!0),p("div",Nzn,[F[23]||(F[23]=p("label",{class:"formLabel"},"API Key",-1)),t(Y,{value:b.value[Oe].apiKey,"onUpdate:value":it=>b.value[Oe].apiKey=it,placeholder:`请输入${w[Oe]}的API Key`,class:"formInput"},null,8,["value","onUpdate:value","placeholder"])])]))])]))),128)),p("section",Rzn,[p("div",Fzn,[p("div",Zzn,[p("div",Xzn,[t(te,{theme:"outline",size:"20",fill:"currentColor"})]),F[24]||(F[24]=p("span",{class:"cardTitle"},"提示词管理",-1))]),t(le,{type:"primary",class:"addBtn",onClick:F[4]||(F[4]=Oe=>l.value=!0)},{default:De(()=>[t(G,{theme:"outline",size:"14",fill:"currentColor"}),F[25]||(F[25]=cn(" 编辑提示词 ",-1))]),_:1})]),F[26]||(F[26]=p("div",{class:"cardContent"},[p("p",{class:"promptTip"},"管理和自定义AI Agent的提示词,可修改主Agent、子Agent和系统提示词")],-1))]),p("section",Uzn,[p("div",Gzn,[p("div",Yzn,[t(re,{theme:"outline",size:"20",fill:"currentColor"})]),F[27]||(F[27]=p("span",{class:"cardTitle"},"数据管理",-1)),F[28]||(F[28]=p("span",{class:"dangerBadge"},"危险区域",-1))]),p("div",qzn,[F[31]||(F[31]=p("p",{class:"dangerTip"},"以下操作不可逆,请谨慎执行",-1)),p("div",Kzn,[t(le,{danger:"",onClick:B},{default:De(()=>[t(ue,{theme:"outline",size:"14",fill:"currentColor"}),F[29]||(F[29]=cn(" 清空数据库 ",-1))]),_:1}),t(le,{danger:"",type:"primary",onClick:T},{default:De(()=>[t(re,{theme:"outline",size:"14",fill:"currentColor"}),F[30]||(F[30]=cn(" 删除数据库 ",-1))]),_:1})])])]),p("section",Jzn,[p("div",Qzn,[p("div",$zn,[t(ce,{theme:"outline",size:"20",fill:"currentColor"})]),F[32]||(F[32]=p("span",{class:"cardTitle"},"关于",-1))]),p("div",_zn,[p("div",pzn,[F[39]||(F[39]=Ine('

ToonFlow 是一款开源的 AI 驱动漫画/分镜创作工具,帮助创作者快速生成故事分镜和视频内容。

',2)),p("div",ePn,[p("div",{class:"linkItem",onClick:x},[p("div",tPn,[t(he,{theme:"outline",size:"20",fill:"currentColor"})]),F[33]||(F[33]=p("div",{class:"linkContent"},[p("span",{class:"linkTitle"},"GitHub 仓库"),p("span",{class:"linkDesc"},"查看源代码、提交 Issue 或贡献代码")],-1)),t(ke,{theme:"outline",size:"16",fill:"#9ca3af"})]),p("div",{class:"linkItem",onClick:M},[p("div",nPn,[t(ye,{theme:"outline",size:"20",fill:"currentColor"})]),F[34]||(F[34]=p("div",{class:"linkContent"},[p("span",{class:"linkTitle"},"Gitee 仓库"),p("span",{class:"linkDesc"},"国内镜像,查看源代码或贡献代码")],-1)),t(ke,{theme:"outline",size:"16",fill:"#9ca3af"})]),p("div",{class:"linkItem",onClick:W},[p("div",iPn,[t(me,{theme:"outline",size:"20",fill:"currentColor"})]),F[35]||(F[35]=p("div",{class:"linkContent"},[p("span",{class:"linkTitle"},"检查更新 (GitHub)"),p("span",{class:"linkDesc"},"前往 GitHub Releases 查看最新版本")],-1)),t(ke,{theme:"outline",size:"16",fill:"#9ca3af"})]),p("div",{class:"linkItem",onClick:S},[p("div",oPn,[t(me,{theme:"outline",size:"20",fill:"currentColor"})]),F[36]||(F[36]=p("div",{class:"linkContent"},[p("span",{class:"linkTitle"},"检查更新 (Gitee)"),p("span",{class:"linkDesc"},"前往 Gitee Releases 查看最新版本")],-1)),t(ke,{theme:"outline",size:"16",fill:"#9ca3af"})]),p("div",{class:"linkItem",onClick:H},[p("div",lPn,[t(xe,{theme:"outline",size:"20",fill:"currentColor"})]),F[37]||(F[37]=p("div",{class:"linkContent"},[p("span",{class:"linkTitle"},"开源协议"),p("span",{class:"linkDesc"},"本项目基于 AGPL-3.0 协议开源")],-1)),t(ke,{theme:"outline",size:"16",fill:"#9ca3af"})])]),p("div",rPn,[t(Ce,{theme:"outline",size:"16",fill:"#9913FA"}),F[38]||(F[38]=p("span",null,"AGPL-3.0 License",-1))])])])]),p("div",sPn,[t(le,{size:"large",onClick:y},{default:De(()=>[...F[40]||(F[40]=[cn("取消",-1)])]),_:1}),t(le,{type:"primary",size:"large",onClick:z},{default:De(()=>[t(Se,{theme:"outline",size:"16",fill:"currentColor"}),F[41]||(F[41]=cn(" 保存设置 ",-1))]),_:1})])])]),t(bTn,{modelValue:s.value,"onUpdate:modelValue":F[5]||(F[5]=Oe=>s.value=Oe),data:a.value,onSave:c},null,8,["modelValue","data"]),t(fzn,{modelValue:l.value,"onUpdate:modelValue":F[6]||(F[6]=Oe=>l.value=Oe)},null,8,["modelValue"]),t(Ee,{title:"执行SQL",open:i.value,"onUpdate:open":F[8]||(F[8]=Oe=>i.value=Oe),onOk:r,centered:""},{default:De(()=>[t(Te,{value:o.value,"onUpdate:value":F[7]||(F[7]=Oe=>o.value=Oe),placeholder:"请输入SQL语句",autosize:{minRows:2,maxRows:12}},null,8,["value"])]),_:1},8,["open"])],64)}}}),cPn=Xo(aPn,[["__scopeId","data-v-728f6f18"]]),dPn=Object.freeze(Object.defineProperty({__proto__:null,default:cPn},Symbol.toStringTag,{value:"Module"})),uPn={class:"taskDetails"},hPn={class:"content"},kPn={key:0,class:"left"},fPn={class:"imageGrid"},vPn={class:"right"},gPn={class:"reasonList"},mPn=_e({__name:"taskDetails",props:{open:{type:Boolean},row:{}},emits:["update:open"],setup(e,{emit:n}){const i=e,o=n,l=_(i.open);Ve(()=>i.open,s=>{l.value=s}),Ve(l,s=>{o("update:open",s)});function r(){o("update:open",!1)}return(s,a)=>{const c=Ea,d=Zo;return ie(),be("div",uPn,[t(d,{open:l.value,"onUpdate:open":a[0]||(a[0]=u=>l.value=u),title:"任务详情",onOk:r,width:800,okText:"保存"},{default:De(()=>{var u,h;return[p("div",hPn,[e.row&&((u=e.row.imageUrl)!=null&&u.length)?(ie(),be("div",kPn,[p("div",fPn,[(ie(!0),be(Gt,null,Qn(e.row.imageUrl,(g,v)=>(ie(),be("div",{class:"imageDiv",key:v},[t(c,{src:g,fallback:A(I2),width:"220",height:"150",style:{"object-fit":"cover","border-radius":"8px"}},null,8,["src","fallback"])]))),128))])])):et("",!0),p("div",vPn,[a[1]||(a[1]=p("div",{class:"title"},"任务失败原因:",-1)),p("ul",gPn,[(ie(!0),be(Gt,null,Qn((h=e.row)==null?void 0:h.errorReason,(g,v)=>(ie(),be("li",{key:v},jt(g),1))),128))])])])]}),_:1},8,["open"])])}}}),wPn=Xo(mPn,[["__scopeId","data-v-a7cf7a47"]]),LPn={class:"taskList"},bPn={class:"search"},CPn={class:"content"},yPn={class:"pagination",style:{"margin-top":"10px","text-align":"right"}},xPn=_e({__name:"index",setup(e){const n=_({page:1,limit:10,total:11,loading:!1});function i(c,d){}function o(c,d){}const l=_([{id:1,projectName:"项目1",taskName:"任务1",state:"进行中",startTime:"2022-01-01",endTime:"2022-01-31",prompt:"提示词",imageUrl:["https://picx.zhimg.com/v2-d6f44389971daab7e688e5b37046e4e4_720w.jpg?source=172ae18b","https://img.shetu66.com/2023/04/27/1682576769453692.png","https://www.baidu.com/img/flexible/logo/pc/result.png"],errorReason:["任务失败"]},{id:2,projectName:"项目2",taskName:"任务2",state:"已完成",startTime:"2022-02-01",endTime:"2022-02-28",prompt:"提示词",imageUrl:["https://www.baidu.com/img/flexible/logo/pc/result.png"],errorReason:["任务失败2"]}]),r=_(!1),s=_(null),a=c=>{s.value=c,r.value=!0};return(c,d)=>{const u=ql,h=Xm,g=Gr,v=J1e,m=nl,k=nn("vxe-column"),f=nn("vxe-table"),w=Vct;return ie(),be("div",LPn,[d[10]||(d[10]=p("div",{class:"header"},[p("h2",{class:"title"},"任务列表")],-1)),p("div",bPn,[p("div",null,[d[3]||(d[3]=p("span",null,"项目名称:",-1)),t(u,{placeholder:"请输入项目名称",size:"middle"})]),p("div",null,[d[4]||(d[4]=p("span",null,"任务名称:",-1)),t(u,{placeholder:"请输入任务名称",size:"middle"})]),p("div",null,[d[7]||(d[7]=p("span",{style:{width:"50px"}},"状态:",-1)),t(v,{compact:"",size:"middle"},{default:De(()=>[t(g,{style:{width:"150px"}},{default:De(()=>[t(h,{value:"inProgress"},{default:De(()=>[...d[5]||(d[5]=[cn("进行中",-1)])]),_:1}),t(h,{value:"completed"},{default:De(()=>[...d[6]||(d[6]=[cn("已完成",-1)])]),_:1})]),_:1})]),_:1})]),t(m,{type:"primary",style:{"margin-left":"50px"}},{default:De(()=>[...d[8]||(d[8]=[cn("查询",-1)])]),_:1})]),p("div",CPn,[t(f,{ref:"tableRef",data:l.value},{default:De(()=>[t(k,{title:"序号",field:"id",width:"70"}),t(k,{title:"项目名称",field:"projectName",width:"120","show-overflow":"title"}),t(k,{title:"任务名称",field:"taskName","show-overflow":"title"}),t(k,{title:"提示词",field:"prompt","show-overflow":"title"}),t(k,{title:"状态",field:"state",width:"120"}),t(k,{title:"开始时间",field:"startTime",width:"120"}),t(k,{title:"结束时间",field:"endTime",width:"120"}),t(k,{title:"操作",width:"120"},{default:De(({row:L})=>[t(m,{type:"primary",onClick:b=>a(L),size:"small"},{default:De(()=>[...d[9]||(d[9]=[cn("查看",-1)])]),_:1},8,["onClick"])]),_:1})]),_:1},8,["data"]),p("div",yPn,[t(w,{current:n.value.page,"onUpdate:current":d[0]||(d[0]=L=>n.value.page=L),pageSize:n.value.limit,"onUpdate:pageSize":d[1]||(d[1]=L=>n.value.limit=L),"show-size-changer":"",total:n.value.total,onShowSizeChange:i,onChange:o},null,8,["current","pageSize","total"])]),t(wPn,{open:r.value,"onUpdate:open":d[2]||(d[2]=L=>r.value=L),row:s.value},null,8,["open","row"])])])}}}),jPn=Xo(xPn,[["__scopeId","data-v-49103d45"]]),MPn=Object.freeze(Object.defineProperty({__proto__:null,default:jPn},Symbol.toStringTag,{value:"Module"})),APn={class:"loginPage"},WPn={class:"formBox"},SPn={class:"logoBox"},DPn=["src"],HPn={__name:"index",setup(e){_(null);const n=_(!0),i=_({show:!0,loginLoading:!1,user:{username:"",password:"",captcha:"",identity:"商家"},rules:{username:[{required:!0,message:"请输入您的账号"}],password:[{required:!0,message:"请输入密码"}],captcha:[{required:!0,message:"请输入验证码"}]}});_(),_(),un(()=>{l()});const o=r=>{console.log("%c Line:70 🥥 values","background:#6ec1c2",r),i.value.loginLoading=!0;const s={...r};Di.post("/other/login",s).then(({data:a})=>{localStorage.setItem("token",a.token),localStorage.setItem("userId",a.id),kj.push("/project"),Sn.success("登录成功"),i.value.loginLoading=!1}).catch(a=>{i.value.loginLoading=!1,Sn.error(a.message),l()})},l=async()=>{};return(r,s)=>{const a=nn("i-people"),c=ql,d=qf,u=nn("i-lock"),h=lj,g=nl,v=Nc,m=ett;return ie(),be(Gt,null,[s[6]||(s[6]=p("div",{class:"bg"},null,-1)),p("div",APn,[p("div",WPn,[p("div",SPn,[p("img",{src:A(NN),alt:"logo",class:"logo-img"},null,8,DPn),s[3]||(s[3]=p("span",{class:"logo-text"},"Toonflow",-1))]),t(v,{model:i.value.user,rules:i.value.rules,ref:"ruleFormRef",onFinish:o,class:"login-form"},{default:De(()=>[t(d,{name:"username"},{default:De(()=>[t(c,{value:i.value.user.username,"onUpdate:value":s[0]||(s[0]=k=>i.value.user.username=k),placeholder:"请输入账号",autocomplete:"username",size:"large"},{prefix:De(()=>[t(a,{theme:"outline",class:"input-icon"})]),_:1},8,["value"])]),_:1}),t(d,{name:"password"},{default:De(()=>[t(h,{value:i.value.user.password,"onUpdate:value":s[1]||(s[1]=k=>i.value.user.password=k),placeholder:"请输入密码",autocomplete:"current-password",size:"large"},{prefix:De(()=>[t(u,{theme:"outline",class:"input-icon"})]),_:1},8,["value"])]),_:1}),t(d,null,{default:De(()=>[t(g,{class:"loginBtn",type:"primary",size:"large",loading:i.value.loginLoading,"html-type":"submit",block:""},{default:De(()=>[...s[4]||(s[4]=[cn("登录",-1)])]),_:1},8,["loading"])]),_:1})]),_:1},8,["model","rules"]),n.value?(ie(),kt(m,{key:0,class:"default-hint",type:"info",closable:"",onClose:s[2]||(s[2]=k=>n.value=!1)},{message:De(()=>[...s[5]||(s[5]=[p("div",{class:"hint-content"},[p("p",null,[cn(" 默认账号: "),p("code",null,"admin")]),p("p",null,[cn(" 默认密码: "),p("code",null,"admin123")]),p("p",null,"登录后可在设置中修改")],-1)])]),_:1})):et("",!0)])])],64)}}},TPn=Xo(HPn,[["__scopeId","data-v-c7fd1053"]]),zPn=Object.freeze(Object.defineProperty({__proto__:null,default:TPn},Symbol.toStringTag,{value:"Module"})); +