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) |