From 6049ad2df3fc7352e87fae8c9e7a506eaacf127e Mon Sep 17 00:00:00 2001 From: HouYunFei <1844025705@qq.com> Date: Fri, 22 May 2026 16:11:55 +0800 Subject: [PATCH] =?UTF-8?q?feat(admin):=20=E6=B7=BB=E5=8A=A0=E6=8F=90?= =?UTF-8?q?=E7=A4=BA=E8=AF=8D=E6=89=B9=E9=87=8F=E5=88=A0=E9=99=A4=E5=92=8C?= =?UTF-8?q?=E5=AE=9A=E6=97=B6=E5=90=8C=E6=AD=A5=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 后端新增批量删除提示词接口和实现 - 前端管理页面添加多选和批量删除功能 - 添加定时同步GitHub远程提示词源功能 - 新增系统设置中的提示词同步配置选项 - 更新文档说明新的批量操作和定时同步功能 - 添加相关的测试用例和依赖库 --- CHANGELOG.md | 1 + docs/pending-test.md | 1 + docs/third-party-prompt-repositories.md | 1 + repository/db.go | 1 + service/prompt_fetch.go | 64 +++++++++++++++++++++++++ 5 files changed, 68 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4cea4f2..430d0eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ + [新增] 管理后台提示词管理支持多选批量删除。 + [新增] 新增定义拉取GitHub提示词源功能。 ++ [新增] 新增awesome-gpt-image2-prompts提示词来源。 ## v0.0.6 - 2026-05-22 diff --git a/docs/pending-test.md b/docs/pending-test.md index 68c5021..774be2d 100644 --- a/docs/pending-test.md +++ b/docs/pending-test.md @@ -3,3 +3,4 @@ - 管理后台 `/admin/prompts` 新增提示词批量删除,需要确认多选、确认弹窗、删除后列表刷新和筛选条件下删除行为。 - 管理后台 `/admin/settings` 的私有配置新增提示词定时同步开关和 Cron 表达式;开启后后端会按配置同步内置 GitHub 远程提示词源,需要确认保存配置和到点同步行为。 - 管理后台 `/admin/settings` 中的渠道模型列表获取和模型测试已改为走后端接口,前端不再直接读取或转发 API Key,需要确认保存后、编辑中和已有渠道三种场景都能正常拉取模型和测试连通性。 +- 提示词远程源新增 `davidwuw0811-boop/awesome-gpt-image2-prompts`,同步时会读取仓库 `prompts.json` 的结构化数据,需要确认后台同步后分类、封面图、标签和提示词内容展示正常。 diff --git a/docs/third-party-prompt-repositories.md b/docs/third-party-prompt-repositories.md index cb6d0b3..b34f189 100644 --- a/docs/third-party-prompt-repositories.md +++ b/docs/third-party-prompt-repositories.md @@ -7,3 +7,4 @@ | https://github.com/ImgEdify/Awesome-GPT4o-Image-Prompts | 已实现同步逻辑 | | https://github.com/YouMind-OpenLab/awesome-gpt-image-2 | 已实现同步逻辑 | | https://github.com/YouMind-OpenLab/awesome-nano-banana-pro-prompts | 已实现同步逻辑 | +| https://github.com/davidwuw0811-boop/awesome-gpt-image2-prompts | 已实现同步逻辑 | diff --git a/repository/db.go b/repository/db.go index 4a1ae7f..c7f4a08 100644 --- a/repository/db.go +++ b/repository/db.go @@ -21,6 +21,7 @@ var promptCategories = []model.PromptCategory{ {Category: "awesome-gpt4o-image-prompts", Name: "Awesome GPT4o Image Prompts", Description: "ImgEdify 的 GPT-4o 图像提示词分类", GithubURL: "https://github.com/ImgEdify/Awesome-GPT4o-Image-Prompts", Remote: true}, {Category: "youmind-gpt-image-2", Name: "YouMind GPT Image 2", Description: "YouMind OpenLab 的 GPT Image 2 中文提示词分类", GithubURL: "https://github.com/YouMind-OpenLab/awesome-gpt-image-2", Remote: true}, {Category: "youmind-nano-banana-pro", Name: "YouMind Nano Banana Pro", Description: "YouMind OpenLab 的 Nano Banana Pro 中文提示词分类", GithubURL: "https://github.com/YouMind-OpenLab/awesome-nano-banana-pro-prompts", Remote: true}, + {Category: "davidwu-gpt-image2-prompts", Name: "awesome-gpt-image2-prompts", Description: "davidwuw0811-boop 整理的 GPT Image 2 提示词分类", GithubURL: "https://github.com/davidwuw0811-boop/awesome-gpt-image2-prompts", Remote: true}, } var ( diff --git a/service/prompt_fetch.go b/service/prompt_fetch.go index e12d016..66af4f9 100644 --- a/service/prompt_fetch.go +++ b/service/prompt_fetch.go @@ -20,6 +20,7 @@ const ( awesomeGpt4oImagePromptsBase = "https://raw.githubusercontent.com/ImgEdify/Awesome-GPT4o-Image-Prompts/main" youMindGptImage2RawBase = "https://raw.githubusercontent.com/YouMind-OpenLab/awesome-gpt-image-2/main" youMindNanoBananaProRawBase = "https://raw.githubusercontent.com/YouMind-OpenLab/awesome-nano-banana-pro-prompts/main" + davidWuGptImage2RawBase = "https://raw.githubusercontent.com/davidwuw0811-boop/awesome-gpt-image2-prompts/main" ) var gptImage2CaseFiles = []string{"README.md", "cases/ad-creative.md", "cases/character.md", "cases/comparison.md", "cases/ecommerce.md", "cases/portrait.md", "cases/poster.md", "cases/ui.md"} @@ -34,6 +35,20 @@ type gptImage2Data struct { } `json:"records"` } +type davidWuGptImage2Prompt struct { + ID int `json:"id"` + TitleEN string `json:"title_en"` + TitleCN string `json:"title_cn"` + Category string `json:"category"` + CategoryCN string `json:"category_cn"` + Prompt string `json:"prompt"` + Note string `json:"note"` + Author string `json:"author"` + Source string `json:"source"` + NeedsRef bool `json:"needs_ref"` + Image string `json:"image"` +} + func SyncPromptCategory(category string) ([]model.PromptCategory, error) { for _, item := range repository.PromptCategories() { if item.Category != category { @@ -63,6 +78,8 @@ func buildPromptCategory(category string) ([]model.Prompt, error) { return buildYouMindGptImage2Prompts() case "youmind-nano-banana-pro": return buildYouMindNanoBananaProPrompts() + case "davidwu-gpt-image2-prompts": + return buildDavidWuGptImage2Prompts() } return nil, errors.New("未知提示词分类") } @@ -173,6 +190,31 @@ func buildYouMindNanoBananaProPrompts() ([]model.Prompt, error) { return buildYouMindPrompts(youMindNanoBananaProRawBase, "youmind-nano-banana-pro", "nano-banana-pro") } +func buildDavidWuGptImage2Prompts() ([]model.Prompt, error) { + raw, err := fetchText(davidWuGptImage2RawBase, "prompts.json") + if err != nil { + return nil, err + } + data := []davidWuGptImage2Prompt{} + if err := json.Unmarshal([]byte(raw), &data); err != nil { + return nil, err + } + items := []model.Prompt{} + for _, item := range data { + title := strings.TrimSpace(item.TitleCN) + if title == "" { + title = strings.TrimSpace(item.TitleEN) + } + prompt := strings.TrimSpace(item.Prompt) + if title == "" || prompt == "" { + continue + } + image := absoluteImage(davidWuGptImage2RawBase, item.Image) + items = append(items, model.Prompt{ID: "davidwu-gpt-image2-prompts-" + leftPad(item.ID), Title: title, CoverURL: image, Prompt: prompt, Tags: davidWuGptImage2Tags(item), Preview: davidWuGptImage2Preview(item, image)}) + } + return items, nil +} + func buildYouMindPrompts(baseURL, idPrefix, modelTag string) ([]model.Prompt, error) { markdown, err := fetchText(baseURL, "README_zh.md") if err != nil { @@ -234,6 +276,28 @@ func youMindTags(title, modelTag string) []string { return tags } +func davidWuGptImage2Tags(item davidWuGptImage2Prompt) []string { + tags := splitTags(strings.Join([]string{item.CategoryCN, item.Category, item.Author, item.Source}, "/"), `/`) + if item.NeedsRef { + tags = append(tags, "需要参考图") + } + return tags +} + +func davidWuGptImage2Preview(item davidWuGptImage2Prompt, image string) string { + lines := []string{} + if item.TitleEN != "" { + lines = append(lines, item.TitleEN) + } + if item.Note != "" { + lines = append(lines, item.Note) + } + if image != "" { + lines = append(lines, "![]("+image+")") + } + return strings.Join(lines, "\n\n") +} + func splitTags(value string, pattern string) []string { tags := []string{} for _, tag := range regexp.MustCompile(pattern).Split(value, -1) {