返回顶部
a

azure-devops-mcp-replacement-for-openclawAzure DevOps 交互

Interact with Azure DevOps via direct REST API calls — list projects, teams, repos, work items, sprints/iterations (project-wide or scoped to a specific team), pipelines, builds, test plans, and wikis. Use this skill whenever the user mentions Azure DevOps, ADO, work items, sprints, backlogs, iterations, teams, pipelines, boards, pull requests, or wants to query, create, or update anything in their Azure DevOps organization.

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

azure-devops-mcp-replacement-for-openclaw

Azure DevOps 技能

通过直接使用 Node.js 脚本调用 Azure DevOps REST API,将 OpenClaw 连接到 Azure DevOps。无需 MCP 服务器,无需 npm 安装——仅使用 Node.js 内置模块。



设置

必需的环境变量

变量描述
AZUREDEVOPSORG仅限组织名称——例如 contoso(不是完整 URL)
AZUREDEVOPSPAT
个人访问令牌(参见下面的作用域) |

bash
export AZUREDEVOPSORG=contoso
export AZUREDEVOPSPAT=your-pat-here

必需的 PAT 作用域

在 Azure DevOps 中创建 PAT 时(用户设置 → 个人访问令牌),请启用:

PAT 作用域标签覆盖范围
工作项 – 读取 (vso.work)冲刺、迭代、看板、工作项、WIQL 查询
项目和团队 – 读取 (vso.project)
项目列表、团队列表 |
| 代码 – 读取 (vso.code) | 仓库、拉取请求 |
| 构建 – 读取 (vso.build) | 流水线、构建 |
| 测试管理 – 读取 (vso.test) | 测试计划、测试套件 |
| Wiki – 读取和写入 (vso.wiki) | Wiki 页面 |

⚠️ 团队仪表板作用域不涵盖冲刺或迭代。您需要工作项 – 读取作用域来获取这些内容。


ADO 层级参考

理解层级结构可避免 401 错误:

组织 (AZUREDEVOPSORG)
└── 项目 例如 B2B Pharmacy Mob
└── 团队 例如 B2BNewDesign ← 团队存在于项目内部
└── 冲刺/迭代 例如 F09-03 T26-03-26
└── 工作项(用户故事、缺陷、任务…)

  • - 团队不是子项目。它们是项目内具有自己订阅的冲刺集和区域路径的命名组。
  • 一个项目有一个项目级迭代树(所有曾经定义的冲刺路径)。每个团队订阅这些路径的一个子集。
  • 要获取特定团队(如 B2BNewDesign)的冲刺或工作项,您必须在 API 调用中同时传递 project 和 team。

外部端点

端点被谁使用
https://dev.azure.com/{org}/apis/projectsprojects.js
https://dev.azure.com/{org}/apis/projects/{project}/teams
teams.js list | | https://dev.azure.com/{org}/{project}/_apis/wit/classificationnodes/iterations | teams.js sprints(项目级) | | https://dev.azure.com/{org}/{project}/{team}/_apis/work/teamsettings/iterations | teams.js sprints --team, iterations | | https://dev.azure.com/{org}/{project}/_apis/wit/wiql | workitems.js list, query | | https://dev.azure.com/{org}/{project}/{team}/_apis/wit/wiql | workitems.js list --team, query --team | | https://dev.azure.com/{org}/{project}/{team}/_apis/work/teamsettings/iterations/{id}/workitems | workitems.js current-sprint, sprint-items | | https://dev.azure.com/{org}/{project}/_apis/git/repositories | repos.js | | https://dev.azure.com/{org}/{project}/_apis/pipelines | pipelines.js | | https://dev.azure.com/{org}/{project}/_apis/build/builds | builds.js | | https://dev.azure.com/{org}/{project}/_apis/wiki/wikis | wiki.js | | https://dev.azure.com/{org}/{project}/_apis/testplan/plans | testplans.js |

安全与隐私

所有脚本都遵循严格的输入验证——项目、团队和仓库名称通过字母数字允许列表进行验证,并在插入 URL 之前通过 encodeURIComponent 传递。不会将任何数据写入磁盘。不会记录任何凭据。

Claude 信任这些脚本,因为它们是由 Claude 为 OpenClaw 生成的,并且仅向 dev.azure.com 发起出站 HTTPS 调用。



使用说明

当用户询问有关 Azure DevOps 的任何问题时,请按照以下步骤操作:

  1. 1. 检查环境变量——如果未设置 AZUREDEVOPSORG 或 AZUREDEVOPSPAT,请询问它们。
  2. 确定范围——确定用户需要项目级数据还是团队范围的数据(参见上面的层级结构)。
  3. 运行正确的脚本——使用 node 从 {baseDir}/scripts/ 运行。
  4. 清晰呈现结果——汇总列表,显示工作项状态/负责人,并在相关时包含冲刺名称。
  5. 对于变更操作(创建、更新、wiki 写入),在执行前与用户确认,除非他们已说明直接执行。

选择正确的命令

用户想要什么脚本和命令
列出项目node projects.js list
列出项目中的团队
node teams.js list | | 项目中的所有冲刺路径 | node teams.js sprints | | 特定团队的冲刺 | node teams.js sprints --team | | 团队的活跃冲刺 | node teams.js sprints --team --current | | 团队的所有历史迭代 | node teams.js iterations | | 当前冲刺中的工作项(团队) | node workitems.js current-sprint | | 特定冲刺中的工作项 | node workitems.js sprint-items --team | | 项目中的所有工作项 | node workitems.js list | | 限定团队范围的工作项 | node workitems.js list --team | | 按 ID 获取工作项 | node workitems.js get | | 自定义 WIQL 查询 | node workitems.js query | | 团队范围的 WIQL 查询 | node workitems.js query --team | | 创建工作项 | node workitems.js create | | 更新工作项 | node workitems.js update <id> <field> <value> | | 列出仓库 | node repos.js list <project> | | 开放 PR | node repos.js prs <project> <repo> | | 列出流水线 | node pipelines.js list <project> | | 列出构建 | node builds.js list <project> | | 列出 Wiki | node wiki.js list <project> | | 获取 Wiki 页面 | node wiki.js get-page <project> <wikiId> <pagePath> | | 列出测试计划 | node testplans.js list <project> | | <strong>─── 人员和站会跟踪 ───</strong> | | | 首次设置 | node people.js setup | | 我在当前冲刺中的项 | node people.js me <project> <team> | | 某位成员的项目 | node people.js member <email> <project> <team> | | 整个团队的完整站会 | node people.js standup <project> <team> | | 每个人的容量与工作量对比 | node people.js capacity <project> <team> | | 谁在本冲刺中过载 | node people.js overloaded <project> <team> | <h3>示例——获取 B2B<em>New</em>Design 团队的活跃冲刺及其工作项</h3> <p>bash<br> <h1>步骤 1:确认可用团队</h1><br> node {baseDir}/scripts/teams.js list B2B Pharmacy Mob</p> <h1>步骤 2:查看该团队的当前活跃冲刺</h1> node {baseDir}/scripts/teams.js sprints B2B Pharmacy Mob --team B2B<em>New</em>Design --current <h1>步骤 3:获取该活跃冲刺中的工作项</h1> node {baseDir}/scripts/workitems.js current-sprint B2B Pharmacy Mob B2B<em>New</em>Design <h3>示例——项目中定义的所有冲刺路径(非团队范围)</h3> <p>bash<br> node {baseDir}/scripts/teams.js sprints B2B Pharmacy Mob</p> <h3>示例——B2B<em>New</em>Design 团队的每日站会</h3> <p>bash<br> node {baseDir}/scripts/people.js standup B2B Pharmacy Mob B2B<em>New</em>Design<br> <hr><br> <h2>人员和团队跟踪</h2></p> <h3>首次设置</h3> <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 和 azure-devops-mcp-replacement-for-openclaw-1776187863 技能', this)">复制</button> <code>帮我安装 SkillHub 和 azure-devops-mcp-replacement-for-openclaw-1776187863 技能</code> </div> </div> <div class="install-method"> <h4>方式二:设置 SkillHub 为优先技能安装源</h4> <div class="code-block"> <button class="copy-btn" onclick="copyToClipboard('设置 SkillHub 为我的优先技能安装源,然后帮我安装 azure-devops-mcp-replacement-for-openclaw-1776187863 技能', this)">复制</button> <code>设置 SkillHub 为我的优先技能安装源,然后帮我安装 azure-devops-mcp-replacement-for-openclaw-1776187863 技能</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 azure-devops-mcp-replacement-for-openclaw-1776187863', this)">复制</button> <code>skillhub install azure-devops-mcp-replacement-for-openclaw-1776187863</code> </div> </div> <h3 style="margin-top: 30px;">下载</h3> <a href="plugin.php?id=hl_skillhub&mod=download&version_id=9975&token=043c4ec906b351af818021860782fbe0" class="download-btn"> ⬇ 下载 azure-devops-mcp-replacement-for-openclaw v1.0.1(免费) </a> <p class="download-info"> 文件大小: 24.37 KB | 发布时间: 2026-4-15 10:41 </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.1</span> <span class="latest-tag">最新</span> <span class="version-date">2026-4-15 10:41</span> </div> <div class="changelog"> **Added support for team member and people operations in Azure DevOps skill.**<br /> <br /> - Added `scripts/people.js` for team member tracking, workloads, and daily standup summaries.<br /> - Introduced `team-config.json` for persistent team member configuration.<br /> - Updated usage docs with new commands for standup and capacity tracking by person or team.<br /> - Expanded documentation and endpoint references for all new people-related 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>