feat: 着陆页加 Windows 安装命令 + PowerShell 安装脚本

- 新增 install.ps1(与 install.sh 功能对等)
- 着陆页 Step 1 加 macOS/Linux 和 Windows Tab 切换
- SVG 图标美化 Tab 按钮
This commit is contained in:
lidf 2026-04-07 08:30:27 +08:00
parent f370632809
commit aaa938ad45
2 changed files with 1150 additions and 0 deletions

170
agent/install.ps1 Normal file
View File

@ -0,0 +1,170 @@
# 黑手党提案 Agent — Windows 一键安装/更新脚本 (PowerShell)
# 用法: irm https://git.brainwork.club/lidf/chanpinhsd/archive/main.zip -OutFile $env:TEMP\mafia.zip; Expand-Archive $env:TEMP\mafia.zip $env:TEMP\mafia -Force; & $env:TEMP\mafia\chanpinhsd\agent\install.ps1
$ErrorActionPreference = "Stop"
function Write-Info($msg) { Write-Host "[mafia] $msg" -ForegroundColor Green }
function Write-Warn($msg) { Write-Host "[mafia] $msg" -ForegroundColor Yellow }
function Write-Err($msg) { Write-Host "[mafia] $msg" -ForegroundColor Red; exit 1 }
$COPAW_HOME = if ($env:COPAW_HOME) { $env:COPAW_HOME } else { Join-Path $env:USERPROFILE ".copaw" }
$AGENT_ID = "mafia-expert"
$WORKSPACE_DIR = Join-Path $COPAW_HOME "workspaces\$AGENT_ID"
$SCRIPT_DIR = Split-Path -Parent $MyInvocation.MyCommand.Path
# ── 检查 CoPaw ────────────────────────────────────────────────────────
if (-not (Test-Path (Join-Path $COPAW_HOME "config.json"))) {
Write-Err "CoPaw 未安装。请先安装 CoPaw 桌面客户端https://copaw.agentscope.io"
}
Write-Info "CoPaw 已就绪"
# ── 创建工作区 ─────────────────────────────────────────────────────────
Write-Info "配置 $AGENT_ID 工作区..."
$dirs = @("skills", "cases", "iteration_reports", "memory")
foreach ($d in $dirs) {
$p = Join-Path $WORKSPACE_DIR $d
if (-not (Test-Path $p)) { New-Item -ItemType Directory -Path $p -Force | Out-Null }
}
# ── 核心配置 ───────────────────────────────────────────────────────────
$coreFiles = @("AGENTS.md", "SOUL.md", "PROFILE.md", "HEARTBEAT.md", "agent.json")
foreach ($f in $coreFiles) {
$src = Join-Path $SCRIPT_DIR $f
if (Test-Path $src) { Copy-Item $src (Join-Path $WORKSPACE_DIR $f) -Force }
}
# MEMORY.md 只在首次创建
$memPath = Join-Path $WORKSPACE_DIR "MEMORY.md"
if (-not (Test-Path $memPath)) {
$memSrc = Join-Path $SCRIPT_DIR "MEMORY.md"
if (Test-Path $memSrc) { Copy-Item $memSrc $memPath }
else { Set-Content $memPath "# 黑手党提案专家长期记忆" -Encoding UTF8 }
}
# ── Skills每次全量覆盖 ─────────────────────────────────────────────
$skillsSrc = Join-Path $SCRIPT_DIR "skills"
if (Test-Path $skillsSrc) {
Get-ChildItem $skillsSrc -Directory | ForEach-Object {
if ($_.Name -eq "mafia_agent_installer") { return }
$target = Join-Path $WORKSPACE_DIR "skills\$($_.Name)"
if (-not (Test-Path $target)) { New-Item -ItemType Directory -Path $target -Force | Out-Null }
Copy-Item "$($_.FullName)\*" $target -Force -Recurse 2>$null
}
}
Write-Info "文件复制完成"
# ── 合并 skill.json ────────────────────────────────────────────────────
Write-Info "注册自定义 Skills..."
$wsSkillJson = Join-Path $WORKSPACE_DIR "skill.json"
$repoSkillJson = Join-Path $SCRIPT_DIR "skill.json"
$pyScript = @"
import json, os, time
ws_skill = r'$wsSkillJson'
repo_skill = r'$repoSkillJson'
if os.path.exists(ws_skill):
with open(ws_skill, encoding='utf-8') as f:
manifest = json.load(f)
else:
manifest = {'schema_version': 'workspace-skill-manifest.v1', 'version': 0, 'skills': {}}
if os.path.exists(repo_skill):
with open(repo_skill, encoding='utf-8') as f:
repo = json.load(f)
for name, skill_cfg in repo.get('skills', {}).items():
manifest['skills'][name] = skill_cfg
print(f' + {name}')
skills_dir = os.path.join(r'$WORKSPACE_DIR', 'skills')
if os.path.isdir(skills_dir):
for d in os.listdir(skills_dir):
if d.startswith('.'):
continue
skill_md = os.path.join(skills_dir, d, 'SKILL.md')
if os.path.exists(skill_md) and d not in manifest['skills']:
manifest['skills'][d] = {
'enabled': True,
'channels': ['all'],
'source': 'customized',
'metadata': {
'name': d,
'description': '',
'version_text': '1.0.0',
'source': 'customized',
'protected': False,
'requirements': {'require_bins': [], 'require_envs': []},
},
'requirements': {'require_bins': [], 'require_envs': []},
}
print(f' + {d} (from dir)')
manifest['version'] = int(time.time() * 1000)
with open(ws_skill, 'w', encoding='utf-8') as f:
json.dump(manifest, f, indent=2, ensure_ascii=False)
print(' skills done')
"@
python3 -c $pyScript 2>$null
if ($LASTEXITCODE -ne 0) { python -c $pyScript }
# ── 注册到 config.json ─────────────────────────────────────────────────
Write-Info "注册 Agent..."
$regScript = @"
import json, os
config_path = os.path.join(r'$COPAW_HOME', 'config.json')
with open(config_path, 'r', encoding='utf-8') as f:
cfg = json.load(f)
agent_id = '$AGENT_ID'
ws_dir = r'$WORKSPACE_DIR'
changed = False
if agent_id not in cfg['agents']['profiles']:
cfg['agents']['profiles'][agent_id] = {
'id': agent_id,
'workspace_dir': ws_dir,
'enabled': True
}
changed = True
if agent_id not in cfg['agents']['agent_order']:
cfg['agents']['agent_order'].append(agent_id)
changed = True
if changed:
with open(config_path, 'w', encoding='utf-8') as f:
json.dump(cfg, f, indent=2, ensure_ascii=False)
print(' registered')
else:
print(' already registered')
"@
python3 -c $regScript 2>$null
if ($LASTEXITCODE -ne 0) { python -c $regScript }
# ── 记录来源 ───────────────────────────────────────────────────────────
$repoDir = Split-Path -Parent $SCRIPT_DIR
Set-Content (Join-Path $WORKSPACE_DIR ".repo_path") $repoDir -Encoding UTF8
# ── 清理临时文件 ───────────────────────────────────────────────────────
if ($SCRIPT_DIR -like "$env:TEMP*") {
Write-Info "清理临时文件..."
Remove-Item $repoDir -Recurse -Force -ErrorAction SilentlyContinue
}
# ── 完成 ───────────────────────────────────────────────────────────────
Write-Host ""
Write-Info "════════════════════════════════════════════════"
Write-Info " ✅ 黑手党提案专家 安装/更新完成!"
Write-Info "════════════════════════════════════════════════"
Write-Host ""
Write-Info "下一步:"
Write-Info " 1. 打开 CoPaw 客户端"
Write-Info " 2. 刷新页面Ctrl+R / F5"
Write-Info " 3. 左上角切换到「黑手党提案专家」"
Write-Info " 4. 发送:我想为 XX 品牌做一个黑手党提案"
Write-Host ""

980
landing/index.html Normal file
View File

@ -0,0 +1,980 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>黑手党提案专家 — CoPaw Agent</title>
<meta name="description" content="基于 TOC 约束理论的 AI 战略顾问,帮你做出对手无法拒绝的提案。一键安装,即刻启用。">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=Noto+Sans+SC:wght@400;500;600;700;800&display=swap" rel="stylesheet">
<style>
:root {
--bg-primary: #0a0a0f;
--bg-secondary: #12121a;
--bg-card: #1a1a26;
--bg-card-hover: #222233;
--text-primary: #f0f0f5;
--text-secondary: #9999aa;
--text-muted: #666677;
--accent: #ff4444;
--accent-glow: rgba(255, 68, 68, 0.15);
--accent-secondary: #ff6b35;
--accent-gold: #ffc107;
--border: rgba(255,255,255,0.06);
--border-accent: rgba(255, 68, 68, 0.3);
--radius: 16px;
--radius-sm: 10px;
--shadow-card: 0 4px 24px rgba(0,0,0,0.3);
--font: 'Inter', 'Noto Sans SC', -apple-system, BlinkMacSystemFont, sans-serif;
}
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: var(--font);
background: var(--bg-primary);
color: var(--text-primary);
line-height: 1.6;
-webkit-font-smoothing: antialiased;
overflow-x: hidden;
}
.container {
max-width: 1100px;
margin: 0 auto;
padding: 0 32px;
}
/* ═══════ SVG icon helpers ═══════ */
.icon-inline {
width: 20px; height: 20px;
flex-shrink: 0;
}
.icon-sm {
width: 16px; height: 16px;
flex-shrink: 0;
}
.icon-lg {
width: 28px; height: 28px;
}
.icon-xl {
width: 32px; height: 32px;
}
/* ═══════════ Hero ═══════════ */
.hero {
position: relative;
padding: 80px 0 60px;
overflow: hidden;
}
.hero::before {
content: '';
position: absolute;
top: -200px;
left: 50%;
transform: translateX(-50%);
width: 800px;
height: 800px;
background: radial-gradient(circle, var(--accent-glow) 0%, transparent 70%);
pointer-events: none;
}
.hero-inner {
position: relative;
text-align: center;
}
.hero-badge {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 6px 16px;
background: var(--bg-card);
border: 1px solid var(--border);
border-radius: 100px;
font-size: 13px;
color: var(--text-secondary);
margin-bottom: 24px;
}
.hero-badge .dot {
width: 6px; height: 6px;
background: #4ade80;
border-radius: 50%;
animation: pulse 2s infinite;
}
@keyframes pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.4; }
}
.hero h1 {
font-size: clamp(36px, 5vw, 56px);
font-weight: 800;
line-height: 1.15;
margin-bottom: 16px;
background: linear-gradient(135deg, var(--text-primary), var(--accent), var(--accent-secondary));
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.hero-subtitle {
font-size: 18px;
color: var(--text-secondary);
max-width: 520px;
margin: 0 auto 40px;
line-height: 1.7;
}
.hero-tagline {
font-size: 14px;
color: var(--text-muted);
margin-top: 8px;
display: flex;
align-items: center;
justify-content: center;
gap: 16px;
}
.hero-tagline em {
color: var(--accent);
font-style: normal;
}
.tag-sep {
width: 4px; height: 4px;
background: var(--text-muted);
border-radius: 50%;
opacity: 0.5;
}
/* ═══════════ Section ═══════════ */
.section {
padding: 64px 0;
}
.section-title {
font-size: 28px;
font-weight: 700;
margin-bottom: 12px;
}
.section-desc {
color: var(--text-secondary);
font-size: 15px;
margin-bottom: 40px;
}
/* ═══════════ Install Steps ═══════════ */
.install-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 24px;
}
@media (max-width: 768px) {
.install-grid { grid-template-columns: 1fr; }
}
.install-card {
background: var(--bg-card);
border: 1px solid var(--border);
border-radius: var(--radius);
padding: 32px;
transition: all 0.3s ease;
}
.install-card:hover {
background: var(--bg-card-hover);
border-color: var(--border-accent);
box-shadow: 0 0 40px var(--accent-glow);
}
.step-header {
display: flex;
align-items: center;
gap: 12px;
margin-bottom: 20px;
}
.step-number {
width: 32px; height: 32px;
background: var(--accent);
color: white;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 14px;
font-weight: 700;
flex-shrink: 0;
}
.step-title {
font-size: 16px;
font-weight: 600;
}
.step-desc {
font-size: 14px;
color: var(--text-secondary);
margin-bottom: 16px;
line-height: 1.7;
}
.code-block {
background: #0d0d14;
border: 1px solid var(--border);
border-radius: var(--radius-sm);
padding: 16px 48px 16px 16px;
font-family: 'SF Mono', 'Fira Code', monospace;
font-size: 12.5px;
color: #e0e0e8;
overflow-x: auto;
position: relative;
word-break: break-all;
white-space: pre-wrap;
line-height: 1.6;
}
.copy-btn {
position: absolute;
top: 10px; right: 10px;
background: rgba(255,255,255,0.08);
border: 1px solid var(--border);
color: var(--text-secondary);
padding: 4px 12px;
border-radius: 6px;
font-size: 12px;
cursor: pointer;
transition: all 0.2s;
display: flex;
align-items: center;
gap: 4px;
}
.copy-btn:hover {
background: var(--accent);
color: white;
border-color: var(--accent);
}
.copy-btn:hover svg { stroke: white; }
.copy-btn.copied {
background: #4ade80;
color: #0a0a0f;
border-color: #4ade80;
}
.copy-btn.copied svg { stroke: #0a0a0f; }
/* ═══════════ Skills Grid ═══════════ */
.skills-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 20px;
}
@media (max-width: 768px) {
.skills-grid { grid-template-columns: 1fr; }
}
.skill-card {
background: var(--bg-card);
border: 1px solid var(--border);
border-radius: var(--radius);
padding: 28px;
transition: all 0.3s ease;
position: relative;
overflow: hidden;
}
.skill-card:hover {
background: var(--bg-card-hover);
border-color: var(--border-accent);
transform: translateY(-4px);
box-shadow: var(--shadow-card);
}
.skill-icon {
width: 48px; height: 48px;
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 16px;
}
.skill-icon svg {
width: 26px; height: 26px;
}
.skill-card h3 {
font-size: 16px;
font-weight: 600;
margin-bottom: 8px;
}
.skill-card p {
font-size: 13.5px;
color: var(--text-secondary);
line-height: 1.65;
}
.skill-badge {
position: absolute;
top: 16px; right: 16px;
font-size: 11px;
padding: 2px 8px;
border-radius: 4px;
font-weight: 500;
}
.badge-toc { background: rgba(255,68,68,0.12); color: #ff6666; }
.badge-data { background: rgba(74,222,128,0.12); color: #4ade80; }
/* ═══════════ Flow ═══════════ */
.flow-section {
background: var(--bg-secondary);
border-radius: var(--radius);
border: 1px solid var(--border);
padding: 48px;
margin-top: 40px;
}
.flow-steps {
display: flex;
align-items: flex-start;
gap: 12px;
flex-wrap: wrap;
justify-content: center;
}
.flow-step {
flex: 1;
min-width: 140px;
max-width: 180px;
text-align: center;
}
.flow-step-icon {
width: 56px; height: 56px;
margin: 0 auto 12px;
background: var(--bg-card);
border: 1px solid var(--border);
border-radius: 14px;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.3s;
}
.flow-step-icon svg {
width: 26px; height: 26px;
}
.flow-step:hover .flow-step-icon {
border-color: var(--accent);
box-shadow: 0 0 20px var(--accent-glow);
}
.flow-step h4 {
font-size: 14px;
font-weight: 600;
margin-bottom: 4px;
}
.flow-step p {
font-size: 12px;
color: var(--text-muted);
}
.flow-arrow {
display: flex;
align-items: center;
padding-top: 18px;
color: var(--text-muted);
}
.flow-arrow svg {
width: 20px; height: 20px;
}
@media (max-width: 768px) {
.flow-arrow { display: none; }
.flow-section { padding: 32px 20px; }
}
/* ═══════════ Key Setup ═══════════ */
.key-section {
background: linear-gradient(135deg, rgba(255,193,7,0.05), rgba(255,68,68,0.05));
border: 1px solid rgba(255,193,7,0.15);
border-radius: var(--radius);
padding: 40px;
margin-top: 40px;
}
.key-section h3 {
font-size: 20px;
font-weight: 700;
margin-bottom: 8px;
display: flex;
align-items: center;
gap: 10px;
}
.key-section h3 svg {
width: 22px; height: 22px;
stroke: var(--accent-gold);
}
.key-section .desc {
color: var(--text-secondary);
font-size: 14px;
margin-bottom: 20px;
}
.key-steps {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 20px;
}
@media (max-width: 768px) {
.key-steps { grid-template-columns: 1fr; }
}
.key-step {
display: flex;
gap: 12px;
align-items: flex-start;
}
.key-step-num {
width: 24px; height: 24px;
background: var(--accent-gold);
color: #0a0a0f;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 12px;
font-weight: 700;
flex-shrink: 0;
margin-top: 2px;
}
.key-step-text h4 {
font-size: 14px;
font-weight: 600;
margin-bottom: 4px;
}
.key-step-text p {
font-size: 13px;
color: var(--text-secondary);
line-height: 1.6;
}
.key-step-text a {
color: var(--accent-gold);
text-decoration: none;
}
.key-step-text a:hover { text-decoration: underline; }
/* ═══════════ Footer ═══════════ */
.footer {
padding: 48px 0;
border-top: 1px solid var(--border);
text-align: center;
color: var(--text-muted);
font-size: 13px;
}
.footer a {
color: var(--text-secondary);
text-decoration: none;
}
.footer a:hover { color: var(--accent); }
.footer-links {
display: flex;
gap: 24px;
justify-content: center;
margin-bottom: 16px;
}
/* ═══════════ Divider ═══════════ */
.divider {
height: 1px;
background: var(--border);
margin: 0 0 64px;
}
/* ═══════════ Prereq ═══════════ */
.prereq-note {
display: flex;
align-items: center;
gap: 10px;
padding: 14px 20px;
background: rgba(74,222,128,0.06);
border: 1px solid rgba(74,222,128,0.15);
border-radius: var(--radius-sm);
font-size: 14px;
color: var(--text-secondary);
margin-bottom: 24px;
}
.prereq-note svg {
width: 18px; height: 18px;
stroke: #4ade80;
flex-shrink: 0;
}
.prereq-note a {
color: #4ade80;
text-decoration: none;
font-weight: 500;
}
.prereq-note a:hover { text-decoration: underline; }
.try-prompt {
padding: 12px 16px;
background: rgba(255,255,255,0.03);
border-radius: 8px;
border: 1px solid var(--border);
}
.try-prompt-label {
font-size: 12px;
color: var(--text-muted);
margin-bottom: 4px;
display: flex;
align-items: center;
gap: 6px;
}
.try-prompt-label svg {
width: 14px; height: 14px;
stroke: var(--text-muted);
}
.try-prompt-text {
font-size: 14px;
color: var(--text-primary);
}
/* ═══════════ OS Tabs ═══════════ */
.os-tabs {
display: flex;
gap: 4px;
margin-bottom: 16px;
}
.os-tab {
display: flex;
align-items: center;
gap: 6px;
padding: 7px 16px;
background: transparent;
border: 1px solid var(--border);
border-radius: 8px;
color: var(--text-muted);
font-size: 13px;
font-weight: 500;
cursor: pointer;
transition: all 0.2s;
font-family: var(--font);
}
.os-tab svg {
width: 16px; height: 16px;
}
.os-tab:hover {
border-color: rgba(255,255,255,0.15);
color: var(--text-secondary);
}
.os-tab.active {
background: rgba(255,68,68,0.1);
border-color: var(--border-accent);
color: var(--accent);
}
.os-tab.active svg {
stroke: var(--accent);
}
.os-cmd-panel {
display: none;
}
.os-cmd-panel.active {
display: block;
}
</style>
</head>
<body>
<!-- ═══════ SVG Sprites (hidden) ═══════ -->
<svg xmlns="http://www.w3.org/2000/svg" style="display:none">
<!-- Search / Diagnose -->
<symbol id="ico-search" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/>
</symbol>
<!-- Zap / Conflict -->
<symbol id="ico-zap" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M13 2 3 14h9l-1 8 10-12h-9l1-8z"/>
</symbol>
<!-- Lightbulb / Insight -->
<symbol id="ico-bulb" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M15 14c.2-1 .7-1.7 1.5-2.5 1-.9 1.5-2.2 1.5-3.5A6 6 0 0 0 6 8c0 1 .2 2.2 1.5 3.5.7.7 1.3 1.5 1.5 2.5"/><path d="M9 18h6"/><path d="M10 22h4"/>
</symbol>
<!-- Git Branch / Negative Branch -->
<symbol id="ico-branch" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<line x1="6" y1="3" x2="6" y2="15"/><circle cx="18" cy="6" r="3"/><circle cx="6" cy="18" r="3"/><path d="M18 9a9 9 0 0 1-9 9"/>
</symbol>
<!-- FileText / Proposal -->
<symbol id="ico-file" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"/><path d="M14 2v4a2 2 0 0 0 2 2h4"/><path d="M10 13h4"/><path d="M10 17h4"/><path d="M10 9h1"/>
</symbol>
<!-- BarChart / VOC Data -->
<symbol id="ico-chart" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<line x1="12" y1="20" x2="12" y2="10"/><line x1="18" y1="20" x2="18" y2="4"/><line x1="6" y1="20" x2="6" y2="16"/>
</symbol>
<!-- Key -->
<symbol id="ico-key" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="m15.5 7.5 2.3 2.3a1 1 0 0 0 1.4 0l2.1-2.1a1 1 0 0 0 0-1.4L19 4"/><path d="m21 2-9.6 9.6"/><circle cx="7.5" cy="15.5" r="5.5"/>
</symbol>
<!-- Terminal -->
<symbol id="ico-terminal" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline points="4 17 10 11 4 5"/><line x1="12" y1="19" x2="20" y2="19"/>
</symbol>
<!-- Package -->
<symbol id="ico-package" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="m7.5 4.27 9 5.15"/><path d="M21 8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16Z"/><path d="m3.3 7 8.7 5 8.7-5"/><path d="M12 22V12"/>
</symbol>
<!-- Copy -->
<symbol id="ico-copy" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/>
</symbol>
<!-- Check -->
<symbol id="ico-check" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline points="20 6 9 17 4 12"/>
</symbol>
<!-- ArrowRight -->
<symbol id="ico-arrow-r" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M5 12h14"/><path d="m12 5 7 7-7 7"/>
</symbol>
<!-- MessageCircle -->
<symbol id="ico-chat" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M7.9 20A9 9 0 1 0 4 16.1L2 22Z"/>
</symbol>
<!-- RefreshCw -->
<symbol id="ico-refresh" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8"/><path d="M21 3v5h-5"/><path d="M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16"/><path d="M8 16H3v5"/>
</symbol>
<!-- Shield -->
<symbol id="ico-shield" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z"/>
</symbol>
</svg>
<!-- ═══════════ Hero ═══════════ -->
<section class="hero">
<div class="container hero-inner">
<div class="hero-badge">
<span class="dot"></span>
CoPaw Agent · 开源免费
</div>
<h1>黑手党提案专家</h1>
<p class="hero-subtitle">
基于 TOC 约束理论的 AI 战略顾问。<br>
帮你做出<strong>对手无法拒绝</strong>的提案。
</p>
<p class="hero-tagline">
<span>TOC 五步法</span>
<span class="tag-sep"></span>
<span>VOC 消费者洞察</span>
<span class="tag-sep"></span>
<em>一键安装</em>
</p>
</div>
</section>
<!-- ═══════════ 安装指引 ═══════════ -->
<section class="section">
<div class="container">
<h2 class="section-title">安装指引</h2>
<p class="section-desc">两步完成部署,让 AI 战略顾问即刻上线</p>
<div class="prereq-note">
<svg><use href="#ico-package"/></svg>
<span>前置条件:需先安装 <a href="https://copaw.agentscope.io" target="_blank">CoPaw 桌面客户端</a>(阿里巴巴开源 AI 助手框架)</span>
</div>
<div class="install-grid">
<!-- Step 1 -->
<div class="install-card">
<div class="step-header">
<div class="step-number">1</div>
<div class="step-title">一键安装到 CoPaw</div>
</div>
<p class="step-desc">
打开终端,粘贴以下命令即可自动完成 Agent 注册、Skills 部署和配置。
</p>
<div class="os-tabs">
<button class="os-tab active" onclick="switchOS('mac', this)">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 20.94c1.5 0 2.75 1.06 4 1.06 3 0 4-5 4-8.5 0-4.5-2.5-6.5-4-6.5-1.25 0-2.5 1-4 1s-2.75-1-4-1c-1.5 0-4 2-4 6.5 0 3.5 1 8.5 4 8.5 1.25 0 2.5-1.06 4-1.06Z"/><path d="M12 7c1.5-2 3-3 5-3"/></svg>
macOS / Linux
</button>
<button class="os-tab" onclick="switchOS('win', this)">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="8" height="8" rx="1"/><rect x="13" y="3" width="8" height="8" rx="1"/><rect x="3" y="13" width="8" height="8" rx="1"/><rect x="13" y="13" width="8" height="8" rx="1"/></svg>
Windows
</button>
</div>
<div id="cmd-mac" class="os-cmd-panel active">
<div class="code-block" id="installCmdMac">curl -fsSL https://git.brainwork.club/lidf/chanpinhsd/archive/main.tar.gz | tar xz -C /tmp && bash /tmp/chanpinhsd/agent/install.sh<button class="copy-btn" onclick="copyCode('installCmdMac', this)"><svg class="icon-sm"><use href="#ico-copy"/></svg>复制</button></div>
</div>
<div id="cmd-win" class="os-cmd-panel">
<div class="code-block" id="installCmdWin">irm https://git.brainwork.club/lidf/chanpinhsd/archive/main.zip -OutFile $env:TEMP\mafia.zip; Expand-Archive $env:TEMP\mafia.zip $env:TEMP\mafia -Force; & $env:TEMP\mafia\chanpinhsd\agent\install.ps1<button class="copy-btn" onclick="copyCode('installCmdWin', this)"><svg class="icon-sm"><use href="#ico-copy"/></svg>复制</button></div>
<p style="font-size:12px; color:var(--text-muted); margin-top:8px;">在 PowerShell 中运行(右键开始菜单 → Windows Terminal</p>
</div>
</div>
<!-- Step 2 -->
<div class="install-card">
<div class="step-header">
<div class="step-number">2</div>
<div class="step-title">刷新并切换 Agent</div>
</div>
<p class="step-desc">
安装完成后,刷新 CoPaw 桌面客户端Cmd+R在左上角切换到「黑手党提案专家」即可开始使用。
</p>
<div style="margin-top: 16px;">
<div class="try-prompt">
<div class="try-prompt-label"><svg><use href="#ico-chat"/></svg>试试说</div>
<div class="try-prompt-text">我想为天维美护肝片做一个黑手党提案</div>
</div>
</div>
</div>
</div>
</div>
</section>
<div class="container"><div class="divider"></div></div>
<!-- ═══════════ 核心技能 ═══════════ -->
<section class="section">
<div class="container">
<h2 class="section-title">核心技能</h2>
<p class="section-desc">TOC 约束理论五步法 + VOC 消费者洞察6 大技能协同工作</p>
<div class="skills-grid">
<div class="skill-card">
<span class="skill-badge badge-toc">TOC</span>
<div class="skill-icon" style="background: rgba(255,68,68,0.1);">
<svg style="stroke:#ff6666"><use href="#ico-search"/></svg>
</div>
<h3>UDE 诊断</h3>
<p>识别品牌面临的「不满意效果」Undesirable Effect找到约束系统的核心痛点</p>
</div>
<div class="skill-card">
<span class="skill-badge badge-toc">TOC</span>
<div class="skill-icon" style="background: rgba(255,107,53,0.1);">
<svg style="stroke:#ff6b35"><use href="#ico-zap"/></svg>
</div>
<h3>冲突图构建</h3>
<p>将 UDE 转化为「对立假设」冲突图,揭示表面矛盾背后的隐藏假设</p>
</div>
<div class="skill-card">
<span class="skill-badge badge-toc">TOC</span>
<div class="skill-icon" style="background: rgba(255,193,7,0.1);">
<svg style="stroke:#ffc107"><use href="#ico-bulb"/></svg>
</div>
<h3>惯例打破</h3>
<p>挑战行业惯例与隐性假设,找到「打破规则」的突破口——提案的核心创新点</p>
</div>
<div class="skill-card">
<span class="skill-badge badge-toc">TOC</span>
<div class="skill-icon" style="background: rgba(139,92,246,0.1);">
<svg style="stroke:#8b5cf6"><use href="#ico-branch"/></svg>
</div>
<h3>负面分支预测</h3>
<p>预判提案可能引发的负面后果NBRS提前设计「修剪策略」降低风险</p>
</div>
<div class="skill-card">
<span class="skill-badge badge-toc">TOC</span>
<div class="skill-icon" style="background: rgba(59,130,246,0.1);">
<svg style="stroke:#3b82f6"><use href="#ico-file"/></svg>
</div>
<h3>提案组装</h3>
<p>将诊断、冲突、惯例、风险整合为完整的黑手党提案交付文档</p>
</div>
<div class="skill-card">
<span class="skill-badge badge-data">数据</span>
<div class="skill-icon" style="background: rgba(74,222,128,0.1);">
<svg style="stroke:#4ade80"><use href="#ico-chart"/></svg>
</div>
<h3>VOC 研究</h3>
<p>调用 VOC 后端 API 采集抖音、小红书消费者声音数据,为诊断提供实证基础</p>
</div>
</div>
<!-- Flow -->
<div class="flow-section">
<h3 style="text-align: center; font-size: 18px; margin-bottom: 32px; color: var(--text-secondary);">工作流程</h3>
<div class="flow-steps">
<div class="flow-step">
<div class="flow-step-icon"><svg style="stroke:#4ade80"><use href="#ico-chart"/></svg></div>
<h4>VOC 采集</h4>
<p>消费者数据</p>
</div>
<div class="flow-arrow"><svg><use href="#ico-arrow-r"/></svg></div>
<div class="flow-step">
<div class="flow-step-icon"><svg style="stroke:#ff6666"><use href="#ico-search"/></svg></div>
<h4>UDE 诊断</h4>
<p>找到痛点</p>
</div>
<div class="flow-arrow"><svg><use href="#ico-arrow-r"/></svg></div>
<div class="flow-step">
<div class="flow-step-icon"><svg style="stroke:#ff6b35"><use href="#ico-zap"/></svg></div>
<h4>冲突图</h4>
<p>揭示矛盾</p>
</div>
<div class="flow-arrow"><svg><use href="#ico-arrow-r"/></svg></div>
<div class="flow-step">
<div class="flow-step-icon"><svg style="stroke:#ffc107"><use href="#ico-bulb"/></svg></div>
<h4>打破惯例</h4>
<p>找到突破</p>
</div>
<div class="flow-arrow"><svg><use href="#ico-arrow-r"/></svg></div>
<div class="flow-step">
<div class="flow-step-icon"><svg style="stroke:#8b5cf6"><use href="#ico-branch"/></svg></div>
<h4>风险修剪</h4>
<p>降低副作用</p>
</div>
<div class="flow-arrow"><svg><use href="#ico-arrow-r"/></svg></div>
<div class="flow-step">
<div class="flow-step-icon"><svg style="stroke:#3b82f6"><use href="#ico-file"/></svg></div>
<h4>提案交付</h4>
<p>完整文档</p>
</div>
</div>
</div>
</div>
</section>
<div class="container"><div class="divider"></div></div>
<!-- ═══════════ TikHub Key ═══════════ -->
<section class="section">
<div class="container">
<h2 class="section-title">VOC 数据采集</h2>
<p class="section-desc">使用 VOC 研究功能需要配置 TikHub API Key用于采集抖音/小红书数据)</p>
<div class="key-section">
<h3><svg><use href="#ico-key"/></svg>TikHub API Key 配置</h3>
<p class="desc">每位用户使用自己的 Key按用量付费。单次研究成本约 $1-312 关键词 × 2 平台)。</p>
<div class="key-steps">
<div class="key-step">
<div class="key-step-num">1</div>
<div class="key-step-text">
<h4>注册 TikHub</h4>
<p>前往 <a href="https://tikhub.io" target="_blank">tikhub.io</a> 注册并充值</p>
</div>
</div>
<div class="key-step">
<div class="key-step-num">2</div>
<div class="key-step-text">
<h4>告诉 Agent</h4>
<p>对 Agent 说「我的 TikHub Key 是 xxx」它会自动保存到本地</p>
</div>
</div>
<div class="key-step">
<div class="key-step-num">3</div>
<div class="key-step-text">
<h4>安全可靠</h4>
<p>Key 存储在本地,加密传输,不存储到服务器数据库</p>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- ═══════════ Footer ═══════════ -->
<footer class="footer">
<div class="container">
<div class="footer-links">
<a href="https://copaw.agentscope.io" target="_blank">CoPaw 官网</a>
<a href="https://git.brainwork.club/lidf/chanpinhsd" target="_blank">源码仓库</a>
<a href="https://tikhub.io" target="_blank">TikHub</a>
</div>
<p>黑手党提案专家 · 基于 <a href="https://copaw.agentscope.io">CoPaw</a> 构建 · BrainWork Studio</p>
</div>
</footer>
<script>
function switchOS(os, btn) {
// Toggle tabs
document.querySelectorAll('.os-tab').forEach(t => t.classList.remove('active'));
btn.classList.add('active');
// Toggle panels
document.querySelectorAll('.os-cmd-panel').forEach(p => p.classList.remove('active'));
document.getElementById('cmd-' + os).classList.add('active');
}
function copyCode(id, btn) {
const el = document.getElementById(id);
const text = el.childNodes[0].textContent.trim();
navigator.clipboard.writeText(text).then(() => {
btn.innerHTML = '<svg class="icon-sm"><use href="#ico-check"/></svg>已复制';
btn.classList.add('copied');
setTimeout(() => {
btn.innerHTML = '<svg class="icon-sm"><use href="#ico-copy"/></svg>复制';
btn.classList.remove('copied');
}, 2000);
});
}
// Subtle scroll animations
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.style.opacity = '1';
entry.target.style.transform = 'translateY(0)';
}
});
}, { threshold: 0.1 });
document.querySelectorAll('.skill-card, .install-card, .flow-step').forEach(el => {
el.style.opacity = '0';
el.style.transform = 'translateY(20px)';
el.style.transition = 'opacity 0.5s ease, transform 0.5s ease';
observer.observe(el);
});
</script>
</body>
</html>