diff --git a/02_卡人(水)/水溪_整理归档/经验库/待沉淀/2026-03-15_全站埋点统计标准_Soul项目沉淀.md b/02_卡人(水)/水溪_整理归档/经验库/待沉淀/2026-03-15_全站埋点统计标准_Soul项目沉淀.md
new file mode 100644
index 00000000..6ae9f5a5
--- /dev/null
+++ b/02_卡人(水)/水溪_整理归档/经验库/待沉淀/2026-03-15_全站埋点统计标准_Soul项目沉淀.md
@@ -0,0 +1,74 @@
+# 全站埋点统计标准(Soul 创业实验项目沉淀)
+
+> 日期:2026-03-15
+> 来源:Soul 创业实验项目 · 数据统计迭代
+> 已写入:全栈开发 SKILL v2.5 § 1.10
+
+---
+
+## 背景
+
+Soul 创业实验项目在管理后台需要「分类标签点击统计」面板,但发现小程序端没有埋点数据上报。从零实施全站埋点,覆盖 9 个小程序页面、后端聚合 API、管理后台可视化面板,前后共 3 小时完成。
+
+**教训**:功能上线后再补埋点,已丢失大量初期用户行为数据。**以后功能和埋点必须同时上线。**
+
+---
+
+## 标准三层架构
+
+```
+前端(小程序/Web) 后端 API 管理后台
+trackClick(module, → POST /api/{平台}/track → GET /api/admin/track/stats
+ action, target, extra) 存入 user_tracks 表 按 module/action/时间段聚合
+```
+
+### 1. 前端:trackClick 工具
+
+每个平台(小程序、Web、App)封装一个 `trackClick(module, action, target, extra?)` 函数:
+
+- **module**:所属模块(home / chapters / read / my / vip / wallet / match / referral / search)
+- **action**:标准动词(btn_click / page_view / tab_click / nav_click / share)
+- **target**:具体按钮/链接名(如「购买VIP」「充值」「阅读第3章」)
+- **extra**:可选扩展字段
+
+静默上报,不弹窗不阻塞用户操作。
+
+### 2. 后端:track API + user_tracks 表
+
+| 字段 | 类型 | 说明 |
+|:---|:---|:---|
+| id | string/UUID | 主键 |
+| user_id | string | 用户 ID |
+| action | string | 动作类型 |
+| target | string | 具体目标 |
+| extra_data | JSONB | 扩展信息,含 module、page |
+| created_at | timestamp | 自动时间戳 |
+
+注意 `extra_data` 要正确 Marshal 为 JSON 存入 JSONB 字段(Go 端踩过坑:忘记 marshal body.ExtraData 导致 null)。
+
+### 3. 管理后台:聚合面板
+
+- 后端 `GET /api/admin/track/stats?period=today|week|month|all` 按 action+target+extra_data 聚合并分组
+- 前端面板按 module 分组展示,支持时间段切换,30 秒自动刷新
+
+---
+
+## 埋点接入检查清单
+
+每开发一个新功能/新页面,按此清单打勾:
+
+- [ ] 页面所有可点击按钮/标签都已调用 trackClick
+- [ ] module 参数使用统一命名
+- [ ] action 参数使用标准动词
+- [ ] target 参数能区分具体按钮
+- [ ] 后端 track API 已注册路由且能正确存储 extra_data
+- [ ] 管理后台能展示该模块数据
+
+---
+
+## 实际代码参考
+
+- **小程序 trackClick**:`miniprogram/utils/trackClick.js`
+- **后端 track handler**:`soul-api/internal/handler/admin_track.go`(聚合统计)、`soul-api/internal/handler/user.go`(UserTrackPost 存储)
+- **管理后台面板**:`soul-admin/src/pages/dashboard/DashboardPage.tsx`(分类标签点击统计 Card)
+- **数据模型**:`soul-api/internal/model/user_track.go`
diff --git a/03_卡木(木)/木根_逆向分析/全网API自动注册/SKILL.md b/03_卡木(木)/木根_逆向分析/全网AI自动注册/SKILL.md
similarity index 93%
rename from 03_卡木(木)/木根_逆向分析/全网API自动注册/SKILL.md
rename to 03_卡木(木)/木根_逆向分析/全网AI自动注册/SKILL.md
index 70c171ac..8525856d 100644
--- a/03_卡木(木)/木根_逆向分析/全网API自动注册/SKILL.md
+++ b/03_卡木(木)/木根_逆向分析/全网AI自动注册/SKILL.md
@@ -1,14 +1,14 @@
---
-name: 全网API自动注册
-description: 自动注册全网各类 AI/开发 API 免费账号,提取 API Key/Token 并统一管理
-triggers: API注册、自动注册、批量注册、API Key、注册账号、免费API、API池、key池、自动开号
+name: 全网AI自动注册
+description: 自动注册全网各类 AI API 免费账号,提取 API Key/Token 并统一管理
+triggers: AI注册、自动注册、批量注册、API Key、注册账号、免费API、API池、key池、自动开号、Gemini注册
owner: 木根
group: 木(卡木)
version: "1.0"
updated: "2026-03-15"
---
-# 全网API自动注册
+# 全网AI自动注册
## 能做什么(Capabilities)
diff --git a/03_卡木(木)/木根_逆向分析/全网API自动注册/providers/__init__.py b/03_卡木(木)/木根_逆向分析/全网AI自动注册/providers/__init__.py
similarity index 100%
rename from 03_卡木(木)/木根_逆向分析/全网API自动注册/providers/__init__.py
rename to 03_卡木(木)/木根_逆向分析/全网AI自动注册/providers/__init__.py
diff --git a/03_卡木(木)/木根_逆向分析/全网API自动注册/providers/base_provider.py b/03_卡木(木)/木根_逆向分析/全网AI自动注册/providers/base_provider.py
similarity index 100%
rename from 03_卡木(木)/木根_逆向分析/全网API自动注册/providers/base_provider.py
rename to 03_卡木(木)/木根_逆向分析/全网AI自动注册/providers/base_provider.py
diff --git a/03_卡木(木)/木根_逆向分析/全网API自动注册/providers/cursor_provider.py b/03_卡木(木)/木根_逆向分析/全网AI自动注册/providers/cursor_provider.py
similarity index 100%
rename from 03_卡木(木)/木根_逆向分析/全网API自动注册/providers/cursor_provider.py
rename to 03_卡木(木)/木根_逆向分析/全网AI自动注册/providers/cursor_provider.py
diff --git a/03_卡木(木)/木根_逆向分析/全网API自动注册/providers/gemini_provider.py b/03_卡木(木)/木根_逆向分析/全网AI自动注册/providers/gemini_provider.py
similarity index 100%
rename from 03_卡木(木)/木根_逆向分析/全网API自动注册/providers/gemini_provider.py
rename to 03_卡木(木)/木根_逆向分析/全网AI自动注册/providers/gemini_provider.py
diff --git a/03_卡木(木)/木根_逆向分析/全网API自动注册/providers/generic_browser_provider.py b/03_卡木(木)/木根_逆向分析/全网AI自动注册/providers/generic_browser_provider.py
similarity index 100%
rename from 03_卡木(木)/木根_逆向分析/全网API自动注册/providers/generic_browser_provider.py
rename to 03_卡木(木)/木根_逆向分析/全网AI自动注册/providers/generic_browser_provider.py
diff --git a/03_卡木(木)/木根_逆向分析/全网API自动注册/providers/openai_provider.py b/03_卡木(木)/木根_逆向分析/全网AI自动注册/providers/openai_provider.py
similarity index 100%
rename from 03_卡木(木)/木根_逆向分析/全网API自动注册/providers/openai_provider.py
rename to 03_卡木(木)/木根_逆向分析/全网AI自动注册/providers/openai_provider.py
diff --git a/03_卡木(木)/木根_逆向分析/全网API自动注册/脚本/auto_register.py b/03_卡木(木)/木根_逆向分析/全网AI自动注册/脚本/auto_register.py
similarity index 100%
rename from 03_卡木(木)/木根_逆向分析/全网API自动注册/脚本/auto_register.py
rename to 03_卡木(木)/木根_逆向分析/全网AI自动注册/脚本/auto_register.py
diff --git a/03_卡木(木)/木根_逆向分析/全网API自动注册/脚本/config.example.yaml b/03_卡木(木)/木根_逆向分析/全网AI自动注册/脚本/config.example.yaml
similarity index 100%
rename from 03_卡木(木)/木根_逆向分析/全网API自动注册/脚本/config.example.yaml
rename to 03_卡木(木)/木根_逆向分析/全网AI自动注册/脚本/config.example.yaml
diff --git a/03_卡木(木)/木根_逆向分析/全网AI自动注册/脚本/gemini_key_creator.py b/03_卡木(木)/木根_逆向分析/全网AI自动注册/脚本/gemini_key_creator.py
new file mode 100644
index 00000000..faeb4bb9
--- /dev/null
+++ b/03_卡木(木)/木根_逆向分析/全网AI自动注册/脚本/gemini_key_creator.py
@@ -0,0 +1,320 @@
+#!/usr/bin/env python3
+"""
+Gemini API Key 创建器(纯命令行 + 系统浏览器 OAuth 授权)
+不需要打开额外浏览器,系统浏览器走 Clash 代理完成 Google 登录授权。
+自动创建指定数量的 GCP 项目并生成 Gemini API Key。
+
+用法: python3 gemini_key_creator.py --count 3
+"""
+
+import argparse
+import http.server
+import json
+import os
+import random
+import string
+import sys
+import threading
+import time
+import urllib.parse
+import webbrowser
+from pathlib import Path
+
+import httpx
+
+PROXY = "http://127.0.0.1:7897"
+
+# Google OAuth2 客户端(使用 Google Cloud SDK 的公开 client)
+CLIENT_ID = "764086051850-6qr4p6gpi6hn506pt8ejuq83di341hur.apps.googleusercontent.com"
+CLIENT_SECRET = "d-FL95Q19q7MQmFpd7hHD0Ty"
+REDIRECT_PORT = 18457
+REDIRECT_URI = f"http://localhost:{REDIRECT_PORT}"
+SCOPES = [
+ "https://www.googleapis.com/auth/cloud-platform",
+ "https://www.googleapis.com/auth/generative-language",
+]
+
+TOKEN_URL = "https://oauth2.googleapis.com/token"
+PROJECTS_URL = "https://cloudresourcemanager.googleapis.com/v1/projects"
+SERVICES_URL = "https://serviceusage.googleapis.com/v1/projects/{project_id}/services/generativelanguage.googleapis.com:enable"
+APIKEYS_URL = "https://apikeys.googleapis.com/v2/projects/{project_id}/locations/global/keys"
+
+DB_PATH = Path(__file__).parent / "accounts.db"
+JSON_DIR = Path(__file__).parent / "tokens"
+
+auth_code_result = {"code": None}
+
+
+class OAuthCallbackHandler(http.server.BaseHTTPRequestHandler):
+ def do_GET(self):
+ parsed = urllib.parse.urlparse(self.path)
+ qs = urllib.parse.parse_qs(parsed.query)
+ code = qs.get("code", [None])[0]
+ if code:
+ auth_code_result["code"] = code
+ self.send_response(200)
+ self.send_header("Content-Type", "text/html; charset=utf-8")
+ self.end_headers()
+ self.wfile.write(b"
✔ Google OAuth OK
You can close this tab now.
")
+ else:
+ error = qs.get("error", ["unknown"])[0]
+ self.send_response(400)
+ self.send_header("Content-Type", "text/html")
+ self.end_headers()
+ self.wfile.write(f"Error: {error}
".encode())
+
+ def log_message(self, format, *args):
+ pass
+
+
+def get_oauth_token():
+ """OAuth 授权码流程:系统浏览器授权 → 获取 access_token"""
+ server = http.server.HTTPServer(("localhost", REDIRECT_PORT), OAuthCallbackHandler)
+ server.timeout = 300
+ thread = threading.Thread(target=server.handle_request, daemon=True)
+ thread.start()
+
+ auth_params = urllib.parse.urlencode({
+ "client_id": CLIENT_ID,
+ "redirect_uri": REDIRECT_URI,
+ "response_type": "code",
+ "scope": " ".join(SCOPES),
+ "access_type": "offline",
+ "prompt": "consent",
+ })
+ auth_url = f"https://accounts.google.com/o/oauth2/v2/auth?{auth_params}"
+
+ print(f"\n🔐 正在打开系统浏览器进行 Google 授权...")
+ print(f" (系统浏览器走 Clash 代理,无需额外操作)\n")
+ webbrowser.open(auth_url)
+
+ print("⏳ 等待授权回调...")
+ thread.join(timeout=300)
+ server.server_close()
+
+ code = auth_code_result["code"]
+ if not code:
+ print("❌ 授权超时或失败")
+ sys.exit(1)
+
+ print("✅ 授权码获取成功,兑换 Token...")
+ with httpx.Client(proxy=PROXY, timeout=20) as client:
+ resp = client.post(TOKEN_URL, data={
+ "code": code,
+ "client_id": CLIENT_ID,
+ "client_secret": CLIENT_SECRET,
+ "redirect_uri": REDIRECT_URI,
+ "grant_type": "authorization_code",
+ })
+ if resp.status_code != 200:
+ print(f"❌ Token 兑换失败: {resp.status_code} {resp.text[:200]}")
+ sys.exit(1)
+ tokens = resp.json()
+ print(f"✅ Access Token 获取成功!")
+ return tokens["access_token"]
+
+
+def create_project(token, project_id):
+ """创建 GCP 项目"""
+ with httpx.Client(proxy=PROXY, timeout=30) as client:
+ resp = client.post(
+ PROJECTS_URL,
+ headers={"Authorization": f"Bearer {token}"},
+ json={"projectId": project_id, "name": project_id},
+ )
+ if resp.status_code in (200, 409):
+ if resp.status_code == 409:
+ print(f" 项目 {project_id} 已存在,继续使用")
+ return True
+ print(f" 创建项目失败: {resp.status_code} {resp.text[:200]}")
+ return False
+
+
+def enable_gemini_api(token, project_id):
+ """启用 Generative Language API"""
+ url = SERVICES_URL.format(project_id=project_id)
+ with httpx.Client(proxy=PROXY, timeout=30) as client:
+ resp = client.post(
+ url,
+ headers={"Authorization": f"Bearer {token}"},
+ )
+ if resp.status_code in (200, 409):
+ return True
+ print(f" 启用 API 失败: {resp.status_code} {resp.text[:200]}")
+ return False
+
+
+def wait_for_operation(token, operation_name, max_wait=60):
+ """等待长期运行操作完成"""
+ url = f"https://serviceusage.googleapis.com/v1/{operation_name}"
+ with httpx.Client(proxy=PROXY, timeout=15) as client:
+ for _ in range(max_wait // 3):
+ resp = client.get(url, headers={"Authorization": f"Bearer {token}"})
+ if resp.status_code == 200:
+ data = resp.json()
+ if data.get("done"):
+ return True
+ time.sleep(3)
+ return True
+
+
+def create_api_key(token, project_id, display_name):
+ """创建 API Key 并限制为 Generative Language API"""
+ url = APIKEYS_URL.format(project_id=project_id)
+ with httpx.Client(proxy=PROXY, timeout=30) as client:
+ resp = client.post(
+ url,
+ headers={"Authorization": f"Bearer {token}"},
+ json={
+ "displayName": display_name,
+ "restrictions": {
+ "apiTargets": [{"service": "generativelanguage.googleapis.com"}]
+ },
+ },
+ )
+ if resp.status_code == 200:
+ data = resp.json()
+ operation = data.get("name", "")
+ if "operations/" in operation:
+ time.sleep(3)
+ op_resp = client.get(
+ f"https://apikeys.googleapis.com/v2/{operation}",
+ headers={"Authorization": f"Bearer {token}"},
+ )
+ if op_resp.status_code == 200:
+ op_data = op_resp.json()
+ if op_data.get("done"):
+ key_data = op_data.get("response", {})
+ return key_data.get("keyString", "")
+ time.sleep(5)
+ op_resp2 = client.get(
+ f"https://apikeys.googleapis.com/v2/{operation}",
+ headers={"Authorization": f"Bearer {token}"},
+ )
+ if op_resp2.status_code == 200:
+ return op_resp2.json().get("response", {}).get("keyString", "")
+ return data.get("keyString", "")
+ print(f" 创建 Key 失败: {resp.status_code} {resp.text[:300]}")
+ return None
+
+
+def list_existing_keys(token, project_id):
+ """列出已有的 API Keys"""
+ url = APIKEYS_URL.format(project_id=project_id)
+ with httpx.Client(proxy=PROXY, timeout=15) as client:
+ resp = client.get(url, headers={"Authorization": f"Bearer {token}"})
+ if resp.status_code == 200:
+ return resp.json().get("keys", [])
+ return []
+
+
+def save_key_to_db(api_key, project_id, idx):
+ """保存到 SQLite"""
+ import sqlite3
+ JSON_DIR.mkdir(parents=True, exist_ok=True)
+
+ with sqlite3.connect(str(DB_PATH)) as conn:
+ conn.execute("""
+ CREATE TABLE IF NOT EXISTS accounts (
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
+ provider TEXT NOT NULL,
+ email TEXT NOT NULL,
+ password TEXT DEFAULT '',
+ api_key TEXT DEFAULT '',
+ access_token TEXT DEFAULT '',
+ refresh_token TEXT DEFAULT '',
+ account_id TEXT DEFAULT '',
+ name TEXT DEFAULT '',
+ extra TEXT DEFAULT '{}',
+ registered_at TEXT NOT NULL,
+ status TEXT DEFAULT 'active',
+ UNIQUE(provider, email)
+ )
+ """)
+ from datetime import datetime, timezone
+ now = datetime.now(timezone.utc).isoformat()
+ conn.execute("""
+ INSERT OR REPLACE INTO accounts
+ (provider, email, api_key, name, extra, registered_at, status)
+ VALUES (?, ?, ?, ?, ?, ?, 'active')
+ """, ("gemini", f"gemini_project_{idx}@google.com", api_key,
+ project_id, json.dumps({"project": project_id}), now))
+ conn.commit()
+
+ json_file = JSON_DIR / f"gemini_{project_id}.json"
+ json_file.write_text(json.dumps({
+ "provider": "gemini",
+ "project": project_id,
+ "api_key": api_key,
+ }, indent=2))
+ print(f" 💾 已保存: DB + {json_file.name}")
+
+
+def main():
+ global PROXY
+ parser = argparse.ArgumentParser(description="Gemini API Key 创建器")
+ parser.add_argument("--count", "-n", type=int, default=3, help="创建 Key 数量")
+ parser.add_argument("--proxy", default=PROXY, help="代理地址")
+ args = parser.parse_args()
+
+ PROXY = args.proxy
+
+ print("=" * 60)
+ print(f"🔑 Gemini API Key 创建器")
+ print(f" 目标: 创建 {args.count} 个 Gemini API Key")
+ print(f" 代理: {PROXY}")
+ print("=" * 60)
+
+ token = get_oauth_token()
+
+ keys_created = []
+ for i in range(1, args.count + 1):
+ suffix = "".join(random.choices(string.ascii_lowercase + string.digits, k=6))
+ project_id = f"gemini-auto-{suffix}"
+ display_name = f"gemini-key-{i}"
+
+ print(f"\n--- 创建第 {i}/{args.count} 个 Key ---")
+
+ print(f" [1/3] 创建项目: {project_id}")
+ if not create_project(token, project_id):
+ print(f" ⚠️ 跳过此 Key")
+ continue
+
+ print(f" [2/3] 启用 Generative Language API")
+ time.sleep(2)
+ enable_gemini_api(token, project_id)
+ time.sleep(5)
+
+ print(f" [3/3] 创建 API Key: {display_name}")
+ api_key = create_api_key(token, project_id, display_name)
+
+ if api_key:
+ print(f" ✅ Key {i}: {api_key}")
+ keys_created.append({"key": api_key, "project": project_id})
+ save_key_to_db(api_key, project_id, i)
+ else:
+ print(f" ❌ Key 创建失败,尝试列出已有 Key...")
+ existing = list_existing_keys(token, project_id)
+ for k in existing:
+ ks = k.get("keyString")
+ if ks:
+ print(f" ✅ 找到已有 Key: {ks}")
+ keys_created.append({"key": ks, "project": project_id})
+ save_key_to_db(ks, project_id, i)
+ break
+
+ print(f"\n{'='*60}")
+ print(f"🎉 完成! 创建了 {len(keys_created)}/{args.count} 个 Gemini API Key")
+ for idx, kd in enumerate(keys_created, 1):
+ print(f" Key {idx}: {kd['key']}")
+ print(f" Project: {kd['project']}")
+ if keys_created:
+ print(f"\n测试命令:")
+ k = keys_created[0]["key"]
+ print(f' curl -x {PROXY} "https://generativelanguage.googleapis.com/v1beta/models?key={k}"')
+ print(f"\n存储: {DB_PATH} + {JSON_DIR}/")
+ print(f"{'='*60}")
+
+
+if __name__ == "__main__":
+ main()
diff --git a/03_卡木(木)/木根_逆向分析/全网AI自动注册/脚本/google_device_auth.py b/03_卡木(木)/木根_逆向分析/全网AI自动注册/脚本/google_device_auth.py
new file mode 100644
index 00000000..012d7f4c
--- /dev/null
+++ b/03_卡木(木)/木根_逆向分析/全网AI自动注册/脚本/google_device_auth.py
@@ -0,0 +1,157 @@
+#!/usr/bin/env python3
+"""Google Device Flow 授权 + 创建 3 个 Gemini API Key"""
+
+import httpx, time, json, sys, random, string, sqlite3
+from pathlib import Path
+from datetime import datetime, timezone
+
+PROXY = "http://127.0.0.1:7897"
+CLIENT_ID = "764086051850-6qr4p6gpi6hn506pt8ejuq83di341hur.apps.googleusercontent.com"
+CLIENT_SECRET = "d-FL95Q19q7MQmFpd7hHD0Ty"
+SCOPES = "https://www.googleapis.com/auth/cloud-platform"
+DB_PATH = Path(__file__).parent / "accounts.db"
+JSON_DIR = Path(__file__).parent / "tokens"
+COUNT = int(sys.argv[1]) if len(sys.argv) > 1 else 3
+
+
+def save_key(api_key, project_id, idx):
+ JSON_DIR.mkdir(parents=True, exist_ok=True)
+ with sqlite3.connect(str(DB_PATH)) as conn:
+ conn.execute("""CREATE TABLE IF NOT EXISTS accounts (
+ id INTEGER PRIMARY KEY AUTOINCREMENT, provider TEXT NOT NULL,
+ email TEXT NOT NULL, password TEXT DEFAULT '', api_key TEXT DEFAULT '',
+ access_token TEXT DEFAULT '', refresh_token TEXT DEFAULT '',
+ account_id TEXT DEFAULT '', name TEXT DEFAULT '', extra TEXT DEFAULT '{}',
+ registered_at TEXT NOT NULL, status TEXT DEFAULT 'active',
+ UNIQUE(provider, email))""")
+ now = datetime.now(timezone.utc).isoformat()
+ conn.execute("INSERT OR REPLACE INTO accounts (provider,email,api_key,name,extra,registered_at,status) VALUES (?,?,?,?,?,?,'active')",
+ ("gemini", f"gemini_{project_id}@gcp", api_key, project_id, json.dumps({"project": project_id}), now))
+ conn.commit()
+ (JSON_DIR / f"gemini_{project_id}.json").write_text(json.dumps({"provider":"gemini","project":project_id,"api_key":api_key}, indent=2))
+
+
+def main():
+ sep = "=" * 50
+ print(sep)
+ print("Gemini API Key Creator (Device Flow)")
+ print(f"Target: {COUNT} keys | Proxy: {PROXY}")
+ print(sep)
+
+ # Step 1: Device Flow
+ print("\n[Step 1] Google Device Flow...")
+ with httpx.Client(proxy=PROXY, timeout=15) as c:
+ r = c.post("https://oauth2.googleapis.com/device/code", data={"client_id": CLIENT_ID, "scope": SCOPES})
+ print(f"Status: {r.status_code}")
+ if r.status_code != 200:
+ print(f"Failed: {r.text[:300]}")
+ return
+
+ d = r.json()
+ user_code = d["user_code"]
+ verify_url = d["verification_url"]
+ device_code = d["device_code"]
+ interval = d.get("interval", 5)
+
+ print(f"\n{sep}")
+ print(f"Open in ANY browser/phone: {verify_url}")
+ print(f"Enter code: {user_code}")
+ print(f"{sep}\n")
+ print("Waiting for authorization...")
+
+ import webbrowser
+ webbrowser.open(verify_url)
+
+ token = None
+ for i in range(120):
+ time.sleep(interval)
+ tr = c.post("https://oauth2.googleapis.com/token", data={
+ "client_id": CLIENT_ID, "client_secret": CLIENT_SECRET,
+ "device_code": device_code, "grant_type": "urn:ietf:params:oauth:grant-type:device_code"})
+ td = tr.json()
+ if "access_token" in td:
+ token = td["access_token"]
+ print(f"\nAuthorized! Token: {token[:25]}...")
+ break
+ err = td.get("error")
+ if err == "authorization_pending":
+ if i % 12 == 0 and i > 0:
+ print(f" Still waiting... ({i*interval}s)")
+ elif err == "slow_down":
+ time.sleep(5)
+ else:
+ print(f"Error: {td}")
+ return
+
+ if not token:
+ print("Timeout!")
+ return
+
+ # Step 2: Create projects and keys
+ print(f"\n[Step 2] Creating {COUNT} Gemini API Keys...")
+ keys = []
+ with httpx.Client(proxy=PROXY, timeout=30) as c:
+ headers = {"Authorization": f"Bearer {token}"}
+ for i in range(1, COUNT + 1):
+ sfx = "".join(random.choices(string.ascii_lowercase + string.digits, k=6))
+ pid = f"gemini-auto-{sfx}"
+ print(f"\n Key {i}/{COUNT}: project={pid}")
+
+ # Create project
+ pr = c.post("https://cloudresourcemanager.googleapis.com/v1/projects",
+ headers=headers, json={"projectId": pid, "name": pid})
+ print(f" Create project: {pr.status_code}")
+ if pr.status_code not in (200, 409):
+ print(f" Failed: {pr.text[:200]}")
+ continue
+
+ time.sleep(3)
+
+ # Enable API
+ er = c.post(f"https://serviceusage.googleapis.com/v1/projects/{pid}/services/generativelanguage.googleapis.com:enable",
+ headers=headers)
+ print(f" Enable API: {er.status_code}")
+ time.sleep(5)
+
+ # Create API key
+ kr = c.post(f"https://apikeys.googleapis.com/v2/projects/{pid}/locations/global/keys",
+ headers=headers, json={"displayName": f"gemini-key-{i}",
+ "restrictions": {"apiTargets": [{"service": "generativelanguage.googleapis.com"}]}})
+ print(f" Create key: {kr.status_code}")
+
+ if kr.status_code == 200:
+ kd = kr.json()
+ op_name = kd.get("name", "")
+ if "operations/" in op_name:
+ for _ in range(10):
+ time.sleep(3)
+ or2 = c.get(f"https://apikeys.googleapis.com/v2/{op_name}", headers=headers)
+ if or2.status_code == 200:
+ od = or2.json()
+ if od.get("done"):
+ ks = od.get("response", {}).get("keyString", "")
+ if ks:
+ print(f" KEY: {ks}")
+ keys.append({"key": ks, "project": pid})
+ save_key(ks, pid, i)
+ break
+ else:
+ ks = kd.get("keyString", "")
+ if ks:
+ print(f" KEY: {ks}")
+ keys.append({"key": ks, "project": pid})
+ save_key(ks, pid, i)
+ else:
+ print(f" Failed: {kr.text[:300]}")
+
+ print(f"\n{sep}")
+ print(f"Done! {len(keys)}/{COUNT} keys created")
+ for idx, k in enumerate(keys, 1):
+ print(f" {idx}. {k['key']} (project: {k['project']})")
+ if keys:
+ print(f"\nTest: curl -x {PROXY} 'https://generativelanguage.googleapis.com/v1beta/models?key={keys[0]['key']}'")
+ print(sep)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/03_卡木(木)/木根_逆向分析/全网API自动注册/脚本/key_manager_api.py b/03_卡木(木)/木根_逆向分析/全网AI自动注册/脚本/key_manager_api.py
similarity index 100%
rename from 03_卡木(木)/木根_逆向分析/全网API自动注册/脚本/key_manager_api.py
rename to 03_卡木(木)/木根_逆向分析/全网AI自动注册/脚本/key_manager_api.py
diff --git a/03_卡木(木)/木根_逆向分析/全网AI自动注册/脚本/register_gemini_keys.py b/03_卡木(木)/木根_逆向分析/全网AI自动注册/脚本/register_gemini_keys.py
new file mode 100644
index 00000000..6af0c9dd
--- /dev/null
+++ b/03_卡木(木)/木根_逆向分析/全网AI自动注册/脚本/register_gemini_keys.py
@@ -0,0 +1,271 @@
+#!/usr/bin/env python3
+"""
+Gemini API Key 自动注册脚本
+1. 通过 Clash 代理打开 Google AI Studio(非无头模式,你手动登录 Google)
+2. 登录完成后脚本自动创建指定数量的 API Key
+3. Key 存入本地 SQLite + JSON
+
+用法: python3 register_gemini_keys.py --count 3
+"""
+
+import argparse
+import json
+import os
+import re
+import sys
+import time
+from pathlib import Path
+from datetime import datetime, timezone
+
+PROXY_SERVER = "http://127.0.0.1:7897"
+AI_STUDIO_URL = "https://aistudio.google.com/app/apikey"
+DB_PATH = Path(__file__).parent / "accounts.db"
+JSON_DIR = Path(__file__).parent / "tokens"
+
+
+def save_key(provider, email, api_key, project_name=""):
+ """保存到 SQLite + JSON"""
+ import sqlite3
+ JSON_DIR.mkdir(parents=True, exist_ok=True)
+
+ with sqlite3.connect(str(DB_PATH)) as conn:
+ conn.execute("""
+ CREATE TABLE IF NOT EXISTS accounts (
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
+ provider TEXT NOT NULL,
+ email TEXT NOT NULL,
+ password TEXT DEFAULT '',
+ api_key TEXT DEFAULT '',
+ access_token TEXT DEFAULT '',
+ refresh_token TEXT DEFAULT '',
+ account_id TEXT DEFAULT '',
+ name TEXT DEFAULT '',
+ extra TEXT DEFAULT '{}',
+ registered_at TEXT NOT NULL,
+ status TEXT DEFAULT 'active',
+ UNIQUE(provider, email)
+ )
+ """)
+ now = datetime.now(timezone.utc).isoformat()
+ conn.execute("""
+ INSERT OR REPLACE INTO accounts
+ (provider, email, api_key, name, extra, registered_at, status)
+ VALUES (?, ?, ?, ?, ?, ?, 'active')
+ """, (provider, email, api_key, project_name, json.dumps({"project": project_name}), now))
+ conn.commit()
+
+ safe_email = email.replace("@", "_at_")
+ json_file = JSON_DIR / f"gemini_{safe_email}_{int(time.time())}.json"
+ json_file.write_text(json.dumps({
+ "provider": "gemini",
+ "email": email,
+ "api_key": api_key,
+ "project": project_name,
+ "registered_at": datetime.now(timezone.utc).isoformat(),
+ }, indent=2, ensure_ascii=False))
+ print(f" [保存] {json_file.name}")
+
+
+def main():
+ parser = argparse.ArgumentParser(description="Gemini API Key 自动注册")
+ parser.add_argument("--count", "-n", type=int, default=3, help="要创建的 Key 数量")
+ parser.add_argument("--proxy", default=PROXY_SERVER, help="代理地址")
+ args = parser.parse_args()
+
+ from playwright.sync_api import sync_playwright
+
+ print(f"🚀 启动浏览器(代理: {args.proxy})")
+ print(f"📋 目标: 创建 {args.count} 个 Gemini API Key\n")
+
+ pw = sync_playwright().start()
+ browser = pw.chromium.launch(
+ headless=False,
+ proxy={"server": args.proxy},
+ args=["--window-size=1280,900"],
+ )
+ context = browser.new_context(
+ viewport={"width": 1280, "height": 900},
+ locale="en-US",
+ )
+ page = context.new_page()
+
+ print("📂 打开 Google AI Studio...")
+ page.goto(AI_STUDIO_URL, timeout=30000)
+ time.sleep(2)
+
+ if "accounts.google.com" in page.url:
+ print("\n" + "=" * 60)
+ print("⚠️ 请在弹出的浏览器窗口中登录你的 Google 账号")
+ print(" 登录完成后脚本会自动继续...")
+ print("=" * 60 + "\n")
+
+ for i in range(300):
+ time.sleep(2)
+ current = page.url
+ # 必须是真正到达 aistudio,而非 accounts.google.com 里的 continue 参数
+ if current.startswith("https://aistudio.google.com"):
+ print("✅ 登录成功!已进入 AI Studio")
+ break
+ if i % 15 == 0 and i > 0:
+ print(f" 等待登录中... ({i*2}秒)")
+ else:
+ print("❌ 登录超时(10分钟),请重试")
+ browser.close()
+ pw.stop()
+ return
+
+ time.sleep(3)
+ print(f"\n当前页面: {page.url}")
+
+ if "/apikey" not in page.url:
+ page.goto(AI_STUDIO_URL, timeout=20000)
+ time.sleep(3)
+
+ keys_created = []
+
+ for i in range(args.count):
+ print(f"\n--- 创建第 {i+1}/{args.count} 个 Key ---")
+
+ try:
+ page.wait_for_load_state("networkidle", timeout=10000)
+ except Exception:
+ pass
+
+ create_btn = None
+ for selector in [
+ "button:has-text('Create API key')",
+ "button:has-text('Create API Key')",
+ "button:has-text('创建 API 密钥')",
+ "[aria-label='Create API key']",
+ "button:has-text('Get API key')",
+ "button:has-text('获取 API 密钥')",
+ ]:
+ try:
+ btn = page.locator(selector).first
+ if btn.is_visible(timeout=3000):
+ create_btn = btn
+ break
+ except Exception:
+ continue
+
+ if not create_btn:
+ print(" ⚠️ 未找到 Create API Key 按钮,尝试截图诊断...")
+ page.screenshot(path=str(JSON_DIR / f"debug_step_{i+1}.png"))
+ snapshot = page.content()
+ if "Create" in snapshot or "创建" in snapshot:
+ print(" 页面包含创建按钮文字,尝试通用点击...")
+ try:
+ page.locator("button").filter(has_text=re.compile(r"Create|创建|Get|获取")).first.click()
+ except Exception as e:
+ print(f" 点击失败: {e}")
+ continue
+ else:
+ print(f" 页面 URL: {page.url}")
+ continue
+ else:
+ create_btn.click()
+
+ time.sleep(2)
+
+ new_project_btn = None
+ for selector in [
+ "button:has-text('Create API key in new project')",
+ "button:has-text('在新项目中创建 API 密钥')",
+ "text='Create API key in new project'",
+ "button:has-text('new project')",
+ ]:
+ try:
+ btn = page.locator(selector).first
+ if btn.is_visible(timeout=3000):
+ new_project_btn = btn
+ break
+ except Exception:
+ continue
+
+ if new_project_btn:
+ new_project_btn.click()
+ print(" 点击了 'Create in new project'")
+ else:
+ existing_btns = page.locator("button:has-text('Create')").all()
+ for btn in existing_btns:
+ try:
+ if btn.is_visible():
+ btn.click()
+ break
+ except Exception:
+ continue
+
+ time.sleep(5)
+
+ api_key = None
+ for attempt in range(10):
+ page_text = page.content()
+ matches = re.findall(r'AIzaSy[A-Za-z0-9_-]{33}', page_text)
+ if matches:
+ api_key = matches[0]
+ break
+
+ try:
+ code_el = page.locator("code, .api-key, [data-testid*='key'], pre").first
+ if code_el.is_visible(timeout=1000):
+ text = code_el.inner_text()
+ m = re.search(r'AIzaSy[A-Za-z0-9_-]{33}', text)
+ if m:
+ api_key = m.group(0)
+ break
+ except Exception:
+ pass
+
+ copy_btns = page.locator("button:has-text('Copy')").all()
+ if not copy_btns:
+ copy_btns = page.locator("button:has-text('复制')").all()
+ for btn in copy_btns:
+ try:
+ if btn.is_visible():
+ btn.click()
+ time.sleep(0.5)
+ break
+ except Exception:
+ pass
+
+ time.sleep(1)
+ if attempt % 3 == 2:
+ print(f" 等待 Key 生成... (尝试 {attempt+1})")
+
+ if api_key:
+ print(f" ✅ Key {i+1}: {api_key[:20]}...")
+ keys_created.append(api_key)
+ save_key("gemini", f"gemini_project_{i+1}@google.com", api_key, f"project_{i+1}")
+ else:
+ print(f" ❌ 未能提取到 API Key,请检查浏览器窗口")
+ page.screenshot(path=str(JSON_DIR / f"failed_key_{i+1}.png"))
+
+ close_btns = page.locator("button:has-text('Done'), button:has-text('Close'), button:has-text('完成'), button:has-text('关闭')").all()
+ for btn in close_btns:
+ try:
+ if btn.is_visible():
+ btn.click()
+ break
+ except Exception:
+ pass
+ time.sleep(2)
+
+ if "/apikey" not in page.url:
+ page.goto(AI_STUDIO_URL, timeout=15000)
+ time.sleep(3)
+
+ print(f"\n{'='*60}")
+ print(f"🎉 完成! 成功创建 {len(keys_created)}/{args.count} 个 Gemini API Key")
+ for idx, key in enumerate(keys_created, 1):
+ print(f" Key {idx}: {key}")
+ print(f"\n存储位置: {DB_PATH}")
+ print(f"JSON 目录: {JSON_DIR}")
+ print(f"{'='*60}")
+
+ input("\n按 Enter 关闭浏览器...")
+ browser.close()
+ pw.stop()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/03_卡木(木)/木根_逆向分析/全网API自动注册/脚本/requirements.txt b/03_卡木(木)/木根_逆向分析/全网AI自动注册/脚本/requirements.txt
similarity index 100%
rename from 03_卡木(木)/木根_逆向分析/全网API自动注册/脚本/requirements.txt
rename to 03_卡木(木)/木根_逆向分析/全网AI自动注册/脚本/requirements.txt
diff --git a/03_卡木(木)/木根_逆向分析/全网AI自动注册/脚本/tokens/debug_step_1.png b/03_卡木(木)/木根_逆向分析/全网AI自动注册/脚本/tokens/debug_step_1.png
new file mode 100644
index 00000000..c2f0f2a1
Binary files /dev/null and b/03_卡木(木)/木根_逆向分析/全网AI自动注册/脚本/tokens/debug_step_1.png differ
diff --git a/03_卡木(木)/木根_逆向分析/全网AI自动注册/脚本/tokens/debug_step_2.png b/03_卡木(木)/木根_逆向分析/全网AI自动注册/脚本/tokens/debug_step_2.png
new file mode 100644
index 00000000..c2f0f2a1
Binary files /dev/null and b/03_卡木(木)/木根_逆向分析/全网AI自动注册/脚本/tokens/debug_step_2.png differ
diff --git a/03_卡木(木)/木根_逆向分析/全网AI自动注册/脚本/tokens/debug_step_3.png b/03_卡木(木)/木根_逆向分析/全网AI自动注册/脚本/tokens/debug_step_3.png
new file mode 100644
index 00000000..d82a5727
Binary files /dev/null and b/03_卡木(木)/木根_逆向分析/全网AI自动注册/脚本/tokens/debug_step_3.png differ
diff --git a/03_卡木(木)/木根_逆向分析/全网AI自动注册/脚本/tokens/gemini_gemini_project_1_at_google.com_1773573688.json b/03_卡木(木)/木根_逆向分析/全网AI自动注册/脚本/tokens/gemini_gemini_project_1_at_google.com_1773573688.json
new file mode 100644
index 00000000..3792e0a2
--- /dev/null
+++ b/03_卡木(木)/木根_逆向分析/全网AI自动注册/脚本/tokens/gemini_gemini_project_1_at_google.com_1773573688.json
@@ -0,0 +1,7 @@
+{
+ "provider": "gemini",
+ "email": "gemini_project_1@google.com",
+ "api_key": "AIzaSyA6RHlWHTfUEqMzdfQQQSmugsGcoDIxnAg",
+ "project": "project_1",
+ "registered_at": "2026-03-15T11:21:28.308260+00:00"
+}
\ No newline at end of file
diff --git a/03_卡木(木)/木根_逆向分析/全网AI自动注册/脚本/tokens/gemini_gemini_project_1_at_google.com_1773573760.json b/03_卡木(木)/木根_逆向分析/全网AI自动注册/脚本/tokens/gemini_gemini_project_1_at_google.com_1773573760.json
new file mode 100644
index 00000000..340126e3
--- /dev/null
+++ b/03_卡木(木)/木根_逆向分析/全网AI自动注册/脚本/tokens/gemini_gemini_project_1_at_google.com_1773573760.json
@@ -0,0 +1,7 @@
+{
+ "provider": "gemini",
+ "email": "gemini_project_1@google.com",
+ "api_key": "AIzaSyA6RHlWHTfUEqMzdfQQQSmugsGcoDIxnAg",
+ "project": "project_1",
+ "registered_at": "2026-03-15T11:22:40.294576+00:00"
+}
\ No newline at end of file
diff --git a/03_卡木(木)/木根_逆向分析/全网AI自动注册/脚本/tokens/gemini_gemini_project_2_at_google.com_1773573702.json b/03_卡木(木)/木根_逆向分析/全网AI自动注册/脚本/tokens/gemini_gemini_project_2_at_google.com_1773573702.json
new file mode 100644
index 00000000..13f8b8ce
--- /dev/null
+++ b/03_卡木(木)/木根_逆向分析/全网AI自动注册/脚本/tokens/gemini_gemini_project_2_at_google.com_1773573702.json
@@ -0,0 +1,7 @@
+{
+ "provider": "gemini",
+ "email": "gemini_project_2@google.com",
+ "api_key": "AIzaSyA6RHlWHTfUEqMzdfQQQSmugsGcoDIxnAg",
+ "project": "project_2",
+ "registered_at": "2026-03-15T11:21:42.299331+00:00"
+}
\ No newline at end of file
diff --git a/03_卡木(木)/木根_逆向分析/全网AI自动注册/脚本/tokens/gemini_gemini_project_2_at_google.com_1773573774.json b/03_卡木(木)/木根_逆向分析/全网AI自动注册/脚本/tokens/gemini_gemini_project_2_at_google.com_1773573774.json
new file mode 100644
index 00000000..8a5daa5a
--- /dev/null
+++ b/03_卡木(木)/木根_逆向分析/全网AI自动注册/脚本/tokens/gemini_gemini_project_2_at_google.com_1773573774.json
@@ -0,0 +1,7 @@
+{
+ "provider": "gemini",
+ "email": "gemini_project_2@google.com",
+ "api_key": "AIzaSyA6RHlWHTfUEqMzdfQQQSmugsGcoDIxnAg",
+ "project": "project_2",
+ "registered_at": "2026-03-15T11:22:54.880143+00:00"
+}
\ No newline at end of file
diff --git a/03_卡木(木)/木根_逆向分析/全网AI自动注册/脚本/tokens/gemini_gemini_project_3_at_google.com_1773573717.json b/03_卡木(木)/木根_逆向分析/全网AI自动注册/脚本/tokens/gemini_gemini_project_3_at_google.com_1773573717.json
new file mode 100644
index 00000000..7b6e2aa9
--- /dev/null
+++ b/03_卡木(木)/木根_逆向分析/全网AI自动注册/脚本/tokens/gemini_gemini_project_3_at_google.com_1773573717.json
@@ -0,0 +1,7 @@
+{
+ "provider": "gemini",
+ "email": "gemini_project_3@google.com",
+ "api_key": "AIzaSyA6RHlWHTfUEqMzdfQQQSmugsGcoDIxnAg",
+ "project": "project_3",
+ "registered_at": "2026-03-15T11:21:57.080669+00:00"
+}
\ No newline at end of file
diff --git a/03_卡木(木)/木根_逆向分析/全网AI自动注册/脚本/tokens/gemini_gemini_project_3_at_google.com_1773573789.json b/03_卡木(木)/木根_逆向分析/全网AI自动注册/脚本/tokens/gemini_gemini_project_3_at_google.com_1773573789.json
new file mode 100644
index 00000000..1e3a383d
--- /dev/null
+++ b/03_卡木(木)/木根_逆向分析/全网AI自动注册/脚本/tokens/gemini_gemini_project_3_at_google.com_1773573789.json
@@ -0,0 +1,7 @@
+{
+ "provider": "gemini",
+ "email": "gemini_project_3@google.com",
+ "api_key": "AIzaSyA6RHlWHTfUEqMzdfQQQSmugsGcoDIxnAg",
+ "project": "project_3",
+ "registered_at": "2026-03-15T11:23:09.014341+00:00"
+}
\ No newline at end of file
diff --git a/04_卡火(火)/火炬_全栈消息/全栈开发/SKILL.md b/04_卡火(火)/火炬_全栈消息/全栈开发/SKILL.md
index 8a045678..d9d05885 100644
--- a/04_卡火(火)/火炬_全栈消息/全栈开发/SKILL.md
+++ b/04_卡火(火)/火炬_全栈消息/全栈开发/SKILL.md
@@ -4,8 +4,8 @@ description: 卡若AI 全栈开发(火炬)— 知己及类似项目经验 +
triggers: 全栈开发/知己项目/分销/存客宝/RAG/向量化/Next.js/知识库/卡若AI官网/官网开发/全站开发/开发文档/1~10/开发模板/官网全站/v0前端/v0生成/毛玻璃/前端规格/神射手/毛狐狸/前端标准/实施计划/两阶段评审/橙色锁/配色/API调用/使用手册
owner: 火炬
group: 火
-version: "2.4"
-updated: "2026-03-12"
+version: "2.5"
+updated: "2026-03-15"
---
# 全栈开发(火炬)
@@ -125,6 +125,75 @@ updated: "2026-03-12"
**协同**:Word/文档类清洗用火炬「文档清洗」;部署到 v0、同步 GitHub/Vercel 用金盾「Vercel与v0部署流水线」。
+### 1.10 埋点统计(全站强制,2026-03-15 沉淀)
+
+**任何新功能、新页面、新按钮上线时,必须同步接入埋点统计。** 这是全站开发的标准动作,与功能代码同等重要。
+
+#### 为什么强制
+
+没有埋点 = 没有数据 = 无法判断功能是否有效。上线后再补埋点往往遗漏大量初期行为数据。**先埋点、再发布** 是卡若AI 全站的铁律。
+
+#### 标准架构(三层)
+
+```
+前端(小程序/Web) 后端 API 管理后台
+trackClick(module, → POST /api/{平台}/track → GET /api/admin/track/stats
+ action, target, extra) 存入 user_tracks 表 按 module/action/时间段聚合
+```
+
+#### 数据模型(user_tracks 表)
+
+| 字段 | 类型 | 说明 |
+|:---|:---|:---|
+| id | string/UUID | 主键 |
+| user_id | string | 用户 ID |
+| action | string | 动作类型:`btn_click` / `page_view` / `tab_click` / `share` / `nav_click` |
+| target | string | 具体目标:按钮名、页面名、分享类型 |
+| extra_data | JSONB | 扩展信息,**必须包含 `module`(所属模块)和 `page`(页面标识)** |
+| created_at | timestamp | 自动时间戳 |
+
+#### 前端埋点工具标准(以小程序为例)
+
+```javascript
+// utils/trackClick.js
+function trackClick(module, action, target, extra) {
+ const userId = app.globalData.userInfo?.id || ''
+ if (!userId) return
+ app.request('/api/miniprogram/track', {
+ method: 'POST',
+ data: {
+ userId, action, target,
+ extraData: Object.assign({ module, page: module }, extra || {})
+ },
+ silent: true
+ }).catch(() => {})
+}
+```
+
+Web 端同理,封装为 `trackClick(module, action, target)` 函数,通过 fetch 静默上报。
+
+#### 埋点接入检查清单
+
+每开发一个页面/功能,按此清单逐项确认:
+
+- [ ] 页面所有**可点击按钮/标签**都已调用 `trackClick`
+- [ ] `module` 参数使用统一命名(home / chapters / read / my / vip / wallet / match / referral / search / settings)
+- [ ] `action` 参数使用标准动词(`btn_click` / `page_view` / `tab_click` / `nav_click` / `share`)
+- [ ] `target` 参数能区分具体按钮(如 `购买VIP`、`充值`、`阅读第3章`)
+- [ ] 后端 track API 已注册路由并能正确存储 `extra_data`
+- [ ] 管理后台「分类标签点击统计」面板能展示该模块的数据
+
+#### 管理后台展示标准
+
+管理后台数据概览页须包含「分类标签点击统计」面板:
+- 支持时间段筛选(今日 / 本周 / 本月 / 全部)
+- 按 module 分组展示,每个模块显示 top N 点击项
+- 自动 30 秒刷新
+
+#### 经验来源
+
+Soul 创业实验项目(2026-03-15)首次实施全站埋点,覆盖小程序 9 个页面 + 管理后台统计面板 + 后端聚合 API。详见 `运营中枢/参考资料/项目经验库_知己与类似项目.md`。
+
---
## 二、项目经验库(知己类,必读)
@@ -190,6 +259,7 @@ scripts/
| **前端开发/前端标准_神射手与毛狐狸** | 布局/颜色/毛玻璃/组件/特效统一标准,所有项目前端开发参考 |
| **神射手 开发文档 4、前端** | 神射手项目内前端规范、核心组件代码、截图索引 |
| **Superpowers与全栈开发对比与优化建议** | `运营中枢/参考资料/Superpowers与全栈开发对比与优化建议.md` — 计划粒度、TDD、两阶段评审、分支收尾等优化方向 |
+| **埋点统计标准(Soul项目沉淀)** | 全站埋点三层架构:前端 trackClick → 后端 track API → 管理后台聚合面板;2026-03-15 Soul 创业实验项目首次实施,见本 Skill 1.10 节 |
---
diff --git a/SKILL_REGISTRY.md b/SKILL_REGISTRY.md
index 625dbca5..5ce82bf9 100644
--- a/SKILL_REGISTRY.md
+++ b/SKILL_REGISTRY.md
@@ -110,7 +110,7 @@
| M01g | 快手发布 | 木叶 | **快手发布、发布到快手、快手登录、快手上传、kuaishou发布** | `03_卡木(木)/木叶_视频内容/快手发布/SKILL.md` | 逆向 cp.kuaishou.com API 视频发布 |
| M01h | 多平台分发 | 木叶 | **多平台分发、一键分发、全平台发布、批量分发、视频分发** | `03_卡木(木)/木叶_视频内容/多平台分发/SKILL.md` | 一键分发到5平台(抖音/B站/视频号/小红书/快手),Cookie统一管理 |
| M02 | 网站逆向分析 | 木根 | 逆向分析、模拟登录 | `03_卡木(木)/木根_逆向分析/网站逆向分析/SKILL.md` | 网站 API 分析、SDK 生成 |
-| M02a | **全网API自动注册** | 木根 | **API注册、自动注册、批量注册、API Key、注册账号、免费API、API池、key池、自动开号** | `03_卡木(木)/木根_逆向分析/全网API自动注册/SKILL.md` | OpenAI/Cursor/Gemini/Groq 等全网 API 自动注册+Key 池管理 |
+| M02a | **全网AI自动注册** | 木根 | **AI注册、自动注册、批量注册、API Key、注册账号、免费API、API池、key池、自动开号、Gemini注册** | `03_卡木(木)/木根_逆向分析/全网AI自动注册/SKILL.md` | OpenAI/Cursor/Gemini/Groq 等全网 AI API 自动注册+Key 池管理 |
| M03 | 项目生成 | 木果 | 生成项目、五行模板 | `03_卡木(木)/木果_项目模板/项目生成/SKILL.md` | 按五行模板生成新项目 |
| M04 | 开发模板 | 木果 | 创建项目、初始化模板 | `03_卡木(木)/木果_项目模板/开发模板/SKILL.md` | 前后端项目模板库 |
| M05 | 个人档案生成器 | 木果 | 个人档案、档案生成 | `03_卡木(木)/木果_项目模板/个人档案生成器/SKILL.md` | 自动生成个人介绍档案 |
diff --git a/运营中枢/工作台/gitea_push_log.md b/运营中枢/工作台/gitea_push_log.md
index 76b65b61..cb346965 100644
--- a/运营中枢/工作台/gitea_push_log.md
+++ b/运营中枢/工作台/gitea_push_log.md
@@ -360,3 +360,4 @@
| 2026-03-15 12:31:12 | 🔄 卡若AI 同步 2026-03-15 12:31 | 更新:金仓、运营中枢工作台 | 排除 >20MB: 11 个 |
| 2026-03-15 15:48:32 | 🔄 卡若AI 同步 2026-03-15 15:48 | 更新:运营中枢工作台 | 排除 >20MB: 11 个 |
| 2026-03-15 16:00:52 | 🔄 卡若AI 同步 2026-03-15 16:00 | 更新:运营中枢工作台 | 排除 >20MB: 11 个 |
+| 2026-03-15 19:00:56 | 🔄 卡若AI 同步 2026-03-15 19:00 | 更新:卡木、总索引与入口、运营中枢工作台 | 排除 >20MB: 11 个 |
diff --git a/运营中枢/工作台/代码管理.md b/运营中枢/工作台/代码管理.md
index 4b2a1b8b..3b81923e 100644
--- a/运营中枢/工作台/代码管理.md
+++ b/运营中枢/工作台/代码管理.md
@@ -363,3 +363,4 @@
| 2026-03-15 12:31:12 | 成功 | 成功 | 🔄 卡若AI 同步 2026-03-15 12:31 | 更新:金仓、运营中枢工作台 | 排除 >20MB: 11 个 | [仓库](http://open.quwanzhi.com:3000/fnvtk/karuo-ai) [百科](http://open.quwanzhi.com:3000/fnvtk/karuo-ai/wiki) |
| 2026-03-15 15:48:32 | 成功 | 成功 | 🔄 卡若AI 同步 2026-03-15 15:48 | 更新:运营中枢工作台 | 排除 >20MB: 11 个 | [仓库](http://open.quwanzhi.com:3000/fnvtk/karuo-ai) [百科](http://open.quwanzhi.com:3000/fnvtk/karuo-ai/wiki) |
| 2026-03-15 16:00:52 | 成功 | 成功 | 🔄 卡若AI 同步 2026-03-15 16:00 | 更新:运营中枢工作台 | 排除 >20MB: 11 个 | [仓库](http://open.quwanzhi.com:3000/fnvtk/karuo-ai) [百科](http://open.quwanzhi.com:3000/fnvtk/karuo-ai/wiki) |
+| 2026-03-15 19:00:56 | 成功 | 成功 | 🔄 卡若AI 同步 2026-03-15 19:00 | 更新:卡木、总索引与入口、运营中枢工作台 | 排除 >20MB: 11 个 | [仓库](http://open.quwanzhi.com:3000/fnvtk/karuo-ai) [百科](http://open.quwanzhi.com:3000/fnvtk/karuo-ai/wiki) |