diff --git a/paicoding-api/src/main/java/com/github/paicoding/forum/api/model/vo/article/AiIllustrationGenerateReq.java b/paicoding-api/src/main/java/com/github/paicoding/forum/api/model/vo/article/AiIllustrationGenerateReq.java new file mode 100644 index 00000000..a0cc1363 --- /dev/null +++ b/paicoding-api/src/main/java/com/github/paicoding/forum/api/model/vo/article/AiIllustrationGenerateReq.java @@ -0,0 +1,19 @@ +package com.github.paicoding.forum.api.model.vo.article; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +@ApiModel("AI生成文章配图请求") +public class AiIllustrationGenerateReq { + + @ApiModelProperty(value = "文章标题", required = true) + private String title; + + @ApiModelProperty(value = "文章正文内容", required = true) + private String content; + + @ApiModelProperty(value = "生成配图数量,默认4张,范围1-8") + private Integer count; +} \ No newline at end of file diff --git a/paicoding-api/src/main/java/com/github/paicoding/forum/api/model/vo/article/AiIllustrationGenerateRes.java b/paicoding-api/src/main/java/com/github/paicoding/forum/api/model/vo/article/AiIllustrationGenerateRes.java new file mode 100644 index 00000000..78177dd9 --- /dev/null +++ b/paicoding-api/src/main/java/com/github/paicoding/forum/api/model/vo/article/AiIllustrationGenerateRes.java @@ -0,0 +1,35 @@ +package com.github.paicoding.forum.api.model.vo.article; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.util.List; + +@Data +@ApiModel("AI生成文章配图响应") +public class AiIllustrationGenerateRes { + + @ApiModelProperty("生成的配图列表") + private List illustrations; + + @Data + @ApiModel("配图项") + public static class IllustrationItem { + + @ApiModelProperty("配图序号") + private Integer index; + + @ApiModelProperty("配图主题") + private String theme; + + @ApiModelProperty("核心意思") + private String coreIdea; + + @ApiModelProperty("建议放置位置(段落序号)") + private Integer placement; + + @ApiModelProperty("配图URL") + private String imageUrl; + } +} \ No newline at end of file diff --git a/paicoding-service/src/main/java/com/github/paicoding/forum/service/article/service/AiIllustrationService.java b/paicoding-service/src/main/java/com/github/paicoding/forum/service/article/service/AiIllustrationService.java new file mode 100644 index 00000000..504d29a2 --- /dev/null +++ b/paicoding-service/src/main/java/com/github/paicoding/forum/service/article/service/AiIllustrationService.java @@ -0,0 +1,9 @@ +package com.github.paicoding.forum.service.article.service; + +import com.github.paicoding.forum.api.model.vo.article.AiIllustrationGenerateReq; +import com.github.paicoding.forum.api.model.vo.article.AiIllustrationGenerateRes; + +public interface AiIllustrationService { + + AiIllustrationGenerateRes generateIllustrations(AiIllustrationGenerateReq req); +} \ No newline at end of file diff --git a/paicoding-service/src/main/java/com/github/paicoding/forum/service/article/service/impl/AiIllustrationServiceImpl.java b/paicoding-service/src/main/java/com/github/paicoding/forum/service/article/service/impl/AiIllustrationServiceImpl.java new file mode 100644 index 00000000..8e2e5533 --- /dev/null +++ b/paicoding-service/src/main/java/com/github/paicoding/forum/service/article/service/impl/AiIllustrationServiceImpl.java @@ -0,0 +1,288 @@ +package com.github.paicoding.forum.service.article.service.impl; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.github.paicoding.forum.api.model.exception.ExceptionUtil; +import com.github.paicoding.forum.api.model.exception.ForumException; +import com.github.paicoding.forum.api.model.vo.article.AiIllustrationGenerateReq; +import com.github.paicoding.forum.api.model.vo.article.AiIllustrationGenerateRes; +import com.github.paicoding.forum.api.model.vo.chat.ChatItemVo; +import com.github.paicoding.forum.api.model.vo.constants.StatusEnum; +import com.github.paicoding.forum.core.async.AsyncUtil; +import com.github.paicoding.forum.service.article.service.AiIllustrationService; +import com.github.paicoding.forum.service.chatai.service.impl.zhipu.ZhipuIntegration; +import com.github.paicoding.forum.service.image.service.ImageService; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +@Slf4j +@Service +public class AiIllustrationServiceImpl implements AiIllustrationService { + + private static final long PROVIDER_TIMEOUT_SECONDS = 300L; + + @Autowired + private ZhipuIntegration zhipuIntegration; + + @Autowired + private ImageService imageService; + + private static final String ANALYSIS_PROMPT_TEMPLATE = + "你是一个专业的中文文章配图设计师。请分析以下文章,提炼出适合配图的关键节点。\n\n" + + "文章标题:%s\n" + + "文章正文:%s\n\n" + + "要求:\n" + + "1. 分析文章的核心观点和认知转折\n" + + "2. 选择4-%d个最适合用图解释的位置(优先选择核心判断、流程、结构、前后对比、概念隐喻)\n" + + "3. 每个配图需要包含:\n" + + " - theme:配图主题(简短概括)\n" + + " - coreIdea:核心意思(这张图要表达什么)\n" + + " - placement:建议放置位置(段落序号,从1开始)\n" + + " - structureType:结构类型(Workflow/系统局部/前后对比/角色状态/概念隐喻/方法分层/地图路线/小漫画分镜)\n" + + " - composition:画面描述(小黑在哪里、正在做什么、主要物件是什么)\n" + + " - elements:建议元素(用/分隔,不超过4个)\n" + + " - labels:建议中文标注词(用/分隔,不超过5个)\n" + + "4. 不要平均配图,优先选择认知锚点\n" + + "5. 返回格式必须是JSON数组,不要添加任何额外文字\n\n" + + "示例格式:\n" + + "[{\"theme\":\"主题1\",\"coreIdea\":\"核心意思1\",\"placement\":1,\"structureType\":\"概念隐喻\",\"composition\":\"小黑在...\",\"elements\":\"元素1/元素2/元素3\",\"labels\":\"标注1/标注2\"}]"; + + private static final String IMAGE_PROMPT_TEMPLATE = + "Generate one standalone 16:9 horizontal Chinese article illustration.\n\n" + + "Visual DNA:\n" + + "Pure white background. Minimalist black hand-drawn line art. Slightly wobbly pen lines. Lots of empty white space. Sparse red/orange/blue handwritten Chinese annotations. Clean absurd product-sketch feeling. No gradients, no shadows, no paper texture, no complex background, no commercial vector style, no PPT infographic look, no cute mascot poster, no children's illustration, no realistic UI.\n\n" + + "Recurring IP character required:\n" + + "小黑, a small solid-black absurd creature with white dot eyes, tiny thin legs, blank serious expression, slightly uneven hand-drawn body shape. 小黑 must perform the core conceptual action, not decorate the scene. Make 小黑 serious, deadpan, and slightly bizarre, not cute.\n\n" + + "Theme:\n" + + "%s\n\n" + + "Structure type:\n" + + "%s\n\n" + + "Core idea:\n" + + "%s\n\n" + + "Composition:\n" + + "%s\n\n" + + "Suggested elements:\n" + + "%s\n\n" + + "Chinese handwritten labels:\n" + + "%s\n\n" + + "Color use:\n" + + "Black for main line art and 小黑. Orange for main flow/path/arrows. Red only for key warnings/problems/results. Blue only for secondary notes or feedback/system state.\n\n" + + "Constraints:\n" + + "One image explains only one core structure. Keep the main subject around 40%%-60%% of the canvas. Preserve at least 35%% blank white space. Use at most 5-8 short handwritten Chinese labels. Do not write a title in the top-left corner. Do not write the structure type on the image. Do not make it a formal diagram, course slide, or dense explainer. Do not copy prior examples or reuse known case compositions unless explicitly requested; invent a fresh visual metaphor for this specific article. It should be clear but not instructional, interesting but not childish, strange but clean."; + + @Override + public AiIllustrationGenerateRes generateIllustrations(AiIllustrationGenerateReq req) { + if (StringUtils.isBlank(req.getTitle()) || StringUtils.isBlank(req.getContent())) { + throw new IllegalArgumentException("文章标题和正文内容不能为空"); + } + + int count = req.getCount() != null ? req.getCount() : 4; + if (count < 1 || count > 8) { + throw new IllegalArgumentException("配图数量必须在1-8之间"); + } + + String content = req.getContent(); + if (content.length() > 3000) { + content = content.substring(0, 3000); + } + + List plan = analyzeArticle(req.getTitle(), content, count); + + List result = new ArrayList<>(); + int index = 1; + for (AiIllustrationGenerateRes.IllustrationItem item : plan) { + try { + String imageUrl = generateImage(item); + item.setImageUrl(imageUrl); + item.setIndex(index++); + result.add(item); + log.info("配图生成成功: {}", item.getTheme()); + } catch (Exception e) { + log.warn("配图生成失败: {}, 原因: {}", item.getTheme(), e.getMessage()); + } + } + + AiIllustrationGenerateRes res = new AiIllustrationGenerateRes(); + res.setIllustrations(result); + return res; + } + + private List analyzeArticle(String title, String content, int count) { + String prompt = String.format(ANALYSIS_PROMPT_TEMPLATE, title, content, count); + + log.info("开始分析文章,生成配图策略"); + ChatItemVo zhipuItem = new ChatItemVo().initQuestion(prompt); + callProviderWithTimeout("智谱AI", () -> zhipuIntegration.directReturn(0L, zhipuItem)); + String answer = zhipuItem.getAnswer(); + + if (StringUtils.isBlank(answer)) { + throw illustrationException("智谱AI返回内容为空"); + } + + try { + return parseAnalysisResponse(answer); + } catch (Exception e) { + log.error("解析智谱AI响应失败", e); + throw illustrationException("解析智谱AI响应失败: " + e.getMessage()); + } + } + + private String generateImage(AiIllustrationGenerateRes.IllustrationItem item) { + String prompt = String.format(IMAGE_PROMPT_TEMPLATE, + item.getTheme(), + item.getStructureType(), + item.getCoreIdea(), + item.getComposition(), + item.getElements(), + item.getLabels()); + + log.info("开始生成配图: {}", item.getTheme()); + + ChatItemVo zhipuItem = new ChatItemVo().initQuestion(prompt); + callProviderWithTimeout("智谱AI", () -> zhipuIntegration.directReturn(0L, zhipuItem)); + String answer = zhipuItem.getAnswer(); + + if (StringUtils.isBlank(answer)) { + throw illustrationException("智谱AI图片生成返回为空"); + } + + String imageUrl = extractImageUrl(answer); + if (StringUtils.isBlank(imageUrl)) { + throw illustrationException("未从响应中提取到图片URL"); + } + + return imageService.saveImg(imageUrl); + } + + private List parseAnalysisResponse(String answer) { + log.info("智谱AI分析响应: {}", answer); + + String cleanedAnswer = answer.trim(); + if (cleanedAnswer.startsWith("\"") && cleanedAnswer.endsWith("\"")) { + cleanedAnswer = JSON.parseObject(cleanedAnswer, String.class); + } + + cleanedAnswer = cleanedAnswer.replaceAll("\\n", "") + .replaceAll("\\r", "") + .trim(); + + if (!cleanedAnswer.startsWith("[")) { + int arrayStart = cleanedAnswer.indexOf("["); + if (arrayStart >= 0) { + cleanedAnswer = cleanedAnswer.substring(arrayStart); + } + } + + JSONArray array = JSON.parseArray(cleanedAnswer); + if (array == null || array.isEmpty()) { + throw illustrationException("智谱AI返回的配图策略为空"); + } + + List items = new ArrayList<>(); + for (int i = 0; i < array.size(); i++) { + JSONObject obj = array.getJSONObject(i); + AiIllustrationGenerateRes.IllustrationItem item = new AiIllustrationGenerateRes.IllustrationItem(); + item.setTheme(obj.getString("theme")); + item.setCoreIdea(obj.getString("coreIdea")); + item.setPlacement(obj.getInteger("placement")); + item.setStructureType(obj.getString("structureType")); + item.setComposition(obj.getString("composition")); + item.setElements(obj.getString("elements")); + item.setLabels(obj.getString("labels")); + items.add(item); + } + + return items; + } + + private String extractImageUrl(String answer) { + try { + String cleanedAnswer = answer.trim(); + if (cleanedAnswer.startsWith("\"") && cleanedAnswer.endsWith("\"")) { + cleanedAnswer = JSON.parseObject(cleanedAnswer, String.class); + } + + JSONObject obj = JSON.parseObject(cleanedAnswer); + if (obj != null && obj.containsKey("url")) { + return obj.getString("url"); + } + + JSONArray choices = obj != null ? obj.getJSONArray("choices") : null; + if (choices != null && !choices.isEmpty()) { + JSONObject choice = choices.getJSONObject(0); + JSONObject message = choice != null ? choice.getJSONObject("message") : null; + String content = message != null ? message.getString("content") : null; + if (content != null) { + JSONObject contentObj = JSON.parseObject(content); + if (contentObj != null && contentObj.containsKey("url")) { + return contentObj.getString("url"); + } + if (content.contains("http") && content.contains("https")) { + int start = content.indexOf("http"); + int end = content.indexOf("\"", start); + if (end > start) { + return content.substring(start, end); + } + } + } + } + + if (answer.contains("http") && answer.contains(".png")) { + int start = answer.indexOf("http"); + int end = answer.indexOf(".png") + 4; + if (end > start) { + return answer.substring(start, end); + } + } + if (answer.contains("http") && answer.contains(".jpg")) { + int start = answer.indexOf("http"); + int end = answer.indexOf(".jpg") + 4; + if (end > start) { + return answer.substring(start, end); + } + } + if (answer.contains("http") && answer.contains(".webp")) { + int start = answer.indexOf("http"); + int end = answer.indexOf(".webp") + 5; + if (end > start) { + return answer.substring(start, end); + } + } + } catch (Exception e) { + log.warn("提取图片URL失败: {}", e.getMessage()); + } + + throw illustrationException("无法从响应中提取图片URL"); + } + + private void callProviderWithTimeout(String providerName, Callable callable) { + boolean success; + try { + success = Boolean.TRUE.equals(AsyncUtil.callWithTimeLimit(PROVIDER_TIMEOUT_SECONDS, TimeUnit.SECONDS, callable)); + } catch (TimeoutException e) { + log.warn("{}生成配图超时,限制:{}秒", providerName, PROVIDER_TIMEOUT_SECONDS, e); + throw illustrationException(providerName + "调用超时,限制:" + PROVIDER_TIMEOUT_SECONDS + "秒"); + } catch (ForumException e) { + throw e; + } catch (Exception e) { + log.error("{}生成配图异常", providerName, e); + throw illustrationException(providerName + "调用异常: " + e.getMessage()); + } + if (!success) { + throw illustrationException(providerName + "调用失败"); + } + } + + private RuntimeException illustrationException(String message) { + return ExceptionUtil.of(StatusEnum.UNEXPECT_ERROR, message); + } +} \ No newline at end of file diff --git a/paicoding-ui/src/main/resources/templates/views/article-edit/index.html b/paicoding-ui/src/main/resources/templates/views/article-edit/index.html index aec642b6..9194ff28 100644 --- a/paicoding-ui/src/main/resources/templates/views/article-edit/index.html +++ b/paicoding-ui/src/main/resources/templates/views/article-edit/index.html @@ -500,6 +500,7 @@
微信支付说明: toolbarIcons: function () { return [ "mdFile","|", + "aiIllustration", "|", "undo", "redo", "|", "bold", "del", "italic", "quote", "ucwords", "uppercase", "lowercase", "|", "h1", "h2", "h3", "h4", "|", @@ -513,6 +514,7 @@
微信支付说明: // 用于增加自定义工具栏的功能,可以直接插入HTML标签,不使用默认的元素创建图标 toolbarIconTexts : { mdFile : "导入MD", + aiIllustration : "", video : "" }, toolbarHandlers: { @@ -578,6 +580,132 @@
微信支付说明: }; fileInput.click(); }, + aiIllustration : function(cm, icon, cursor, selection){ + console.log("AI生成配图"); + const dialogHtml = ` +
+
+
+

AI生成文章配图

+ +
+
+ + +
+
+
配图风格:小黑手绘风
+
基于文章内容分析,自动生成适合的配图位置和主题
+
+ + +
+ + +
+
+
+ `; + $('body').append(dialogHtml); + + $('#aiIllustrationCloseBtn').on('click', function() { + $('.ai-illustration-dialog-overlay').remove(); + }); + + $('#aiIllustrationCancelBtn').on('click', function() { + $('.ai-illustration-dialog-overlay').remove(); + }); + + $('.ai-illustration-dialog-overlay').on('click', function(e) { + if (e.target === this) { + $(this).remove(); + } + }); + + $(document).on('keydown.aiIllustrationDialog', function(e) { + if (e.key === 'Escape') { + $('.ai-illustration-dialog-overlay').remove(); + $(document).off('keydown.aiIllustrationDialog'); + } + }); + + $('#aiIllustrationGenerateBtn').on('click', function() { + const title = $("#titleInput").val().trim(); + const content = simplemde.getMarkdown().trim(); + const count = parseInt($('#aiIllustrationCount').val()); + + if (!title) { + toastr.warning('请先输入文章标题'); + return; + } + if (!content) { + toastr.warning('请先输入文章内容'); + return; + } + + $('#aiIllustrationGenerateBtn').prop('disabled', true).text('生成中...'); + $('#aiIllustrationLoading').show(); + $('#aiIllustrationResult').hide(); + $('#aiIllustrationList').empty(); + + post("/api/admin/article/generate/illustrations", { + title: title, + content: content, + count: count + }, function(data) { + console.log("AI配图生成结果:", data); + $('#aiIllustrationLoading').hide(); + + if (data && data.result && data.result.illustrations && data.result.illustrations.length > 0) { + $('#aiIllustrationResult').show(); + const illustrations = data.result.illustrations; + illustrations.forEach(function(illustration) { + const imgItem = ` +
+ ${illustration.theme} +
+
${illustration.theme}
+
位置:第${illustration.placement}段
+
+
+ `; + $('#aiIllustrationList').append(imgItem); + }); + + $('.ai-illustration-item').on('click', function() { + const url = $(this).data('url'); + const theme = $(this).data('theme'); + cm.replaceSelection('\n![配图:' + theme + '](' + url + ')\n\n'); + toastr.success('图片已插入文章'); + }); + + toastr.success('配图生成成功,点击图片插入到文章'); + } else { + toastr.error('生成配图失败,请重试'); + } + + $('#aiIllustrationGenerateBtn').prop('disabled', false).text('重新生成'); + }, function(error) { + console.error("AI配图生成失败:", error); + $('#aiIllustrationLoading').hide(); + $('#aiIllustrationGenerateBtn').prop('disabled', false).text('重新生成'); + toastr.error('生成配图失败,请重试'); + }); + }); + }, video : function(cm, icon, cursor, selection){ console.log("插入视频"); @@ -737,6 +865,7 @@

插入视频< lang: { toolbar: { mdFile: "导入MD", + aiIllustration: "AI配图", video: "插入视频" } }, diff --git a/paicoding-web/src/main/java/com/github/paicoding/forum/web/admin/rest/ArticleSettingRestController.java b/paicoding-web/src/main/java/com/github/paicoding/forum/web/admin/rest/ArticleSettingRestController.java index c2ed31f1..7b3b7160 100644 --- a/paicoding-web/src/main/java/com/github/paicoding/forum/web/admin/rest/ArticleSettingRestController.java +++ b/paicoding-web/src/main/java/com/github/paicoding/forum/web/admin/rest/ArticleSettingRestController.java @@ -4,6 +4,8 @@ import com.github.paicoding.forum.api.model.enums.OperateArticleEnum; import com.github.paicoding.forum.api.model.vo.PageVo; import com.github.paicoding.forum.api.model.vo.ResVo; +import com.github.paicoding.forum.api.model.vo.article.AiIllustrationGenerateReq; +import com.github.paicoding.forum.api.model.vo.article.AiIllustrationGenerateRes; import com.github.paicoding.forum.api.model.vo.article.AiSeoGenerateReq; import com.github.paicoding.forum.api.model.vo.article.AiSeoGenerateRes; import com.github.paicoding.forum.api.model.vo.article.AiSlugGenerateReq; @@ -17,6 +19,7 @@ import com.github.paicoding.forum.core.permission.Permission; import com.github.paicoding.forum.core.permission.UserRole; import com.github.paicoding.forum.core.util.NumUtil; +import com.github.paicoding.forum.service.article.service.AiIllustrationService; import com.github.paicoding.forum.service.article.service.AiSeoService; import com.github.paicoding.forum.service.article.service.ArticleReadService; import com.github.paicoding.forum.service.article.service.ArticleSettingService; @@ -53,6 +56,9 @@ public class ArticleSettingRestController { @Autowired private AiSeoService aiSeoService; + @Autowired + private AiIllustrationService aiIllustrationService; + @Permission(role = UserRole.ADMIN) @PostMapping(path = "save") public ResVo save(@RequestBody ArticlePostReq req) { @@ -149,4 +155,11 @@ public ResVo updateSlug(@RequestBody ArticleUrlSlugReq req) { return ResVo.ok(articleSettingService.updateArticleUrlSlug(req)); } + @ApiOperation("AI生成文章配图") + @PostMapping(path = "generate/illustrations") + public ResVo generateIllustrations(@RequestBody AiIllustrationGenerateReq req) { + AiIllustrationGenerateRes response = aiIllustrationService.generateIllustrations(req); + return ResVo.ok(response); + } + } diff --git a/skills/ian-xiaohei-illustrations-main/.gitignore b/skills/ian-xiaohei-illustrations-main/.gitignore new file mode 100644 index 00000000..5dac13be --- /dev/null +++ b/skills/ian-xiaohei-illustrations-main/.gitignore @@ -0,0 +1,14 @@ +.DS_Store +Thumbs.db + +# Local generated outputs +generated/ +outputs/ +dist/ + +# Local editor files +.idea/ +.vscode/ + +# Logs +*.log diff --git a/skills/ian-xiaohei-illustrations-main/LICENSE b/skills/ian-xiaohei-illustrations-main/LICENSE new file mode 100644 index 00000000..b95ca615 --- /dev/null +++ b/skills/ian-xiaohei-illustrations-main/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Ian + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/skills/ian-xiaohei-illustrations-main/NOTICE.md b/skills/ian-xiaohei-illustrations-main/NOTICE.md new file mode 100644 index 00000000..09ef8c0a --- /dev/null +++ b/skills/ian-xiaohei-illustrations-main/NOTICE.md @@ -0,0 +1,13 @@ +# Notice + +Ian Xiaohei Illustrations is an AI-agent skill created by Ian. + +The bundled example images in `examples/images/` and `ian-xiaohei-illustrations/assets/examples/` were generated by Ian and are included as style calibration examples for this skill. + +The recurring character "小黑" is part of Ian's visual language for Chinese article illustrations. When redistributing or adapting this repository, please keep the `Ian Xiaohei Illustrations` name or provide attribution to Ian in your derived documentation. + +Author links: + +- GitHub: +- Website: +- X/Twitter: diff --git a/skills/ian-xiaohei-illustrations-main/README.md b/skills/ian-xiaohei-illustrations-main/README.md new file mode 100644 index 00000000..227eb6ff --- /dev/null +++ b/skills/ian-xiaohei-illustrations-main/README.md @@ -0,0 +1,281 @@ +# Ian Xiaohei Illustrations + +> 把中文文章里的判断、流程、状态和隐喻,变成一张张白底、手绘、怪诞但清爽的正文配图。 +> +> 16:9 横版 | 小黑 IP | 纯白手绘 | 少量红橙蓝中文批注 | Codex Skill + +--- + +## 这个仓库是什么 + +Ian Xiaohei Illustrations 是一个 Codex Skill,用来指导 AI Agent 为中文文章、帖子、博客、Notion 文档和方法论内容生成正文配图。 + +它不是通用插画 prompt,也不是 PPT 信息图模板。它的核心目标是:先理解文章里的认知锚点,再把其中一个判断、流程、结构、状态或隐喻,变成一张有记忆点的 16:9 手绘解释图。 + +默认视觉 IP 是“小黑”:一个黑色实心、白点眼、细腿、空表情的小角色。小黑不是吉祥物,不是贴纸,也不是站在角落里的装饰物,而是正在认真参与系统运转的荒诞工作者。 + +一句话:**让 AI 不只是“配一张图”,而是把文章里的一个关键认知动作画出来。** + +--- + +## 适合谁用 + +特别适合: + +- 写中文文章,需要正文配图和文章插图的人 +- 做知识型内容、方法论内容、AI 工作流内容的人 +- 想把抽象判断画成具体隐喻的人 +- 想要一种比 PPT 信息图更轻、更怪、更有个人识别度的配图风格的人 +- 用 Codex 做内容生产,希望稳定复用一套视觉语言的人 + +不适合: + +- 想要商业插画、品牌 KV 或精致扁平插画的人 +- 想要传统 PPT 信息图、复杂架构图或流程图的人 +- 想要儿童卡通、可爱 IP、表情包风格的人 +- 想把大量正文、长段解释或完整课程页塞进一张图里的人 +- 需要严格可编辑矢量源文件的人 + +--- + +## 它会产出什么 + +默认输出: + +- 16:9 横版正文配图 +- 一篇文章的 4-8 张 shot list +- 每张图的主题、核心意思、结构类型、小黑动作和中文标注建议 +- 最终 PNG 图片,保存到 workspace 的 `assets/-illustrations/` + +默认不输出: + +- PPTX / PDF / Keynote +- SVG / HTML / Canvas 可编辑图 +- 商业海报或封面 KV +- 大段文字型信息图 + +--- + +## 视觉风格 + +这个 skill 默认使用 Ian 的“小黑怪诞正文配图”风格: + +- 纯白背景,不要纸纹、米色、阴影、渐变 +- 黑色手绘线稿,细线,轻微抖动 +- 大量留白,主体只占画面约 40%-60% +- 少量红色、橙色、蓝色中文手写批注 +- 一张图只表达一个核心动作、结构、状态或隐喻 +- 小黑必须参与核心动作,不能只是装饰 +- 怪诞、有创意、清爽,但不幼稚、不卖萌 + +--- + +## 示例效果 + +### 两个断点 + +![两个断点](examples/images/01-two-breakpoints.png) + +### 按目的分拣 + +![按目的分拣](examples/images/02-sort-by-purpose.png) + +### 一鱼多吃 + +![一鱼多吃](examples/images/03-one-fish-many-uses.png) + +### 承接路径 + +![承接路径](examples/images/04-handoff-path.png) + +### 信息井 + +![信息井](examples/images/05-information-well.png) + +### 想法压机 + +![想法压机](examples/images/06-idea-press.png) + +### 内容发酵 + +![内容发酵](examples/images/07-content-fermentation.png) + +### 信任桥 + +![信任桥](examples/images/08-trust-bridge.png) + +这些图片是风格校准样例,不是构图模板。使用时应该从当前文章重新发明隐喻,不要照抄旧案例的物件和构图。 + +--- + +## 安装 + +克隆仓库: + +```bash +git clone https://github.com/helloianneo/ian-xiaohei-illustrations.git +cd ian-xiaohei-illustrations +``` + +复制 skill 到 Codex skills 目录: + +```bash +mkdir -p "${CODEX_HOME:-$HOME/.codex}/skills" +cp -R ./ian-xiaohei-illustrations "${CODEX_HOME:-$HOME/.codex}/skills/" +``` + +安装后,在 Codex 里使用: + +```text +Use $ian-xiaohei-illustrations 为这篇中文文章设计并生成 5 张小黑怪诞正文配图。 +``` + +--- + +## 怎么用 + +### 只做配图规划 + +```text +Use $ian-xiaohei-illustrations 先不要生图。 +请分析下面这篇文章哪里值得配图,输出 5 张左右的 shot list。 +每张图写清楚:放在哪段后、主题、核心意思、结构类型、小黑在做什么、建议中文标注词。 + +<粘贴文章> +``` + +### 直接生成正文配图 + +```text +Use $ian-xiaohei-illustrations 把下面这篇文章生成 4 张小黑怪诞正文配图。 +要求:16:9 横版、纯白背景、黑色手绘线稿、少量红橙蓝中文手写批注。 + +<粘贴文章> +``` + +### 为单个概念生成一张图 + +```text +Use $ian-xiaohei-illustrations 为“信任不是喊出来的,而是一块证据一块证据铺过去”生成一张正文配图。 +画面要怪诞但清爽,小黑必须承担核心动作。 +``` + +### 去掉图里的标题或错误文字 + +```text +Use $ian-xiaohei-illustrations 帮我编辑这张图,去掉左上角的“流程图”标题,其他内容保持不变。 +``` + +更多示例见 [examples/prompts.md](examples/prompts.md)。 + +--- + +## 工作流程 + +这个 skill 的流程是: + +1. 读取文章、Markdown、Notion 内容、截图或用户给的主题 +2. 提炼核心观点、认知转折、流程结构和适合视觉化的段落 +3. 先输出 shot list:每张图只选一个认知锚点 +4. 为每张图选择结构类型:Workflow、系统局部、前后对比、角色状态、概念隐喻、方法分层、地图路线或小漫画分镜 +5. 重新发明一个低科技、怪诞但成立的物理隐喻 +6. 让小黑承担核心动作 +7. 每张图单独调用图像模型生成 +8. 按 QA checklist 检查:白底、留白、小黑动作、中文标注、非 PPT 感、非旧案例复刻 +9. 保存最终 PNG,并报告用途和路径 + +--- + +## 目录结构 + +```text +. +├── README.md +├── LICENSE +├── NOTICE.md +├── assets/ +│ └── ian-wechat-qr.jpg +├── examples/ +│ ├── images/ +│ │ ├── 01-two-breakpoints.png +│ │ ├── 02-sort-by-purpose.png +│ │ └── ... +│ └── prompts.md +└── ian-xiaohei-illustrations/ + ├── SKILL.md + ├── agents/ + │ └── openai.yaml + ├── assets/ + │ └── examples/ + └── references/ + ├── style-dna.md + ├── xiaohei-ip.md + ├── composition-patterns.md + ├── prompt-template.md + └── qa-checklist.md +``` + +真正需要安装到 Codex 的是子目录: + +```text +ian-xiaohei-illustrations/ +``` + +根目录的 README、LICENSE、NOTICE 和 examples 是 GitHub 分享文档。 + +--- + +## 注意事项 + +- 图片里的中文文字越短越稳定。 +- 每张图只讲一个核心结构,不要把文章做成说明书。 +- 小黑必须承担核心动作;如果去掉小黑画面仍然完全成立,说明小黑太装饰了。 +- 示例图只用于校准线条密度、留白、颜色克制和小黑参与方式,不要复刻构图。 +- AI 图像模型可能出现错字、幻觉标签、风格漂移或多余标题,生成后需要检查。 +- 如果中文错字严重,优先减少标注词并重生成。 + +--- + +## 相关项目 + +- [Ian Handdrawn PPT](https://github.com/helloianneo/ian-handdrawn-ppt) — 中文手绘技术 PPT-style 页面图生成 Skill +- [Awesome Claude Code Skills](https://github.com/helloianneo/awesome-claude-code-skills) — Claude Code Skills / Agents / Plugins 精选合集 +- [Obsidian + Claude AI Second Brain](https://github.com/helloianneo/obsidian-ai-second-brain) — Obsidian + Claude AI 个人知识库搭建指南 + +--- + +## 关于作者 + +**Ian (伊恩)** — 产品设计师 / 一人公司实践者 / AI Builder + +用 AI 团队打造一人公司。 + +- GitHub: [helloianneo](https://github.com/helloianneo) +- X/Twitter: [@ianneo_ai](https://x.com/ianneo_ai) +- 网站: [www.ianneo.xyz](https://www.ianneo.xyz) +- 微信: `ianneoxyz` +- 邮箱: hello.neoc@gmail.com + +--- + +## 继续探索 + +这套小黑配图 Skill,只是我用 AI 搭建个人生产系统里的一个小工具。 + +如果你也在用 AI 做内容、知识库、工作流或产品化,可以继续看我的网站:[www.ianneo.xyz](https://www.ianneo.xyz)。 + +只想先观察,可以关注我的 [X/Twitter](https://x.com/ianneo_ai)。 + +想了解 Indie Builders Club,加微信:`ianneoxyz`,备注「OPC」。 + +

+ Ian 微信二维码 +

+ +不方便扫码也可以搜索微信:`ianneoxyz`。 + +--- + +## License + +MIT License. See [LICENSE](LICENSE). diff --git a/skills/ian-xiaohei-illustrations-main/assets/ian-wechat-qr.jpg b/skills/ian-xiaohei-illustrations-main/assets/ian-wechat-qr.jpg new file mode 100644 index 00000000..ca1d83ec Binary files /dev/null and b/skills/ian-xiaohei-illustrations-main/assets/ian-wechat-qr.jpg differ diff --git a/skills/ian-xiaohei-illustrations-main/examples/images/01-two-breakpoints.png b/skills/ian-xiaohei-illustrations-main/examples/images/01-two-breakpoints.png new file mode 100644 index 00000000..44c197de Binary files /dev/null and b/skills/ian-xiaohei-illustrations-main/examples/images/01-two-breakpoints.png differ diff --git a/skills/ian-xiaohei-illustrations-main/examples/images/02-sort-by-purpose.png b/skills/ian-xiaohei-illustrations-main/examples/images/02-sort-by-purpose.png new file mode 100644 index 00000000..80b29896 Binary files /dev/null and b/skills/ian-xiaohei-illustrations-main/examples/images/02-sort-by-purpose.png differ diff --git a/skills/ian-xiaohei-illustrations-main/examples/images/03-one-fish-many-uses.png b/skills/ian-xiaohei-illustrations-main/examples/images/03-one-fish-many-uses.png new file mode 100644 index 00000000..b87e74a0 Binary files /dev/null and b/skills/ian-xiaohei-illustrations-main/examples/images/03-one-fish-many-uses.png differ diff --git a/skills/ian-xiaohei-illustrations-main/examples/images/04-handoff-path.png b/skills/ian-xiaohei-illustrations-main/examples/images/04-handoff-path.png new file mode 100644 index 00000000..166b9c9a Binary files /dev/null and b/skills/ian-xiaohei-illustrations-main/examples/images/04-handoff-path.png differ diff --git a/skills/ian-xiaohei-illustrations-main/examples/images/05-information-well.png b/skills/ian-xiaohei-illustrations-main/examples/images/05-information-well.png new file mode 100644 index 00000000..f498931c Binary files /dev/null and b/skills/ian-xiaohei-illustrations-main/examples/images/05-information-well.png differ diff --git a/skills/ian-xiaohei-illustrations-main/examples/images/06-idea-press.png b/skills/ian-xiaohei-illustrations-main/examples/images/06-idea-press.png new file mode 100644 index 00000000..5d124836 Binary files /dev/null and b/skills/ian-xiaohei-illustrations-main/examples/images/06-idea-press.png differ diff --git a/skills/ian-xiaohei-illustrations-main/examples/images/07-content-fermentation.png b/skills/ian-xiaohei-illustrations-main/examples/images/07-content-fermentation.png new file mode 100644 index 00000000..c056506f Binary files /dev/null and b/skills/ian-xiaohei-illustrations-main/examples/images/07-content-fermentation.png differ diff --git a/skills/ian-xiaohei-illustrations-main/examples/images/08-trust-bridge.png b/skills/ian-xiaohei-illustrations-main/examples/images/08-trust-bridge.png new file mode 100644 index 00000000..18d3556f Binary files /dev/null and b/skills/ian-xiaohei-illustrations-main/examples/images/08-trust-bridge.png differ diff --git a/skills/ian-xiaohei-illustrations-main/examples/prompts.md b/skills/ian-xiaohei-illustrations-main/examples/prompts.md new file mode 100644 index 00000000..06c3b296 --- /dev/null +++ b/skills/ian-xiaohei-illustrations-main/examples/prompts.md @@ -0,0 +1,83 @@ +# Prompt Examples + +下面这些 prompt 可以直接复制到 Codex 里使用。 + +## 只做配图规划 + +```text +Use $ian-xiaohei-illustrations 先不要生图。 +请分析下面这篇文章哪里值得配图,输出 5 张左右的 shot list。 +每张图写清楚: +- 放在哪个段落后 +- 图的主题 +- 核心意思 +- 结构类型 +- 小黑在图里做什么 +- 建议元素 +- 建议中文标注词 + +<粘贴文章> +``` + +## 文章正文配图 + +```text +Use $ian-xiaohei-illustrations 把下面这篇文章生成 4 张小黑怪诞正文配图。 +要求:16:9 横版、纯白背景、黑色手绘线稿、少量红橙蓝中文手写批注。 +每张图只讲一个核心结构,不要做 PPT 信息图,不要可爱卡通。 + +<粘贴文章> +``` + +## 长文配图策略 + +```text +Use $ian-xiaohei-illustrations 给这篇长文做配图策略。 +不要平均配图,只挑认知锚点:核心判断、输入输出闭环、前后对比、常见坑、承接路径。 +默认 6-8 张,先输出 shot list,不要生成图片。 + +<粘贴文章> +``` + +## 单个观点生成一张图 + +```text +Use $ian-xiaohei-illustrations 为这个观点生成一张 16:9 正文配图: + +信任不是喊出来的,而是一块证据一块证据铺过去。 + +画面要怪诞但清爽,小黑必须承担核心动作。 +中文标注最多 5 个,短一点。 +``` + +## 工作流主题 + +```text +Use $ian-xiaohei-illustrations 为“把一条原始素材加工成流量、信任、转化三种内容”生成一张图。 +不要画正式流程图,不要复刻一鱼多吃旧案例。 +请重新发明一个新的低科技隐喻,让小黑参与核心动作。 +``` + +## 改图:去掉标题 + +```text +Use $ian-xiaohei-illustrations 帮我编辑这张图。 +去掉左上角的“Workflow / 流程图”标题和下划线,其他内容保持不变。 +不要新增任何文字或物件。 +``` + +## 改图:增强小黑参与感 + +```text +Use $ian-xiaohei-illustrations 这张图方向对,但小黑有点像装饰。 +请保持核心意思不变,重生成一版:让小黑成为真正推动结构运转的人。 +画面更怪一点,但仍然纯白、清爽、少字。 +``` + +## 生成一组风格样片 + +```text +Use $ian-xiaohei-illustrations 输出 5 个不同主题的小黑正文配图效果。 +主题分别覆盖:信息过载、产品验证、内容复利、一人公司、信任建立。 +每张单独生成,不要拼成一张。 +``` diff --git a/skills/ian-xiaohei-illustrations-main/ian-xiaohei-illustrations/SKILL.md b/skills/ian-xiaohei-illustrations-main/ian-xiaohei-illustrations/SKILL.md new file mode 100644 index 00000000..90192663 --- /dev/null +++ b/skills/ian-xiaohei-illustrations-main/ian-xiaohei-illustrations/SKILL.md @@ -0,0 +1,106 @@ +--- +name: ian-xiaohei-illustrations +description: 生成 Ian 风格的中文正文配图。用于用户要求为中文文章、帖子、博客、Notion 文档、工作流文档、方法论、流程、结构、状态、隐喻或观点生成“怪诞”“小黑”“手绘”“正文配图”“文章插图”“配图建议”“shot list”“去标题/改图”等任务;默认使用小黑 IP、纯白手绘、少量红橙蓝批注、简洁清爽但天马行空的视觉风格。 +--- + +# Ian 小黑怪诞正文配图 + +## 核心定位 + +为中文文章设计和生成 16:9 横版正文配图。目标不是做商业插画、PPT 信息图或可爱卡通,而是把文章里的关键判断、流程、结构、状态或隐喻,变成一张清爽、怪诞、有创意、可读但不说明书的手绘解释图。 + +默认视觉 IP 是“小黑”:黑色实心、白点眼、细腿、空表情,认真做一件荒诞但成立的事。小黑必须参与画面的核心动作,不能只是站在旁边当装饰。 + +## 先读这些参考 + +按任务需要读取,不要一次塞满上下文: + +- `references/style-dna.md`:风格 DNA、颜色、文字、禁忌。 +- `references/xiaohei-ip.md`:小黑 IP 的形象、性格、动作库和禁忌。 +- `references/composition-patterns.md`:结构类型、原创隐喻方法和反复刻规则。 +- `references/prompt-template.md`:单张生图提示词模板。 +- `references/qa-checklist.md`:生成后检查和迭代规则。 +- `assets/examples/`:只作低频视觉校准,不进入默认生成路径。不要照抄这些案例的构图、物件或标注。 + +## 工作流 + +### 1. 消化正文 + +先读用户给的正文、链接、Notion 页面、Markdown 文件或截图内容。提炼: + +- 核心观点是什么 +- 哪些段落承担认知转折 +- 哪些内容适合用图解释 +- 哪些地方只适合文字,不需要图 + +不要平均配图。优先选择“认知锚点”,例如:核心判断、两个断点、输入输出闭环、分流、前后对比、一鱼多吃、承接路径、常见坑、角色状态变化。 + +### 2. 先出配图策略 + +如果用户只是说“分析怎么配图 / 思考哪些地方需要配图”,先给 shot list。每张图写清楚: + +- 放在哪个段落后 +- 图的主题 +- 核心意思 +- 结构类型 +- 小黑在图里做什么 +- 建议元素 +- 建议中文标注词 + +默认 4-8 张。文章很短时 1-3 张;长文也不要轻易超过 9 张。够用就好,避免把正文做成画册。 + +### 3. 单张生成 + +如果用户明确要求“生成 / 输出 / 做图 / 帮我生成”,不要停下来等确认;用内置 `image_gen` 每张单独生成。不要把多张图拼在一张里。 + +每张图只讲一个核心结构。提示词必须包含: + +- 16:9 横版中文正文配图 +- 纯白背景 +- 黑色手绘线稿 +- 少量红色/橙色/蓝色中文手写批注 +- 大量留白 +- 小黑作为核心动作主体 +- 禁止 PPT、商业插画、幼稚可爱、复杂架构、左上角类型标题 + +不要复刻过往案例。案例只提供风格密度和小黑参与方式,不能直接复用“传送带断点 / 小黑拉线 / 素材鱼 / 盖章工具箱 / 常见坑路径”等已有构图,除非用户明确要求复刻某张图。每次都要从当前文章重新发明一个奇怪但成立的隐喻。 + +### 4. 检查与迭代 + +生成后检查 `references/qa-checklist.md`。如果出现以下问题,优先重生成或局部编辑: + +- 小黑只是装饰 +- 画面太满 +- 太像流程图/PPT +- 中文太多或错字严重 +- 左上角出现“常见坑/流程图/系统架构图”等标题 +- 画风太可爱、幼稚、死板 +- 背景不是干净白底 + +### 5. 保存交付 + +如果用户在 workspace 内工作,把最终图复制到: + +```text +assets/-illustrations/ +``` + +按顺序命名: + +```text +01-topic-name.png +02-topic-name.png +``` + +保留原始生成文件,不要覆盖已有资产,除非用户明确要求替换。 + +## 输出口径 + +生成前的策略输出要短而准。生成后的交付要包含: + +- 生成了几张 +- 每张图的用途 +- 保存路径 +- 哪些图最稳,哪些图是可选 + +不要长篇解释风格理论;让图自己说话。 diff --git a/skills/ian-xiaohei-illustrations-main/ian-xiaohei-illustrations/agents/openai.yaml b/skills/ian-xiaohei-illustrations-main/ian-xiaohei-illustrations/agents/openai.yaml new file mode 100644 index 00000000..611a8c54 --- /dev/null +++ b/skills/ian-xiaohei-illustrations-main/ian-xiaohei-illustrations/agents/openai.yaml @@ -0,0 +1,6 @@ +interface: + display_name: "Ian 小黑配图" + short_description: "为中文文章生成怪诞清爽、有小黑IP的正文配图资产" + default_prompt: "Use $ian-xiaohei-illustrations to 为这篇中文文章设计并生成几张小黑怪诞正文配图。" +policy: + allow_implicit_invocation: true diff --git a/skills/ian-xiaohei-illustrations-main/ian-xiaohei-illustrations/assets/examples/01-two-breakpoints.png b/skills/ian-xiaohei-illustrations-main/ian-xiaohei-illustrations/assets/examples/01-two-breakpoints.png new file mode 100644 index 00000000..44c197de Binary files /dev/null and b/skills/ian-xiaohei-illustrations-main/ian-xiaohei-illustrations/assets/examples/01-two-breakpoints.png differ diff --git a/skills/ian-xiaohei-illustrations-main/ian-xiaohei-illustrations/assets/examples/02-minimum-loop.png b/skills/ian-xiaohei-illustrations-main/ian-xiaohei-illustrations/assets/examples/02-minimum-loop.png new file mode 100644 index 00000000..2629a08f Binary files /dev/null and b/skills/ian-xiaohei-illustrations-main/ian-xiaohei-illustrations/assets/examples/02-minimum-loop.png differ diff --git a/skills/ian-xiaohei-illustrations-main/ian-xiaohei-illustrations/assets/examples/03-sort-by-purpose.png b/skills/ian-xiaohei-illustrations-main/ian-xiaohei-illustrations/assets/examples/03-sort-by-purpose.png new file mode 100644 index 00000000..80b29896 Binary files /dev/null and b/skills/ian-xiaohei-illustrations-main/ian-xiaohei-illustrations/assets/examples/03-sort-by-purpose.png differ diff --git a/skills/ian-xiaohei-illustrations-main/ian-xiaohei-illustrations/assets/examples/04-one-fish-many-uses.png b/skills/ian-xiaohei-illustrations-main/ian-xiaohei-illustrations/assets/examples/04-one-fish-many-uses.png new file mode 100644 index 00000000..b87e74a0 Binary files /dev/null and b/skills/ian-xiaohei-illustrations-main/ian-xiaohei-illustrations/assets/examples/04-one-fish-many-uses.png differ diff --git a/skills/ian-xiaohei-illustrations-main/ian-xiaohei-illustrations/assets/examples/05-handoff-path.png b/skills/ian-xiaohei-illustrations-main/ian-xiaohei-illustrations/assets/examples/05-handoff-path.png new file mode 100644 index 00000000..166b9c9a Binary files /dev/null and b/skills/ian-xiaohei-illustrations-main/ian-xiaohei-illustrations/assets/examples/05-handoff-path.png differ diff --git a/skills/ian-xiaohei-illustrations-main/ian-xiaohei-illustrations/assets/examples/06-three-sources.png b/skills/ian-xiaohei-illustrations-main/ian-xiaohei-illustrations/assets/examples/06-three-sources.png new file mode 100644 index 00000000..e6b51a74 Binary files /dev/null and b/skills/ian-xiaohei-illustrations-main/ian-xiaohei-illustrations/assets/examples/06-three-sources.png differ diff --git a/skills/ian-xiaohei-illustrations-main/ian-xiaohei-illustrations/assets/examples/07-three-content-jobs.png b/skills/ian-xiaohei-illustrations-main/ian-xiaohei-illustrations/assets/examples/07-three-content-jobs.png new file mode 100644 index 00000000..5ffd89fe Binary files /dev/null and b/skills/ian-xiaohei-illustrations-main/ian-xiaohei-illustrations/assets/examples/07-three-content-jobs.png differ diff --git a/skills/ian-xiaohei-illustrations-main/ian-xiaohei-illustrations/assets/examples/08-handoff-copy-toolbox.png b/skills/ian-xiaohei-illustrations-main/ian-xiaohei-illustrations/assets/examples/08-handoff-copy-toolbox.png new file mode 100644 index 00000000..1c0ad2c0 Binary files /dev/null and b/skills/ian-xiaohei-illustrations-main/ian-xiaohei-illustrations/assets/examples/08-handoff-copy-toolbox.png differ diff --git a/skills/ian-xiaohei-illustrations-main/ian-xiaohei-illustrations/assets/examples/09-common-pits-no-title.png b/skills/ian-xiaohei-illustrations-main/ian-xiaohei-illustrations/assets/examples/09-common-pits-no-title.png new file mode 100644 index 00000000..6b2fcb8c Binary files /dev/null and b/skills/ian-xiaohei-illustrations-main/ian-xiaohei-illustrations/assets/examples/09-common-pits-no-title.png differ diff --git a/skills/ian-xiaohei-illustrations-main/ian-xiaohei-illustrations/assets/examples/10-information-well.png b/skills/ian-xiaohei-illustrations-main/ian-xiaohei-illustrations/assets/examples/10-information-well.png new file mode 100644 index 00000000..f498931c Binary files /dev/null and b/skills/ian-xiaohei-illustrations-main/ian-xiaohei-illustrations/assets/examples/10-information-well.png differ diff --git a/skills/ian-xiaohei-illustrations-main/ian-xiaohei-illustrations/assets/examples/11-idea-press.png b/skills/ian-xiaohei-illustrations-main/ian-xiaohei-illustrations/assets/examples/11-idea-press.png new file mode 100644 index 00000000..5d124836 Binary files /dev/null and b/skills/ian-xiaohei-illustrations-main/ian-xiaohei-illustrations/assets/examples/11-idea-press.png differ diff --git a/skills/ian-xiaohei-illustrations-main/ian-xiaohei-illustrations/assets/examples/12-content-fermentation.png b/skills/ian-xiaohei-illustrations-main/ian-xiaohei-illustrations/assets/examples/12-content-fermentation.png new file mode 100644 index 00000000..c056506f Binary files /dev/null and b/skills/ian-xiaohei-illustrations-main/ian-xiaohei-illustrations/assets/examples/12-content-fermentation.png differ diff --git a/skills/ian-xiaohei-illustrations-main/ian-xiaohei-illustrations/assets/examples/13-system-bearing.png b/skills/ian-xiaohei-illustrations-main/ian-xiaohei-illustrations/assets/examples/13-system-bearing.png new file mode 100644 index 00000000..efcae9e8 Binary files /dev/null and b/skills/ian-xiaohei-illustrations-main/ian-xiaohei-illustrations/assets/examples/13-system-bearing.png differ diff --git a/skills/ian-xiaohei-illustrations-main/ian-xiaohei-illustrations/assets/examples/14-trust-bridge.png b/skills/ian-xiaohei-illustrations-main/ian-xiaohei-illustrations/assets/examples/14-trust-bridge.png new file mode 100644 index 00000000..18d3556f Binary files /dev/null and b/skills/ian-xiaohei-illustrations-main/ian-xiaohei-illustrations/assets/examples/14-trust-bridge.png differ diff --git a/skills/ian-xiaohei-illustrations-main/ian-xiaohei-illustrations/references/composition-patterns.md b/skills/ian-xiaohei-illustrations-main/ian-xiaohei-illustrations/references/composition-patterns.md new file mode 100644 index 00000000..d7ff928f --- /dev/null +++ b/skills/ian-xiaohei-illustrations-main/ian-xiaohei-illustrations/references/composition-patterns.md @@ -0,0 +1,91 @@ +# 构图模式与原创规则 + +## 基础结构类型 + +选择一种结构即可,不要混太多。 + +### Workflow 流程 + +适合:输入 -> 处理 -> 输出,内容生产,AI 工作流,自动化链路。 + +画法:左侧输入,中间小黑或怪机器处理,右侧输出,橙色箭头表达主流向。 + +### 系统局部 + +适合:信息来源、过滤器、数据库、渲染器、agent 系统局部。 + +画法:只画 3-5 个核心模块,小黑参与其中一个关键动作。 + +### 前后对比 + +适合:混乱/有序,手动/自动,分散/收拢,焦虑/稳定。 + +画法:左混乱,右稳定,中间橙色箭头。角色可以更夸张。 + +### 角色状态 + +适合:用户痛点、创作者状态、工具太多、信息焦虑、卡住到跑起来。 + +画法:2-4 个小状态,每个状态一个短标注。 + +### 概念隐喻 + +适合:内容工厂、信息仓库、脑内黑盒、工作流机器、自动日报。 + +画法:一个大的怪物件或机器,少量输入,一个输出。要有记忆点。 + +### 方法分层 + +适合:方法论框架、系统层级、能力栈、内容系统分层。 + +画法:一层层盒子,不要正式金字塔;小黑在旁边搬砖或搭建。 + +### 地图路线 + +适合:从想法到上线、用户路径、内容承接路径、学习路线。 + +画法:一条弯曲路径,少量节点,小黑牵线或走路。 + +### 小漫画分镜 + +适合:失败到成功、真实过程、吐槽、使用前后变化。 + +画法:2-4 个小场景,每格只表达一个动作。 + +## 原创隐喻生成法 + +每次都从当前文章重新发明隐喻,不能照搬旧图。 + +### 三步 + +1. 把抽象概念换成一个物理动作:卡住、漏掉、变重、分拣、沉淀、发酵、开门、折叠、拆包、回流。 +2. 把系统结构换成一个低科技物件:坏掉的机器、纸箱、抽屉、水管、邮筒、怪表盘、秤、井、梯子、奇怪工位。 +3. 让小黑承担动作:不是站旁边,而是卡在机器里、拉错线、守门、搬运、修补、称重、扶梯子、记录、把东西塞进某个怪装置。 + +### 可用物件池 + +- 纸箱、抽屉、旧机器、漏斗、秤、邮筒、门、井、梯子、水管、线团、闸门、转盘、黑盒、打孔器、压面机、晾衣绳、怪工位。 +- 用时只选 1-2 个,不要堆满。 + +### 小黑动作池 + +- 拉、扛、塞、捞、压、称、缝、剪、拧、守、推、接、拆、标记、回收。 +- 动作要服务核心意思,不要为了怪而怪。 + +## 反复刻规则 + +不要默认打开或复刻 `assets/examples/`。这些图片只用于风格校准,例如线条密度、留白、颜色克制、小黑气质。 + +除非用户明确说“照这张 / 复刻这个构图 / 用这个案例改”,否则不要直接复用这些旧构图: + +- 传送带两个断点 +- 小黑在内容机器里拉判断杆 +- 小黑变漏斗分拣流量/信任/转化 +- 小黑切素材鱼 +- 小黑牵承接路径 +- 小黑拉三层信息源 +- 三个小黑分别拿喇叭/搭桥/开门 +- 小黑盖章话术工具箱 +- 小黑举牌看常见坑路径 + +同类主题也要换新隐喻。例如“承接路径”不一定画路线,可以画小黑把内容尾巴接到门把手;“一鱼多吃”不一定画鱼,可以画小黑把一个纸团压成几种形状。 diff --git a/skills/ian-xiaohei-illustrations-main/ian-xiaohei-illustrations/references/prompt-template.md b/skills/ian-xiaohei-illustrations-main/ian-xiaohei-illustrations/references/prompt-template.md new file mode 100644 index 00000000..ddfeda83 --- /dev/null +++ b/skills/ian-xiaohei-illustrations-main/ian-xiaohei-illustrations/references/prompt-template.md @@ -0,0 +1,51 @@ +# 生图提示词模板 + +每张图单独生成。根据正文内容替换变量,不要把多张图拼在一起。 + +```text +Generate one standalone 16:9 horizontal Chinese article illustration. + +Visual DNA: +Pure white background. Minimalist black hand-drawn line art. Slightly wobbly pen lines. Lots of empty white space. Sparse red/orange/blue handwritten Chinese annotations. Clean absurd product-sketch feeling. No gradients, no shadows, no paper texture, no complex background, no commercial vector style, no PPT infographic look, no cute mascot poster, no children's illustration, no realistic UI. + +Recurring IP character required: +小黑, a small solid-black absurd creature with white dot eyes, tiny thin legs, blank serious expression, slightly uneven hand-drawn body shape. 小黑 must perform the core conceptual action, not decorate the scene. Make 小黑 serious, deadpan, and slightly bizarre, not cute. + +Theme: +{正文配图主题} + +Structure type: +{结构类型:Workflow / 系统局部 / 前后对比 / 角色状态 / 概念隐喻 / 方法分层 / 地图路线 / 小漫画分镜} + +Core idea: +{这张图要表达的核心意思} + +Composition: +{具体画面:小黑在哪里、正在做什么、主要物件是什么、信息如何流动} + +Suggested elements: +{元素1} / {元素2} / {元素3} / {元素4} + +Chinese handwritten labels: +{标注词1} / {标注词2} / {标注词3} / {标注词4} / {可选标注词5} + +Color use: +Black for main line art and 小黑. Orange for main flow/path/arrows. Red only for key warnings/problems/results. Blue only for secondary notes or feedback/system state. + +Constraints: +One image explains only one core structure. Keep the main subject around 40%-60% of the canvas. Preserve at least 35% blank white space. Use at most 5-8 short handwritten Chinese labels. Do not write a title in the top-left corner. Do not write the structure type on the image. Do not make it a formal diagram, course slide, or dense explainer. Do not copy prior examples or reuse known case compositions unless explicitly requested; invent a fresh visual metaphor for this specific article. It should be clear but not instructional, interesting but not childish, strange but clean. +``` + +## 图像编辑提示 + +去掉左上角标题: + +```text +Edit the provided image. Remove only the handwritten title "{要删除的文字}" and its underline from the top-left corner. Fill that area with the same clean white background, matching the surrounding blank paper. Preserve everything else exactly: characters, labels, paths, line style, composition, aspect ratio, and image quality. Do not add any new text or objects. +``` + +增强怪诞感: + +```text +Regenerate this illustration with the same core meaning and simple layout, but make 小黑 more central to the conceptual action. 小黑 should be doing the strange work that explains the idea, not standing beside the diagram. Keep it clean, sparse, hand-drawn, and not cute. +``` diff --git a/skills/ian-xiaohei-illustrations-main/ian-xiaohei-illustrations/references/qa-checklist.md b/skills/ian-xiaohei-illustrations-main/ian-xiaohei-illustrations/references/qa-checklist.md new file mode 100644 index 00000000..da5b0c40 --- /dev/null +++ b/skills/ian-xiaohei-illustrations-main/ian-xiaohei-illustrations/references/qa-checklist.md @@ -0,0 +1,46 @@ +# QA Checklist + +## 必过项 + +- 是 16:9 横版。 +- 背景是干净白底。 +- 有小黑。 +- 小黑承担核心动作,不只是装饰。 +- 没有复刻旧案例构图,而是为当前文章生成了新隐喻。 +- 画面怪诞、有创意、有意思。 +- 简洁清爽,主体不超过画面约 60%。 +- 一张图只讲一个核心结构。 +- 中文标注少、短、能读。 +- 橙色只用于主路径或箭头。 +- 红色只用于重点、问题、提醒或结果。 +- 蓝色只用于补充说明、反馈或系统状态。 + +## 失败信号 + +出现以下情况,重生成或局部编辑: + +- 左上角有“常见坑 / Workflow / 系统架构图 / 路线图”等标题。 +- 小黑像吉祥物、表情包或可爱卡通。 +- 画面像 PPT、课程课件、正式流程图。 +- 元素太多、箭头太多、节点太多。 +- 文字变成大段解释。 +- 背景有纸纹、阴影、渐变、米色、噪点。 +- 真实 UI 截图或科技感界面。 +- 中文错字严重或标注不可读。 +- 画面太死板,没有荒诞隐喻。 +- 和 `assets/examples/` 里的旧案例构图过于相似。 + +## 迭代方法 + +- 太普通:让小黑成为动作主体,加入一个奇怪但成立的隐喻。 +- 太复杂:删节点,只保留一个动作和 3-5 个短标注。 +- 太可爱:强调 deadpan、blank serious expression、not cute、not mascot。 +- 太 PPT:去掉标题、边框、整齐网格和过多箭头,改成手绘场景。 +- 太像旧案例:保留核心意思,换掉主物件和小黑动作。 +- 文字错:优先局部编辑;错得多就重生成并减少标注数量。 + +## 交付判断 + +高质量图应该让读者先觉得“有点怪”,然后 1 秒内看懂结构。 + +如果第一眼像教程页,而不是白纸上的怪诞产品草图,就不合格。 diff --git a/skills/ian-xiaohei-illustrations-main/ian-xiaohei-illustrations/references/style-dna.md b/skills/ian-xiaohei-illustrations-main/ian-xiaohei-illustrations/references/style-dna.md new file mode 100644 index 00000000..042f7616 --- /dev/null +++ b/skills/ian-xiaohei-illustrations-main/ian-xiaohei-illustrations/references/style-dna.md @@ -0,0 +1,48 @@ +# 风格 DNA + +## 一句话 + +纯白、极简、手绘、留白、克制、怪诞、产品草图感、中文手写感、结构清楚但不说明书。 + +像一个长期做 AI、产品、设计、开发工具的人,在白纸上随手画出来的一张解释草图。 + +## 必须 + +- 16:9 横版正文配图。 +- 纯白背景:不要米色、暖灰、纸张纹理、渐变、阴影、噪点、复古纸感。 +- 黑色手绘线稿为主:细线、轻微抖动、不机械、不矢量、不厚重描边。 +- 大量留白:主体占画面约 40%-60%,至少 35% 空白,最好有一整块安静区域。 +- 少量中文手写批注:最多 5-8 处,每处尽量 2-8 个字。 +- 一张图只讲一个核心动作、结构、状态或隐喻。 +- 结构要自然表达,不要在图上写结构类型名称。 + +## 颜色 + +- 黑色:主体线稿、角色、框线、结构、主要文字、主体物件。 +- 红色:重点批注、问题、情绪点、关键提醒、结果。 +- 橙色:主流程、路径、箭头、自动化流向、从 A 到 B 的移动关系。 +- 蓝色:补充说明、脑内状态、系统状态、第二层解释、AI/assistant/自动化提示。 + +蓝色不是每张都必须用。颜色要克制,宁可少不要多。 + +## 绝对不要 + +- 不要商业插画。 +- 不要 PPT 信息图。 +- 不要正式流程图。 +- 不要课程课件。 +- 不要可爱卡通海报。 +- 不要儿童插画。 +- 不要复杂架构图。 +- 不要精致扁平插画。 +- 不要科技感 UI。 +- 不要真实 App 截图。 +- 不要复杂背景、渐变、阴影、纹理。 +- 不要把每个节点都解释清楚。 +- 不要左上角写“Workflow 流程图 / 系统架构图 / 常见坑 / 路线图”等类型标题。 + +## 审美方向 + +要怪诞、创意、有意思、简洁清爽、天马行空。 + +不要可爱、幼稚、很复杂、死板。 diff --git a/skills/ian-xiaohei-illustrations-main/ian-xiaohei-illustrations/references/xiaohei-ip.md b/skills/ian-xiaohei-illustrations-main/ian-xiaohei-illustrations/references/xiaohei-ip.md new file mode 100644 index 00000000..93ac2330 --- /dev/null +++ b/skills/ian-xiaohei-illustrations-main/ian-xiaohei-illustrations/references/xiaohei-ip.md @@ -0,0 +1,53 @@ +# 小黑 IP + +## 角色定义 + +小黑是 Ian 中文正文配图的固定视觉 IP。 + +默认每张图都要出现小黑。小黑不是吉祥物,不是贴纸,不是可爱装饰,而是正在认真参与系统运转的荒诞工作者。 + +## 外形 + +- 黑色实心小怪物。 +- 白色圆点眼睛。 +- 细腿,偶尔有细胳膊。 +- 身体可以是圆柱、黑豆、黑盒、漏斗、影子、洞口、机器内部黑块。 +- 轮廓略微不规则,有手绘感。 +- 表情空、呆、冷静、认真。 + +## 性格 + +- 很认真,但做的事有点荒诞。 +- 像一个低调的系统操作员。 +- 冷幽默,不卖萌。 +- 有点笨拙,但不蠢。 +- 像在白板草图里真的负责某个工作。 + +## 常见职责 + +让小黑承担核心动作: + +- 搬运素材。 +- 拉线汇聚信息源。 +- 卡在断点里。 +- 在机器里操作“判断”杆。 +- 变成筛选漏斗。 +- 切开“素材鱼”。 +- 盖章承接话术。 +- 牵着承接路径。 +- 举警告牌看坑。 +- 从洞里伸手但接不住内容。 +- 在旁边搬砖、搭桥、开门、分拣、记录。 + +## 禁止 + +- 不要把小黑画成过度可爱的吉祥物。 +- 不要画成儿童卡通角色。 +- 不要给小黑复杂服装、表情包、闪亮眼睛。 +- 不要让小黑只是站在角落里看。 +- 不要让小黑抢走结构表达。 +- 不要把小黑画得太商业、太圆润、太精致。 + +## 判断标准 + +如果去掉小黑,图的核心隐喻还能完全成立,说明小黑太装饰了;要重写提示词,让小黑成为动作主体。