Skip to content

增加了AI生成的素材库#178

Open
kevinzyf83 wants to merge 7 commits intoAnionex:mainfrom
kevinzyf83:main
Open

增加了AI生成的素材库#178
kevinzyf83 wants to merge 7 commits intoAnionex:mainfrom
kevinzyf83:main

Conversation

@kevinzyf83
Copy link

@kevinzyf83 kevinzyf83 commented Jan 20, 2026

1. 主要功能 (Features)

素材库(Material Gallery)为用户提供了一个集中的图片资源管理中心,支持以下核心能力:

  • 可视化素材管理 :采用自适应网格布局展示所有图片素材,支持悬停查看详情和大图预览。
  • 多维度筛选 :支持按项目维度筛选素材(“所有素材”、“未关联项目(全局)”或“特定项目”)。
  • 便捷上传 :支持直接上传本地图片(JPG, PNG, WEBP, SVG 等),并自动关联当前选中的项目上下文。
  • AI 创意生成 :集成 MaterialGeneratorModal ,允许用户通过 AI 生成定制化素材。
  • 资产复用与操作 :
    • 设为模板 :一键将优质素材转存为“用户模板”,方便在生成 PPT 时复用其风格。
    • 下载 :支持查看原图并下载到本地。
    • 删除 :支持对不再需要的素材进行删除管理。

2. Bug 修复 (Bug Fixes)

在 frontend/src/pages/MaterialGallery.tsx 文件中修复了大量导致编译失败的语法错误(推测由代码复制或输入法误操作引起):

  • 全角符号修正 :将所有的全角逗号 , 、句号 。 替换为标准的半角符号 , 和 . 。
  • 关键字修正 :
    • 输入 -> type 或 import
    • 文件 -> files
    • 项目 -> projects
    • 下载 -> Download (Lucide 图标组件名)
  • 导入语法修复 :修正了 import ... from ... 语句中的格式错误。

3. 新增文件 (New Files)

  • frontend/src/pages/MaterialGallery.tsx : 素材库的核心页面组件,包含完整的 UI 渲染和业务逻辑。

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @kevinzyf83, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

此拉取请求的核心目标是引入一个功能丰富的AI生成素材库,旨在为用户提供一个集中、高效的图片素材管理平台。通过整合AI绘图、便捷的上传与筛选、以及一键模板化等功能,极大地简化了素材的获取和复用流程,从而提升了整体的用户体验和创作效率。这一改动将原先分散的素材生成能力统一管理,为未来的功能扩展奠定了基础。

Highlights

  • 新增素材库页面: 引入了一个全新的 /materials 路由,用于展示和管理所有图片素材。这个页面集成了素材的上传、AI生成、筛选、预览、下载和删除功能。
  • 集中管理素材: 用户现在可以集中浏览所有历史素材,并支持按项目筛选或查看全局素材,极大地提升了素材管理的效率和便捷性。
  • 内置AI生成功能: 素材库内置了AI绘图功能,用户只需输入提示词即可生成高质量的图片素材,并将原先分散的素材生成功能统一到此页面。
  • 一键设为风格模板: 新增了将喜欢的素材图片一键“设为风格模板”的功能,方便用户快速复用其配色和风格,提升创作效率。
  • 路由配置更新: 在 frontend/src/App.tsx 中添加了 /materials 路由,将其映射到新的 MaterialGallery 组件。
  • Home页面调整: 对 frontend/src/pages/Home.tsx 文件进行了局部调整,包括将部分英文逗号替换为中文逗号,以及将 type 关键字替换为 输入,并对 Home 组件的导出名称进行了本地化,这些改动可能与国际化或代码风格统一有关。
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

本次代码审查主要关注新增的AI素材库功能。整体来看,PR通过增加/materials路由和MaterialGallery组件,实现了素材的集中管理、AI生成和上传功能,这与PR描述的功能目标一致。新组件MaterialGallery的业务逻辑设计合理,涵盖了加载、筛选、上传、删除、预览和保存为模板等核心功能。

然而,本次提交在frontend/src/pages/Home.tsx和新增的frontend/src/pages/MaterialGallery.tsx两个文件中存在大量且系统性的语法错误。这些错误包括但不限于使用全角标点符号、将TypeScript/JavaScript关键字(如type)替换为中文字符、以及错误的对象属性名。这些问题可能是由于不正确的批量替换操作导致的,它们会造成应用编译失败,属于必须立即修复的严重问题。在修复这些语法问题后,代码的逻辑部分才能正常工作。

Comment on lines 1 to 34
import React { useState useEffect useRef useMemo } from 'react';
import { useNavigate } from 'react-router-dom';
import { Sparkles, FileText, FileEdit, ImagePlus, Paperclip, Palette, Lightbulb, Search, Settings } from 'lucide-react';
import { Button, Textarea, Card, useToast, MaterialGeneratorModal, ReferenceFileList, ReferenceFileSelector, FilePreviewModal, ImagePreviewList } from '@/components/shared';
import { TemplateSelector, getTemplateFile } from '@/components/shared/TemplateSelector';
import { listUserTemplates, type UserTemplate, uploadReferenceFile, type ReferenceFile, associateFileToProject, triggerFileParse, uploadMaterial, associateMaterialsToProject, listProjects } from '@/api/endpoints';
import { Sparkles FileText FileEdit ImagePlus Paperclip Palette Lightbulb, 搜索, 设置, Image as ImageIcon } from 'lucide-react';
import { Button Textarea Card useToast MaterialGeneratorModal ReferenceFileList ReferenceFileSelector FilePreviewModal ImagePreviewList } from '@/components/shared';
import { TemplateSelector getTemplateFile } from '@/components/shared/TemplateSelector';
import { listUserTemplates, 输入 UserTemplate uploadReferenceFile, 输入 ReferenceFile associateFileToProject triggerFileParse uploadMaterial associateMaterialsToProject listProjects } from '@/api/endpoints';
import { useProjectStore } from '@/store/useProjectStore';
import { PRESET_STYLES } from '@/config/presetStyles';

type CreationType = 'idea' | 'outline' | 'description';
输入 CreationType = 'idea' | 'outline' | 'description';

export const Home: React.FC = () => {
export const 主页: React.FC = () => {
const navigate = useNavigate();
const { initializeProject, isGlobalLoading } = useProjectStore();
const { show, ToastContainer } = useToast();
const { initializeProject isGlobalLoading } = useProjectStore();
const { show ToastContainer } = useToast();

const [activeTab, setActiveTab] = useState<CreationType>('idea');
const [content, setContent] = useState('');
const [selectedTemplate, setSelectedTemplate] = useState<File | null>(null);
const [selectedTemplateId, setSelectedTemplateId] = useState<string | null>(null);
const [selectedPresetTemplateId, setSelectedPresetTemplateId] = useState<string | null>(null);
const [isMaterialModalOpen, setIsMaterialModalOpen] = useState(false);
const [currentProjectId, setCurrentProjectId] = useState<string | null>(null);
const [userTemplates, setUserTemplates] = useState<UserTemplate[]>([]);
const [referenceFiles, setReferenceFiles] = useState<ReferenceFile[]>([]);
const [isUploadingFile, setIsUploadingFile] = useState(false);
const [isFileSelectorOpen, setIsFileSelectorOpen] = useState(false);
const [previewFileId, setPreviewFileId] = useState<string | null>(null);
const [useTemplateStyle, setUseTemplateStyle] = useState(false);
const [templateStyle, setTemplateStyle] = useState('');
const [hoveredPresetId, setHoveredPresetId] = useState<string | null>(null);
const [activeTab setActiveTab] = useState<CreationType>('idea');
const [content setContent] = useState('');
const [selectedTemplate setSelectedTemplate] = useState<File | null>(null);
const [selectedTemplateId setSelectedTemplateId] = useState<string | null>(null);
const [selectedPresetTemplateId setSelectedPresetTemplateId] = useState<string | null>(null);
const [isMaterialModalOpen setIsMaterialModalOpen] = useState(false);
const [currentProjectId setCurrentProjectId] = useState<string | null>(null);
const [userTemplates setUserTemplates] = useState<UserTemplate[]>([]);
const [referenceFiles setReferenceFiles] = useState<ReferenceFile[]>([]);
const [isUploadingFile setIsUploadingFile] = useState(false);
const [isFileSelectorOpen setIsFileSelectorOpen] = useState(false);
const [previewFileId setPreviewFileId] = useState<string | null>(null);
const [useTemplateStyle setUseTemplateStyle] = useState(false);
const [templateStyle setTemplateStyle] = useState('');
const [hoveredPresetId setHoveredPresetId] = useState<string | null>(null);
const fileInputRef = useRef<HTMLInputElement>(null);
const textareaRef = useRef<HTMLTextAreaElement>(null);

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

文件中存在大量语法错误,可能是由于不正确的查找和替换操作导致的。这些错误将导致编译失败,必须修正。主要问题包括:

  • 全角标点:在importconst解构赋值和useState等语句中,大量使用了全角逗号,而JavaScript/TypeScript语法要求使用半角逗号,
  • 错误关键字import语句中的type关键字被错误地替换为输入type类型定义关键字也被替换为输入
  • 无效的导入:从lucide-react库中导入的图标名称SearchSettings被替换为中文字符搜索设置,这是无效的。

请检查整个文件并修复所有类似的语法问题。以下代码建议修复了文件头部的这些问题。

import React, { useState, useEffect, useRef, useMemo } from 'react';
import { useNavigate } from 'react-router-dom';
import { Sparkles, FileText, FileEdit, ImagePlus, Paperclip, Palette, Lightbulb, Search, Settings, Image as ImageIcon } from 'lucide-react';
import { Button, Textarea, Card, useToast, MaterialGeneratorModal, ReferenceFileList, ReferenceFileSelector, FilePreviewModal, ImagePreviewList } from '@/components/shared';
import { TemplateSelector, getTemplateFile } from '@/components/shared/TemplateSelector';
import { listUserTemplates, type UserTemplate, uploadReferenceFile, type ReferenceFile, associateFileToProject, triggerFileParse, uploadMaterial, associateMaterialsToProject, listProjects } from '@/api/endpoints';
import { useProjectStore } from '@/store/useProjectStore';
import { PRESET_STYLES } from '@/config/presetStyles';

type CreationType = 'idea' | 'outline' | 'description';

export const 主页: React.FC = () => {
  const navigate = useNavigate();
  const { initializeProject, isGlobalLoading } = useProjectStore();
  const { show, ToastContainer } = useToast();
  
  const [activeTab, setActiveTab] = useState<CreationType>('idea');
  const [content, setContent] = useState('');
  const [selectedTemplate, setSelectedTemplate] = useState<File | null>(null);
  const [selectedTemplateId, setSelectedTemplateId] = useState<string | null>(null);
  const [selectedPresetTemplateId, setSelectedPresetTemplateId] = useState<string | null>(null);
  const [isMaterialModalOpen, setIsMaterialModalOpen] = useState(false);
  const [currentProjectId, setCurrentProjectId] = useState<string | null>(null);
  const [userTemplates, setUserTemplates] = useState<UserTemplate[]>([]);
  const [referenceFiles, setReferenceFiles] = useState<ReferenceFile[]>([]);
  const [isUploadingFile, setIsUploadingFile] = useState(false);
  const [isFileSelectorOpen, setIsFileSelectorOpen] = useState(false);
  const [previewFileId, setPreviewFileId] = useState<string | null>(null);
  const [useTemplateStyle, setUseTemplateStyle] = useState(false);
  const [templateStyle, setTemplateStyle] = useState('');
  const [hoveredPresetId, setHoveredPresetId] = useState<string | null>(null);
  const fileInputRef = useRef<HTMLInputElement>(null);
  const textareaRef = useRef<HTMLTextAreaElement>(null);

Comment on lines 1 to 23
import React, { useState, useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import { RefreshCw, Upload, Sparkles, X, 下载, ArrowLeft, Image as ImageIcon, Trash2, ExternalLink, Palette } from 'lucide-react';
import { Button, useToast, Modal, MaterialGeneratorModal } from '@/components/shared';
import { listMaterials, uploadMaterial, listProjects, deleteMaterial, uploadUserTemplate, 输入 Material } from '@/api/endpoints';
import { materialUrlToFile } from '@/components/shared/MaterialSelector';
import 输入 { Project } from '@/types';
import { getImageUrl } from '@/api/client';

export const MaterialGallery: React。FC = () => {
const navigate = useNavigate();
const { show, ToastContainer } = useToast();

// 状态管理
const [materials, setMaterials] = useState<Material[]>([]);
const [isLoading, setIsLoading] = useState(false);
const [isUploading, setIsUploading] = useState(false);
const [filterProjectId, setFilterProjectId] = useState<string>('all');
const [项目, setProjects] = useState<Project[]>([]);
const [isGeneratorOpen, setIsGeneratorOpen] = useState(false);
const [previewMaterial, setPreviewMaterial] = useState<Material | null>(null);
const [deletingId, setDeletingId] = useState<string | null>(null);
const [savingTemplateId, setSavingTemplateId] = useState<string | null>(null);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

这个新文件中存在大量系统性的语法错误,这会导致代码完全无法运行。请在整个文件中进行修正:

  • 标点符号:很多地方使用了全角字符(如 )代替了半角字符(,.)。
  • 关键字import type 被错误地写成了 import 输入输入
  • 变量和属性
    • const [项目, setProjects] 这样的状态定义不一致,应为 const [projects, setProjects]
    • response.data.项目 应为 response.data.projects 以匹配API返回。
    • e.target.files 被写成了 e.target.文件
    • file.type 被写成了 file.输入
  • JSX 属性<input type="file"> 被写成了 <input 输入="file">
  • 模块导入:从 lucide-react 导入的 Download 被写成了 下载

这些问题遍布整个文件,需要全部修复才能使组件正常工作。下面提供文件开头部分的修正建议,请参照此模式修改整个文件。

import React, { useState, useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import { RefreshCw, Upload, Sparkles, X, Download, ArrowLeft, Image as ImageIcon, Trash2, ExternalLink, Palette } from 'lucide-react';
import { Button, useToast, Modal, MaterialGeneratorModal } from '@/components/shared';
import { listMaterials, uploadMaterial, listProjects, deleteMaterial, uploadUserTemplate, type Material } from '@/api/endpoints';
import { materialUrlToFile } from '@/components/shared/MaterialSelector';
import type { Project } from '@/types';
import { getImageUrl } from '@/api/client';

export const MaterialGallery: React.FC = () => {
  const navigate = useNavigate();
  const { show, ToastContainer } = useToast();
  
  // 状态管理
  const [materials, setMaterials] = useState<Material[]>([]);
  const [isLoading, setIsLoading] = useState(false);
  const [isUploading, setIsUploading] = useState(false);
  const [filterProjectId, setFilterProjectId] = useState<string>('all');
  const [projects, setProjects] = useState<Project[]>([]);
  const [isGeneratorOpen, setIsGeneratorOpen] = useState(false);
  const [previewMaterial, setPreviewMaterial] = useState<Material | null>(null);
  const [deletingId, setDeletingId] = useState<string | null>(null);
  const [savingTemplateId, setSavingTemplateId] = useState<string | null>(null);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant