From 1fb782819b29625c2a0fc0cc7631d86816594a43 Mon Sep 17 00:00:00 2001 From: HouYunFei <1844025705@qq.com> Date: Tue, 26 May 2026 13:00:16 +0800 Subject: [PATCH] =?UTF-8?q?feat(canvas):=20=E5=AE=9E=E7=8E=B0=E7=94=BB?= =?UTF-8?q?=E5=B8=83=E9=A1=B9=E7=9B=AE=E5=AF=BC=E5=87=BA=E4=B8=BAZIP?= =?UTF-8?q?=E5=8E=8B=E7=BC=A9=E5=8C=85=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 canvas-export 工具模块,支持将画布项目打包为 ZIP 文件 - 修改导出功能,将原来的 JSON 格式改为 ZIP 压缩包,包含 projects.json 和相关媒体文件 - 添加对 fflate 库的依赖用于 ZIP 文件处理 - 更新画布库页面,支持多选项目批量导出 - 修改导入功能以支持读取新版 ZIP 格式的画布项目 - 新增 zip 处理工具库,封装压缩和解压操作 - 扩展文件存储服务,添加获取和设置 Blob 对象的方法 - 更新 AGENTS.md 文档,添加标准库使用原则 --- AGENTS.md | 1 + docs/pending-test.md | 3 ++ web/bun.lock | 3 ++ web/package.json | 1 + .../canvas/components/canvas-project-card.tsx | 13 +---- web/src/app/(user)/canvas/export-types.ts | 20 +++++++ web/src/app/(user)/canvas/page.tsx | 50 +++++++++++------ .../app/(user)/canvas/utils/canvas-export.ts | 54 +++++++++++++++++++ web/src/lib/zip.ts | 21 ++++++++ web/src/services/file-storage.ts | 11 ++++ web/src/services/image-storage.ts | 11 ++++ 11 files changed, 160 insertions(+), 28 deletions(-) create mode 100644 web/src/app/(user)/canvas/export-types.ts create mode 100644 web/src/app/(user)/canvas/utils/canvas-export.ts create mode 100644 web/src/lib/zip.ts diff --git a/AGENTS.md b/AGENTS.md index ee7e276..242e3ca 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -6,6 +6,7 @@ - 先读现有代码,再动手修改,优先沿用项目已有结构和写法。 - 写代码保持最少行数,能简单实现就不要引入复杂抽象。 +- 标准格式、协议、解析、压缩、加密、日期等通用能力优先使用成熟稳定的库,不要手写底层实现,除非用户明确要求或项目已有实现必须沿用。 - 不要为了“兼容更多场景”写大量分支,只实现当前明确需要的功能。 - 项目尚未上线,不需要兼容旧数据;表结构或字段调整时直接按新设计修改,不写旧字段兼容、数据迁移兜底或删除旧表的清理逻辑,除非用户明确要求。 - 每次写完代码,不需要检查语法,不需要执行构建,用户会自己做。 diff --git a/docs/pending-test.md b/docs/pending-test.md index ba8bf91..18f1096 100644 --- a/docs/pending-test.md +++ b/docs/pending-test.md @@ -1,5 +1,8 @@ # 待测试 +- 画布项目导出改为下载 `.zip` 压缩包,包内包含 `projects.json` 和当前画布引用到的本地图片、视频文件,避免只导出 JSON 时丢失媒体内容。 +- 画布库支持多选后一键导出多个画布项目,导出的压缩包可一次恢复多个项目。 +- 画布项目导入改为读取新版 `.zip` 压缩包,会先按 `projects.json` 中的文件映射恢复图片、视频到本地存储,再插入画布项目,导入成功后仍停留在画布库。 - 未登录状态下,画布右上角不再显示用户头像菜单、用户名称、算力点余额和退出登录入口,改为显示登录入口;快捷键入口仍可直接打开。 - 生图工作台的图片参数区复用画布里的紧凑版图像设置面板,尺寸、质量、生成张数的交互保持一致;工作台仍保留独立的模型选择。 - 视频设置抽成画布和视频创作台共用的紧凑面板,清晰度、尺寸、秒数按固定网格选择并支持手动输入;尺寸选择 `auto` 时请求不传 `size`。 diff --git a/web/bun.lock b/web/bun.lock index d14f1aa..2f470d9 100644 --- a/web/bun.lock +++ b/web/bun.lock @@ -17,6 +17,7 @@ "clsx": "^2.1.1", "copy-to-clipboard": "^4.0.2", "dayjs": "^1.11.20", + "fflate": "^0.8.3", "localforage": "^1.10.0", "lucide-react": "^1.16.0", "motion": "^12.38.0", @@ -802,6 +803,8 @@ "fetch-blob": ["fetch-blob@3.2.0", "https://registry.npmmirror.com/fetch-blob/-/fetch-blob-3.2.0.tgz", { "dependencies": { "node-domexception": "^1.0.0", "web-streams-polyfill": "^3.0.3" } }, "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ=="], + "fflate": ["fflate@0.8.3", "", {}, "sha512-tbZNuJrLwGUp3zshBtdy4W+ORxZuIh8a5ilyIEQDC5rY1f3U20JMry0Ll3WBzU58EZKsEuJFXhb5gwv8CsPvgA=="], + "figures": ["figures@6.1.0", "https://registry.npmmirror.com/figures/-/figures-6.1.0.tgz", { "dependencies": { "is-unicode-supported": "^2.0.0" } }, "sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg=="], "fill-range": ["fill-range@7.1.1", "https://registry.npmmirror.com/fill-range/-/fill-range-7.1.1.tgz", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="], diff --git a/web/package.json b/web/package.json index 6eaca4f..20b1015 100644 --- a/web/package.json +++ b/web/package.json @@ -23,6 +23,7 @@ "clsx": "^2.1.1", "copy-to-clipboard": "^4.0.2", "dayjs": "^1.11.20", + "fflate": "^0.8.3", "localforage": "^1.10.0", "lucide-react": "^1.16.0", "motion": "^12.38.0", diff --git a/web/src/app/(user)/canvas/components/canvas-project-card.tsx b/web/src/app/(user)/canvas/components/canvas-project-card.tsx index e667b5c..b432bde 100644 --- a/web/src/app/(user)/canvas/components/canvas-project-card.tsx +++ b/web/src/app/(user)/canvas/components/canvas-project-card.tsx @@ -6,6 +6,7 @@ import { Button, Input } from "antd"; import { useCanvasStore, type CanvasProject } from "../stores/use-canvas-store"; import { useCanvasUiStore } from "../stores/use-canvas-ui-store"; +import { exportCanvasProjects } from "../utils/canvas-export"; export function CanvasProjectCard({ project }: { project: CanvasProject }) { const router = useRouter(); @@ -65,7 +66,7 @@ export function CanvasProjectCard({ project }: { project: CanvasProject }) { ) : ( <> - + <> + + + ) : null} {projects.length ? (