返回顶部
m

myvibe-publish发布到MyVibe

Publish static HTML, ZIP archive, or directory to MyVibe. Use this skill when user wants to publish web content to MyVibe.

作者: admin | 来源: ClawHub
源自
ClawHub
版本
V 1.0.0
安全检测
已通过
1,045
下载量
免费
免费
0
收藏
概述
安装方式
版本历史

myvibe-publish

MyVibe 发布

将网页内容(HTML 文件、ZIP 压缩包或目录)发布到 MyVibe。

前提条件

  • - Node.js 18 或更高版本
  • 此技能中的所有脚本执行都需要网络访问。始终使用 sandboxpermissions=requireescalated 运行 Bash 命令,以确保网络权限已启用。
  • 部署和截图生成可能需要几分钟。对发布命令使用 10 分钟(600000ms)的超时时间。

使用方法

bash
/myvibe:myvibe-publish --file ./dist.zip # 发布 ZIP 压缩包
/myvibe:myvibe-publish --file ./index.html # 发布 HTML 文件
/myvibe:myvibe-publish --dir ./dist # 发布目录
/myvibe:myvibe-publish --url https://example.com/app # 从 URL 导入
/myvibe:myvibe-publish --dir ./dist --new # 强制创建新的 Vibe
/myvibe:myvibe-publish --dir ./dist --did z2qaXXX # 更新指定的 Vibe

选项

选项别名描述
--file <路径>-fHTML 文件或 ZIP 压缩包的路径
--dir <路径>
-d | 要压缩并发布的目录 | | --url <网址> | -u | 要导入并发布的 URL | | --hub <网址> | -h | MyVibe URL(默认:https://www.myvibe.so/) | | --title <标题> | -t | 项目标题 | | --desc <描述> | | 项目描述 | | --visibility <可见性> | -v | 可见性:public 或 private(默认:public) | | --did | | 用于版本更新的 Vibe DID(覆盖自动检测) | | --new | | 强制创建新的 Vibe,忽略发布历史 |

工作流程概览

  1. 1. 检测项目类型 → 如果不需要构建,后台启动截图
  2. 构建(如果需要)→ 然后后台启动截图
  3. 元数据分析 → 提取标题、描述、标签
  4. 确认发布 → 显示元数据,获取用户确认
  5. 执行发布 → 脚本自动读取截图结果
  6. 返回结果 → 显示发布 URL

首次工具调用 - 并行执行:

  • - Read:读取源文件或目录中的主要文件
  • Bash:git remote get-url origin 2>/dev/null || echo Not a git repo
  • Bash:node {skill_path}/scripts/utils/fetch-tags.mjs --hub {hub}



步骤 1:检测项目类型


检查项项目类型下一步
--file 带有 HTML/ZIP单个文件→ 启动截图,然后执行步骤 3
存在包含 index.html 的 dist/、build/ 或 out/
预构建 | → 步骤 2(确认重新构建) |
| 存在包含构建脚本的 package.json,无输出 | 可构建 | → 步骤 2(先构建) |
| 多个 package.json 或工作区配置 | Monorepo | → 步骤 2(选择应用) |
| 根目录存在 index.html,无 package.json | 静态 | → 启动截图,然后执行步骤 3 |

为非构建项目启动截图(runinbackground: true):

对于目录源(--dir):
bash
node {skillpath}/scripts/utils/generate-screenshot.mjs --dir {publishtarget} --hub {hub}

对于单个文件源(--file):
bash
node {skillpath}/scripts/utils/generate-screenshot.mjs --file {publishtarget} --hub {hub}

重要提示:当源是单个 HTML 文件时使用 --file,当源是目录时使用 --dir。该标志必须与发布配置中的 source.type 匹配,以便两个脚本为截图结果文件计算相同的哈希值。

启动截图后台任务后,在继续之前使用 TaskOutput(带 block: false)检查任务输出。如果输出包含agent-browser is not installed或Chromium is not installed:

  1. 1. 安装 agent-browser:npm install -g agent-browser && agent-browser install
  2. 重新运行截图命令(与上述命令相同,runinbackground: true)
  3. 再次使用 TaskOutput(block: false)检查以确认正在运行

这确保了在您继续进行元数据分析时,截图可以在后台成功完成。



步骤 2:构建(如果需要)

从锁定文件检测包管理器,从 package.json 脚本检测构建命令。

使用 AskUserQuestion 确认:

  • - 预构建:重新构建还是使用现有输出?
  • 可构建:发布前是否构建?
  • Monorepo:要发布哪个应用?

构建完成后,后台启动截图(与步骤 1 相同的检查:使用 TaskOutput block: false 验证 agent-browser 是否可用,如果需要则安装,然后重试),然后继续执行步骤 3。



步骤 3:元数据分析

提取标题

优先级: → og:title → package.json 中的 name → 第一个 <h1> <h3>生成描述(50-150 字,故事风格)</h3> <p>涵盖:<strong>为什么</strong>(动机)→ <strong>是什么</strong>(功能)→ <strong>历程</strong>(可选)</p> <p>来源:对话历史、README.md、源代码、package.json、git 日志</p> <p>指南:<br> <ul><li>- 自然、对话式的语气</li><li>关注价值和故事,而非技术规格</li><li>避免通用的一个用 React 构建的网页应用</li></ul></p> <h3>提取 githubRepo</h3> 从 git remote 或 package.json 的 repository 字段获取。将 SSH 格式转换为 HTTPS 格式。 <h3>匹配标签</h3> <p>获取标签:node {skill_path}/scripts/utils/fetch-tags.mjs --hub {hub}<br> <table><thead><tr><th>标签类型</th><th>匹配方法</th></tr></thead><tbody><tr><td><strong>techStackTags</strong></td><td>将 package.json 依赖项与标签 slug 匹配</td></tr><tr><td><strong>platformTags</strong></td></tr></tbody></table> 从对话上下文中获取(Claude Code、Cursor 等) |<br> | <strong>modelTags</strong> | 从对话上下文中获取(Claude 3.5 Sonnet、GPT-4 等) |<br> | <strong>categoryTags</strong> | 从项目中推断(游戏库 → 游戏,图表 → 可视化) |<br> <hr><br> <h2>步骤 4:确认发布</h2></p> <p>显示元数据并使用 AskUserQuestion:</p> <p>发布到 MyVibe:<br> ──────────────────────<br> 标题:[值]</p> <p>描述:<br> [50-150 字故事]</p> <p>GitHub:[URL 或未检测到]<br> 封面图片:[如果就绪将包含]</p> <p>标签:技术栈:[...] | 平台:[...] | 分类:[...] | 模型:[...]</p> <p>选项:发布 / 编辑详情<br> <hr><br> <h2>步骤 5:执行发布</h2></p> <p><strong>检查依赖项</strong>:如果 scripts/node_modules 缺失,先运行 npm install。<br> 发布脚本自动读取截图结果文件。直接执行发布:</p> <p>通过 stdin 传递配置:</p> <p>bash<br> node {skill_path}/scripts/publish.mjs --config-stdin <<EOF<br> {<br> source: { type: dir, path: ./dist, did: z2qaXXXX },<br> hub: https://www.myvibe.so,<br> metadata: {<br> title: 我的应用,<br> description: 此处为故事描述,<br> visibility: public,<br> githubRepo: https://github.com/user/repo,<br> platformTags: [1, 2],<br> techStackTags: [3, 4],<br> categoryTags: [5],<br> modelTags: [6]<br> }<br> }<br> EOF</p> <ul><li>- did 可选 - 用于显式版本更新</li><li>coverImage 从 /tmp/myvibe-screenshot-{hash}.json 自动读取</li><li>发布后清理截图结果文件</li></ul> <hr> <h2>步骤 6:返回结果</h2> <p>发布脚本完成后,<strong>检查脚本输出</strong>中是否有以下消息:</p> <h3>成功消息</h3> 始终在回复中包含 Vibe URL: <p>发布成功!<br> 🔗 [URL]</p> <h3>升级提示(重要)</h3> 当更新现有 Vibe 但未启用版本历史时,脚本会打印升级提示: <p>📦 之前的版本已被覆盖。想要保留版本历史吗?<br> 升级到 Creator → {hub}/pricing</p> <p><strong>如果脚本输出中包含此信息,您必须在回复用户时包含此升级信息。</strong> 这有助于免费用户发现版本历史功能。<br> <hr><br> <h2>错误处理</h2></p> <p>| 错误 |</p></div> </div> <div class="tags"> <h4>标签</h4> <span class="tag">skill</span> <span class="tag">ai</span> </div> </div> </div> <div class="tab-content" id="tab-install"> <div class="install-panel"> <h3>通过对话安装</h3> <p>该技能支持在以下平台通过对话安装:</p> <div class="platform-list"> <span class="platform-tag">OpenClaw</span> <span class="platform-tag">WorkBuddy</span> <span class="platform-tag">QClaw</span> <span class="platform-tag">Kimi</span> <span class="platform-tag">Claude</span> </div> <div class="install-method"> <h4>方式一:安装 SkillHub 和技能</h4> <div class="code-block"> <button class="copy-btn" onclick="copyToClipboard('帮我安装 SkillHub 和 myvibe-skills-1776420089 技能', this)">复制</button> <code>帮我安装 SkillHub 和 myvibe-skills-1776420089 技能</code> </div> </div> <div class="install-method"> <h4>方式二:设置 SkillHub 为优先技能安装源</h4> <div class="code-block"> <button class="copy-btn" onclick="copyToClipboard('设置 SkillHub 为我的优先技能安装源,然后帮我安装 myvibe-skills-1776420089 技能', this)">复制</button> <code>设置 SkillHub 为我的优先技能安装源,然后帮我安装 myvibe-skills-1776420089 技能</code> </div> </div> <h3 style="margin-top: 30px;">通过命令行安装</h3> <div class="install-method"> <div class="code-block"> <button class="copy-btn" onclick="copyToClipboard('skillhub install myvibe-skills-1776420089', this)">复制</button> <code>skillhub install myvibe-skills-1776420089</code> </div> </div> <h3 style="margin-top: 30px;">下载</h3> <a href="plugin.php?id=hl_skillhub&mod=download&version_id=23400&token=564641cfa797dbbd12cc93ca977f3e57" class="download-btn"> ⬇ 下载 myvibe-publish v1.0.0(免费) </a> <p class="download-info"> 文件大小: 116.39 KB | 发布时间: 2026-4-17 18:25 </p> </div> </div> <div class="tab-content" id="tab-versions"> <div class="version-list"> <div class="version-item"> <div class="version-header"> <span class="version-number">v1.0.0</span> <span class="latest-tag">最新</span> <span class="version-date">2026-4-17 18:25</span> </div> <div class="changelog"> myvibe-skills v1.0.0<br /> <br /> - Initial release of the MyVibe Publish skill.<br /> - Allows publishing static HTML, ZIP archives, or directories to MyVibe.<br /> - Supports publishing from file, directory, or URL with optional metadata extraction, git integration, and screenshot generation.<br /> - Provides automated project type detection (static, buildable, monorepo) and smart workflow (build, analyze, confirm, publish).<br /> - Includes advanced options for visibility, updating specific Vibes, and import from external URLs.<br /> - Guides users through error handling and upgrade prompts for version history features. </div> </div> </div> </div> <!-- 推荐技能 --> <div class="related-skills"> <h3>相关推荐</h3> <div class="skill-list-related"> <div class="skillhub-card-related"> <a href="plugin.php?id=hl_skillhub&mod=detail&slug=self-improving-agent-1776396682"> <div class="skill-icon"> <div class="default-icon">s</div> </div> <h3 class="skill-name">self-improvement</h3> <p class="skill-desc">Captures learnings, errors, and corrections to enable continuous improvement. Use when: (1) A command or operation fails unexpectedly, (2) User corrects Claude ('No, that's wrong...', 'Actually...'), (3) User requests a capability that doesn't exist, (4) An external API or tool fails, (5) Claude realizes its knowledge is outdated or incorrect, (6) A better approach is discovered for a recurring task. Also review learnings before major tasks.</p> <div class="skill-meta"> <div class="stats"> <span>⭐ 3209</span> <span>⬇ 392958</span> </div> <span class="skill-source">AI智能</span> </div> </a> </div> <div class="skillhub-card-related"> <a href="plugin.php?id=hl_skillhub&mod=detail&slug=self-improving-agent-1776382578"> <div class="skill-icon"> <div class="default-icon">s</div> </div> <h3 class="skill-name">self-improvement</h3> <p class="skill-desc">Captures learnings, errors, and corrections to enable continuous improvement. Use when: (1) A command or operation fails unexpectedly, (2) User corrects Claude ('No, that's wrong...', 'Actually...'), (3) User requests a capability that doesn't exist, (4) An external API or tool fails, (5) Claude realizes its knowledge is outdated or incorrect, (6) A better approach is discovered for a recurring task. Also review learnings before major tasks.</p> <div class="skill-meta"> <div class="stats"> <span>⭐ 3209</span> <span>⬇ 392957</span> </div> <span class="skill-source">AI智能</span> </div> </a> </div> <div class="skillhub-card-related"> <a href="plugin.php?id=hl_skillhub&mod=detail&slug=self-improving-agent-1776282374"> <div class="skill-icon"> <div class="default-icon">s</div> </div> <h3 class="skill-name">self-improvement</h3> <p class="skill-desc">Captures learnings, errors, and corrections to enable continuous improvement. Use when: (1) A command or operation fails unexpectedly, (2) User corrects Claude ('No, that's wrong...', 'Actually...'), (3) User requests a capability that doesn't exist, (4) An external API or tool fails, (5) Claude realizes its knowledge is outdated or incorrect, (6) A better approach is discovered for a recurring task. Also review learnings before major tasks.</p> <div class="skill-meta"> <div class="stats"> <span>⭐ 3195</span> <span>⬇ 389589</span> </div> <span class="skill-source">AI智能</span> </div> </a> </div> <div class="skillhub-card-related"> <a href="plugin.php?id=hl_skillhub&mod=detail&slug=self-improving-agent-1776190579"> <div class="skill-icon"> <div class="default-icon">s</div> </div> <h3 class="skill-name">self-improvement</h3> <p class="skill-desc">Captures learnings, errors, and corrections to enable continuous improvement. Use when: (1) A command or operation fails unexpectedly, (2) User corrects Claude ('No, that's wrong...', 'Actually...'), (3) User requests a capability that doesn't exist, (4) An external API or tool fails, (5) Claude realizes its knowledge is outdated or incorrect, (6) A better approach is discovered for a recurring task. Also review learnings before major tasks.</p> <div class="skill-meta"> <div class="stats"> <span>⭐ 3177</span> <span>⬇ 386644</span> </div> <span class="skill-source">AI智能</span> </div> </a> </div> </div> </div> </div> </div> <style> .skill-detail { padding: 20px 0; min-height: 100vh; } .breadcrumb { margin-bottom: 20px; color: #666; } .breadcrumb a { color: #155BD5; } .breadcrumb span { margin: 0 5px; } .skill-detail-header { display: flex; gap: 24px; padding: 30px; background: #fff; border-radius: 12px; margin-bottom: 20px; border: 1px solid #e8e8e8; } .skill-icon-large { width: 120px; height: 120px; flex-shrink: 0; } .skill-icon-large img { width: 100%; height: 100%; border-radius: 20px; object-fit: cover; } .skill-icon-large .default-icon-large { width: 100%; height: 100%; border-radius: 20px; background: #155BD5; color: #fff; display: flex; align-items: center; justify-content: center; font-size: 48px; font-weight: bold; } .skill-info { flex: 1; } .skill-header-action { flex-shrink: 0; display: flex; align-items: center; padding-left: 20px; } .header-download-btn { display: inline-flex; align-items: center; gap: 8px; padding: 12px 24px; background: #155BD5; color: #fff; border-radius: 8px; text-decoration: none; font-size: 14px; font-weight: 500; transition: all 0.2s ease; white-space: nowrap; } .header-download-btn:hover { background: #0d4bb5; transform: translateY(-1px); box-shadow: 0 4px 12px rgba(21, 91, 213, 0.3); } .header-download-btn.buy { background: #f97316; } .header-download-btn.buy:hover { background: #ea580c; box-shadow: 0 4px 12px rgba(249, 115, 22, 0.3); } .skill-info h1 { font-size: 36px; font-weight: 700; color: #1e293b; margin-bottom: 10px; display: flex; align-items: center; flex-wrap: wrap; gap: 12px; } .skill-info h1 .name-cn { font-size: 20px; color: #666; font-weight: 500; background: #f1f5f9; padding: 4px 14px; border-radius: 20px; white-space: nowrap; } .skill-info .skill-desc { font-size: 16px; color: #666; margin-bottom: 8px; } .skill-info .skill-scenarios { font-size: 14px; color: #999; margin-bottom: 10px; } .skill-info .skill-author { font-size: 13px; color: #999; } /* 统计面板 */ .stats-panel { display: flex; align-items: center; background: #fff; border-radius: 12px; padding: 24px 0; margin-bottom: 24px; border: 1px solid #e8e8e8; box-shadow: 0 1px 3px rgba(0,0,0,0.05); } .stats-panel .stats-item { flex: 1; text-align: center; padding: 0 16px; } .stats-panel .stats-divider { width: 1px; height: 48px; background: linear-gradient(180deg, transparent, #e8e8e8, transparent); } .stats-panel .stats-icon { width: 40px; height: 40px; margin: 0 auto 8px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 18px; background: #f1f5f9; color: #64748b; } .stats-panel .stats-icon.source-icon { background: #e0e7ff; color: #6366f1; } .stats-panel .stats-icon.version-icon { background: #fef3c7; color: #d97706; } .stats-panel .stats-icon.security-icon { background: #fee2e2; color: #9ca3af; } .stats-panel .stats-icon.security-icon.verified { background: #d1fae5; color: #10b981; } .stats-panel .stats-value { font-size: 15px; font-weight: 600; color: #374151; margin-bottom: 4px; } .stats-panel .stats-number { font-size: 24px; font-weight: 700; color: #111827; margin-bottom: 4px; line-height: 1.2; } .stats-panel .stats-label { font-size: 13px; color: #9ca3af; } .stats-panel .stats-item.highlight .stats-label { color: #6b7280; } .skill-tabs { display: flex; gap: 40px; border-bottom: 1px solid #e8e8e8; margin-bottom: 20px; } .skill-tabs .tab-item { padding: 15px 0; color: #666; cursor: pointer; border-bottom: 2px solid transparent; font-size: 16px; } .skill-tabs .tab-item.active { color: #155BD5; border-bottom-color: #155BD5; } .tab-content { background: #fff; border-radius: 12px; padding: 30px; margin-bottom: 20px; border: 1px solid #e8e8e8; opacity: 0; transform: translateY(10px); transition: all 0.3s ease; display: none; } .tab-content.active { opacity: 1; transform: translateY(0); display: block; } .lang-switcher { display: flex; gap: 8px; margin-bottom: 16px; justify-content: flex-end; } .lang-switcher .lang-btn { padding: 4px 16px; border: 1px solid #d1d5db; background: #fff; border-radius: 20px; font-size: 13px; color: #6b7280; cursor: pointer; transition: all 0.2s; } .lang-switcher .lang-btn:hover { border-color: #155BD5; color: #155BD5; } .lang-switcher .lang-btn.active { background: #155BD5; color: #fff; border-color: #155BD5; } .overview-content h3 { margin-bottom: 15px; } /* Markdown 预览样式 */ .markdown-body { line-height: 1.8; color: #333; margin-bottom: 20px; } .markdown-body h1, .markdown-body h2, .markdown-body h3, .markdown-body h4, .markdown-body h5, .markdown-body h6 { margin-top: 24px; margin-bottom: 16px; font-weight: 600; line-height: 1.25; color: #1e293b; } .markdown-body h1 { font-size: 2em; border-bottom: 1px solid #e8e8e8; padding-bottom: 8px; } .markdown-body h2 { font-size: 1.5em; border-bottom: 1px solid #e8e8e8; padding-bottom: 8px; } .markdown-body h3 { font-size: 1.25em; } .markdown-body p { margin-bottom: 16px; } .markdown-body ul, .markdown-body ol { padding-left: 2em; margin-bottom: 16px; } .markdown-body li { margin-bottom: 4px; } .markdown-body code { padding: 2px 6px; background: #f1f5f9; border-radius: 4px; font-family: 'Consolas', monospace; font-size: 0.9em; color: #155BD5; } .markdown-body pre { padding: 16px; background: #1e1e1e; border-radius: 8px; overflow-x: auto; margin-bottom: 16px; } .markdown-body pre code { background: transparent; color: #d4d4d4; padding: 0; } .markdown-body blockquote { padding: 0 1em; border-left: 4px solid #155BD5; color: #666; margin-bottom: 16px; } .markdown-body table { width: 100%; border-collapse: collapse; margin-bottom: 16px; } .markdown-body th, .markdown-body td { padding: 8px 12px; border: 1px solid #e8e8e8; } .markdown-body th { background: #f8f9fa; font-weight: 600; } .markdown-body a { color: #155BD5; text-decoration: none; } .markdown-body a:hover { text-decoration: underline; } .markdown-body img { max-width: 100%; border-radius: 8px; } .overview-content .tags { margin-top: 20px; } .overview-content .tags h4 { margin-bottom: 10px; } .overview-content .tag { display: inline-block; padding: 4px 12px; background: #f0f0f0; border-radius: 4px; margin-right: 8px; margin-bottom: 8px; font-size: 13px; } .install-panel h3 { margin-bottom: 15px; } .platform-list { margin-bottom: 20px; } .platform-tag { display: inline-block; padding: 4px 12px; background: #e3f2fd; color: #1976d2; border-radius: 4px; margin-right: 8px; font-size: 13px; } .install-method { margin-bottom: 25px; } .install-method h4 { margin-bottom: 10px; font-size: 14px; color: #666; } .code-block { position: relative; background: #1e1e1e; border-radius: 8px; padding: 16px 60px 16px 16px; } .code-block code { color: #d4d4d4; font-family: 'Consolas', monospace; font-size: 14px; } .copy-btn { position: absolute; right: 12px; top: 50%; transform: translateY(-50%); padding: 4px 12px; background: #333; border: none; border-radius: 4px; color: #fff; cursor: pointer; font-size: 12px; } .copy-btn:hover { background: #444; } .copy-btn.copied { background: #10b981 !important; animation: copyPulse 0.3s ease; } @keyframes copyPulse { 0%, 100% { transform: translateY(-50%) scale(1); } 50% { transform: translateY(-50%) scale(1.1); } } .download-btn { display: inline-block; padding: 12px 24px; background: #155BD5; color: #fff; border-radius: 8px; text-decoration: none; font-size: 14px; } .download-btn:hover { background: #0d4bb5; } .download-info { margin-top: 10px; font-size: 13px; color: #999; } .version-list .version-item { padding: 20px 0; border-bottom: 1px solid #e8e8e8; } .version-list .version-item:last-child { border-bottom: none; } .version-header { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; } .version-header .version-number { font-size: 18px; font-weight: 600; } .version-header .latest-tag { padding: 2px 8px; background: #e8f5e9; color: #4caf50; border-radius: 4px; font-size: 12px; } .version-header .version-date { margin-left: auto; color: #999; font-size: 13px; } .changelog { color: #666; line-height: 1.6; } /* 相关推荐 */ .related-skills { margin-top: 40px; padding: 24px; background: #fff; border-radius: 12px; border: 1px solid #e8e8e8; } .related-skills h3 { margin-bottom: 20px; font-size: 18px; font-weight: 600; color: #1e293b; display: flex; align-items: center; gap: 8px; } .related-skills h3:before { content: ''; width: 4px; height: 20px; background: #155BD5; border-radius: 2px; } .skill-list-related { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 20px; } .skillhub-card-related { border-radius: 16px; padding: 20px; transition: all 0.3s ease; background: rgba(255, 255, 255, 0.95); backdrop-filter: blur(10px); border: 1px solid rgba(0, 0, 0, 0.08); box-shadow: 0 1px 3px rgba(0,0,0,0.05), 0 4px 12px rgba(0,0,0,0.03); } .skillhub-card-related:hover { box-shadow: 0 8px 24px rgba(21, 91, 213, 0.15); transform: translateY(-4px); } .skillhub-card-related:active { transform: scale(0.98); } .skillhub-card-related a { color: inherit; text-decoration: none; } .skillhub-card-related .skill-icon { width: 56px; height: 56px; margin-bottom: 12px; } .skillhub-card-related .skill-icon .default-icon { width: 100%; height: 100%; border-radius: 12px; background: #155BD5; color: #fff; display: flex; align-items: center; justify-content: center; font-size: 24px; font-weight: bold; } .skillhub-card-related .skill-name { font-size: 16px; font-weight: 600; margin-bottom: 8px; color: #333; } .skillhub-card-related .skill-desc { font-size: 13px; color: #666; line-height: 1.5; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; margin-bottom: 12px; min-height: 39px; } .skillhub-card-related .skill-meta { display: flex; justify-content: space-between; align-items: center; font-size: 12px; color: #999; } .skillhub-card-related .skill-meta .stats { display: flex; gap: 12px; } .skillhub-card-related .skill-source { background: #f0f0f0; padding: 2px 10px; border-radius: 12px; font-size: 12px; } @media screen and (max-width: 768px) { .skill-detail-header { flex-direction: column; text-align: center; padding: 24px 20px; } .skill-icon-large { width: 80px; height: 80px; } .skill-icon-large .default-icon-large { font-size: 32px; } .skill-info h1 { font-size: 24px; } .skill-info h1 .name-cn { font-size: 14px; padding: 2px 10px; margin-left: 0; margin-top: 6px; } .skill-header-action { padding-left: 0; padding-top: 16px; width: 100%; justify-content: center; } .header-download-btn { width: 100%; justify-content: center; max-width: 280px; } .stats-panel { flex-wrap: wrap; padding: 16px 0; } .stats-panel .stats-item { flex: 1 1 30%; min-width: 80px; padding: 12px 8px; } .stats-panel .stats-divider { width: 1px; height: 36px; } .stats-panel .stats-icon { width: 32px; height: 32px; font-size: 14px; } .stats-panel .stats-number { font-size: 18px; } .stats-panel .stats-value { font-size: 13px; } .stats-panel .stats-label { font-size: 11px; } .skill-tabs { overflow-x: auto; gap: 24px; -webkit-overflow-scrolling: touch; } .skill-tabs .tab-item { white-space: nowrap; } .code-block { padding: 16px 50px 16px 16px; } .code-block code { font-size: 12px; word-break: break-all; } } /* Paid skill notice */ .paid-notice { text-align: center; padding: 40px 24px; background: linear-gradient(135deg, #fff7ed, #ffedd5); border-radius: 12px; border: 1px solid #fed7aa; } .paid-notice-icon { width: 56px; height: 56px; margin: 0 auto 16px; background: #fff; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 28px; color: #f97316; box-shadow: 0 2px 8px rgba(249,115,22,0.15); } .paid-notice h3 { font-size: 20px; color: #9a3412; margin-bottom: 8px; } .paid-notice p { font-size: 14px; color: #c2410c; margin: 4px 0; } .paid-buy-box { padding: 20px; background: #fff7ed; border-radius: 8px; border: 1px solid #fed7aa; margin-bottom: 12px; } .paid-buy-box p { color: #7c2d12; font-size: 15px; margin: 0; }</style> <script> // 复制功能 function copyToClipboard(text, btn) { if (navigator.clipboard && navigator.clipboard.writeText) { navigator.clipboard.writeText(text).then(function() { showCopied(btn); }).catch(function() { fallbackCopy(text, btn); }); } else { fallbackCopy(text, btn); } } function fallbackCopy(text, btn) { var textarea = document.createElement('textarea'); textarea.value = text; textarea.style.position = 'fixed'; textarea.style.opacity = '0'; document.body.appendChild(textarea); textarea.select(); try { document.execCommand('copy'); showCopied(btn); } catch (err) { btn.textContent = '失败'; } document.body.removeChild(textarea); } function showCopied(btn) { var originalText = btn.textContent; btn.textContent = '已复制!'; btn.classList.add('copied'); setTimeout(function() { btn.textContent = originalText; btn.classList.remove('copied'); }, 2000); } // Tab 切换 document.addEventListener('DOMContentLoaded', function() { var tabItems = document.querySelectorAll('.skill-tabs .tab-item'); var tabContents = document.querySelectorAll('.tab-content'); tabItems.forEach(function(item) { item.addEventListener('click', function() { var target = this.getAttribute('data-tab'); var targetContent = document.getElementById('tab-' + target); // 移除所有 active tabItems.forEach(function(t) { t.classList.remove('active'); }); tabContents.forEach(function(c) { c.classList.remove('active'); }); // 添加 active this.classList.add('active'); // 延迟添加动画类,确保过渡效果 setTimeout(function() { targetContent.classList.add('active'); }, 50); window.location.hash = target; }); }); var hash = window.location.hash.replace('#', ''); if (hash) { var targetTab = document.querySelector('.skill-tabs .tab-item[data-tab="' + hash + '"]'); if (targetTab) { targetTab.click(); } } // 中英文描述切换 var langSwitcher = document.getElementById('langSwitcher'); if (langSwitcher) { var descEn = document.querySelector('#markdownContent .desc-en'); var descCn = document.querySelector('#markdownContent .desc-cn'); var toggleBtn = document.getElementById('langToggleBtn'); var currentLang = 'cn'; toggleBtn.addEventListener('click', function() { if (currentLang === 'en') { currentLang = 'cn'; toggleBtn.textContent = 'English'; if (descEn) descEn.style.display = 'none'; if (descCn) descCn.style.display = 'block'; } else { currentLang = 'en'; toggleBtn.textContent = '中文'; if (descCn) descCn.style.display = 'none'; if (descEn) descEn.style.display = 'block'; } }); } }); </script></div> <script src="source/plugin/hl_skillhub/static/js/main.js"></script><div style="height:299px; overflow:hidden" class="cl"> <div class="hl_footer cl"> <div class="hl_fttop cl"> <div class="w1180 cl"> <div class="hl_ftl" style=" position: relative;"> <ul> <li> <div class="hl_h5">闲社论坛</div> <a href="category-43.html" target="_blank">关于我们</a> <a href="/vip/" target="_blank">会员介绍</a> <a href="forum-99-1.html">开通会员</a> <a href="forum-98-1.html" target="_blank">羊毛论坛</a> </li> <li> <div class="hl_h5">闲社论坛</div> <a href="category-43.html" target="_blank">羊毛交流论坛</a> <a href="/vip/" target="_blank">线报讨论社区</a> <a href="forum-99-1.html">优惠分享交流</a> <a href="forum-98-1.html" target="_blank">线报更新服务</a> </li> <li> <div class="hl_h5">网站服务</div> <a href="https://wpa.qq.com/msgrd?v=3&uin=515151560&site=qq&menu=yes" target="_blank" rel="nofollow">会员咨询:515151560</a> <a href="https://wpa.qq.com/msgrd?v=3&uin=515151570&site=qq&menu=yes" target="_blank" rel="nofollow">广告合作:515151570</a> <a href="https://wpa.qq.com/msgrd?v=3&uin=515151580&site=qq&menu=yes" target="_blank" rel="nofollow">投诉建议:515151580</a> <a href="https://wpa.qq.com/msgrd?v=3&uin=515151590&site=qq&menu=yes" target="_blank" rel="nofollow">售后指导:515151590</a> </li> <div class="clear"></div> </ul> <p style="font-size: 16px;color: #fff;width: 370px;text-align: center;margin-top: 5px;position: absolute; left:0px; bottom:0px"> 多链集团旗下-闲社网</p> </div> <div class="hl_ftm"> <div class="hl_h5">闲社网热线 </div> <div class="hl_h2">免费联系电话 </div> <div class="hl_fttel"> 0527-80111111 </div> <h6 class="cl mtm hl_time"><a href="http://wpa.b.qq.com/cgi/wpa.php?ln=1&key=XzkzODA1MTM1NF80NjQ5NDZfNDAwMDgwOTkxMV8yXw" target="_blank" rel="nofollow"><img src="template/xianshe/neoconex/qqline.png"></a>            <a href="http://wpa.b.qq.com/cgi/wpa.php?ln=1&key=XzkzODA1MTM1NF80NjQ5NDZfNDAwMDgwOTkxMV8yXw" target="_blank" rel="nofollow"><img alt="qqline" title="qqline" src="template/xianshe/neoconex/qqline.png"></a></h6> <p class="hl_time">服务时间:周一到周日 8:00-24:00</p> </div> <div class="hl_ftl"> <ul> <li> <div class="hl_h5">公众号</div> <span style="font-size:18px;color: #fff;display: block;">闲社</span> <span style="font-size:18px;color: #fff;">闲社线报社区</span> </li> <div class="clear"></div> </ul> </div> <div class="hl_ftr"> <div class="hl_h5">关注闲社网</div> <div class="hl_guznzhuxx"> <ul> <li> <img alt="wxkf" title="wxkf" src="template/xianshe/neoconex/wxkf.jpg"> <p>闲社在线客服</p> </li> <li> <img alt="wx" title="wx" src="template/xianshe/neoconex/wx.jpg"> <p>关注闲社网微信</p> </li> <li style=" margin-right: 0;"> <img alt="app" title="app" src="template/xianshe/neoconex/app.png"> <p>闲社网APP</p> </li> <div class="clear"></div> </ul> </div> </div> <div class="clear"></div> </div> </div> </div> <div class="hl_ftbottom"> <div class="w1180 cl"> <div class="hl_ftblt"> <p> <a href="archiver/" rel="nofollow">Archiver</a><span>·</span><a href="forum.php?mobile=yes" rel="nofollow">手机版</a><span>·</span><span>闲社网·闲社论坛·羊毛社区· 多链控股集团有限公司</span> <span>·</span> <a href="http://beian.miit.gov.cn/" target="_blank" rel="nofollow">苏ICP备2025199260号-1</a></p> <p> Powered by <a href="http://www.discuz.net" target="_blank" rel="nofollow">Discuz!</a> <em>X5.0</em>   © 2024-2025 <a href="https://www.xianshe.com/" target="_blank">闲社网·线报更新论坛·羊毛分享社区·http://xianshe.com</a> </p> </div> <div class="hl_ftrgh"> <a id="_pingansec_bottomimagelarge_p2p" rel="nofollow" href="https://kashen.com/d/?z6"><img alt="p2p_official_large" title="p2p_official_large" src="template/xianshe/neoconex/p2p_official_large.jpg" /></a> </div> <div class="clear"></div> </div> </div> </div> <div id="scrolltop"> <span hidefocus="true"><a title="返回顶部" onclick="window.scrollTo('0','0')" class="scrolltopa"><b>返回顶部</b></a></span> </div> <script type="text/javascript">_attachEvent(window, 'scroll', function () { showTopLink(); }); checkBlind();</script> </body> </html>