diff --git a/01_卡资(金)/金仓_存储备份/分布式算力管控/SKILL.md b/01_卡资(金)/金仓_存储备份/分布式算力管控/SKILL.md
index da9b2094..f99f1fe5 100644
--- a/01_卡资(金)/金仓_存储备份/分布式算力管控/SKILL.md
+++ b/01_卡资(金)/金仓_存储备份/分布式算力管控/SKILL.md
@@ -170,9 +170,8 @@ remote_port = 18882
| 名称 | IP | 端口 | 用户名 | 密码 | 用途 |
|:---|:---|:---|:---|:---|:---|
-| 小型宝塔 | 42.194.232.22 | 22 | root | Zhiqun1984 | 主力Node部署 |
| 存客宝 | 42.194.245.239 | 22 | root | Zhiqun1984 | 私域银行 |
-| kr宝塔 | 43.139.27.93 | 22 | root | Zhiqun1984 | 辅助服务 |
+| kr宝塔 | 43.139.27.93 | 22022 | root | Zhiqun1984 | Node/辅助 |
| 公司NAS(CKB) | 192.168.1.201 | 22 | fnvtk | (SSH密钥) | 群晖NAS |
| 家里NAS(Station) | 192.168.110.29 | 22 | admin | zhiqun1984 | 家庭NAS(DS213j,armv7l) |
@@ -427,7 +426,6 @@ OWN_INFRASTRUCTURE = {
# 云服务器(腾讯云)
"cloud_servers": [
- {"name": "小型宝塔", "ip": "42.194.232.22"},
{"name": "存客宝", "ip": "42.194.245.239"},
{"name": "kr宝塔", "ip": "43.139.27.93"},
],
@@ -446,7 +444,6 @@ OWN_INFRASTRUCTURE = {
# 排除的 IP 段(自有云服务器所在的小段)
"exclude_cidrs": [
- "42.194.232.22/32",
"42.194.245.239/32",
"43.139.27.93/32",
],
@@ -488,7 +485,6 @@ def filter_scan_targets(ip_list):
```bash
# 生成排除文件
cat > /tmp/exclude_own.txt << 'EOF'
-42.194.232.22
42.194.245.239
43.139.27.93
192.168.1.0/24
@@ -516,9 +512,8 @@ nmap -iL targets.txt --excludefile /tmp/exclude_own.txt -p 22,80,443,3389,8080 -
|:---|:---|:---|:---|:---|:---|:---|:---|
| 家里NAS(DS213j) | 192.168.110.29 | 群晖NAS(armv7l) | 22 | admin | ✅ **已部署运行中** | chroot | 外网不可达,内网正常 |
| 公司NAS(CKB) | 192.168.1.201 | 群晖NAS(DS1825+,x86_64) | 22 | fnvtk | 🟢 **SSH可用** | Docker | 外网SSH已验证(22201) |
-| 小型宝塔 | 42.194.232.22 | Linux | 22 | root | 🔴 **离线** | Docker | 无端口开放,疑似关机 |
| 存客宝 | 42.194.245.239 | Linux | 22 | root | 🟡 **SSH需开放** | Docker | 15端口开放(VNC/RDP/MySQL等),22关闭 |
-| kr宝塔 | 43.139.27.93 | Linux | 22 | root | 🟡 **SSH需开放** | Docker | 11端口开放(含v0项目),22关闭 |
+| kr宝塔 | 43.139.27.93 | Linux | 22022 | root | 🟡 **SSH需开放** | Docker | 11端口开放(含v0项目) |
### 6.2 已部署节点详情
@@ -1702,9 +1697,8 @@ done
| 设备 | 外网可达 | SSH | 原因/备注 |
|:---|:---|:---|:---|
-| 小型宝塔 42.194.232.22 | ❌ | ❌ | 疑似关机,需查腾讯云控制台 |
| 存客宝 42.194.245.239 | ✅ | ❌(22关) | 安全组未开放22,有VNC(5901)/RDP(3389) |
-| kr宝塔 43.139.27.93 | ✅ | ❌(22关) | 安全组未开放22,运行多个v0项目 |
+| kr宝塔 43.139.27.93 | ✅ | ✅(22022) | 安全组开放22022,运行多个v0项目 |
| 公司NAS | ✅ | ✅ | fnvtk/zhiqun1984, 端口22201 |
| 家里NAS | ❌ | ❌ | DDNS或NAS离线,需本地检查 |
diff --git a/01_卡资(金)/金仓_存储备份/分布式算力管控/参考资料/已部署节点清单.md b/01_卡资(金)/金仓_存储备份/分布式算力管控/参考资料/已部署节点清单.md
index 5142e3f3..fc2bdbd2 100644
--- a/01_卡资(金)/金仓_存储备份/分布式算力管控/参考资料/已部署节点清单.md
+++ b/01_卡资(金)/金仓_存储备份/分布式算力管控/参考资料/已部署节点清单.md
@@ -9,9 +9,8 @@
| 设备名 | IP | SSH端口 | 用户名 | 类型 | 部署状态 | 最新扫描结果 |
|:---|:---|:---|:---|:---|:---|:---|
-| 小型宝塔 | 42.194.232.22 | 22 | root | Linux(2核4G) | 🔴 **离线** | 无任何端口开放,不可达 |
| 存客宝 | 42.194.245.239 | 22 | root | Linux | 🟡 SSH需开放 | 15个端口开放(FTP/HTTP/MySQL/RDP/VNC等),SSH关闭 |
-| kr宝塔 | 43.139.27.93 | 22 | root | Linux | 🟡 SSH需开放 | 11个端口开放(HTTP/FTP/3000-3031等),SSH关闭 |
+| kr宝塔 | 43.139.27.93 | 22022 | root | Linux | 🟡 SSH需开放 | 11个端口开放(HTTP/FTP/3000-3031等) |
| 公司NAS(CKB) | 192.168.1.201 | 22 | fnvtk | 群晖NAS | 🟢 **SSH可用** | 外网SSH已验证(open.quwanzhi.com:22201) |
| 家里NAS(DS213j) | 192.168.110.29 | 22 | admin | 群晖NAS(armv7l) | ⚠️ **外网不可达** | 内网已部署PCDN,外网连接超时 |
@@ -34,7 +33,6 @@
## 网心云绑定检查清单
-- [ ] 42.194.232.22 - 打开 http://42.194.232.22:18888 扫码绑定
- [ ] 42.194.245.239 - 打开 http://42.194.245.239:18888 扫码绑定
- [ ] 43.139.27.93 - 打开 http://43.139.27.93:18888 扫码绑定
- [ ] 192.168.1.201 - 打开 http://192.168.1.201:18888 扫码绑定(需先修复镜像拉取)
diff --git a/01_卡资(金)/金仓_存储备份/分布式算力管控/脚本/fleet_monitor.py b/01_卡资(金)/金仓_存储备份/分布式算力管控/脚本/fleet_monitor.py
index 0804d0e1..2498bbc0 100755
--- a/01_卡资(金)/金仓_存储备份/分布式算力管控/脚本/fleet_monitor.py
+++ b/01_卡资(金)/金仓_存储备份/分布式算力管控/脚本/fleet_monitor.py
@@ -11,7 +11,7 @@
用法:
python3 fleet_monitor.py --all # 检查所有已知设备
- python3 fleet_monitor.py --host 42.194.232.22 # 检查单个
+ python3 fleet_monitor.py --host 43.139.27.93 # 检查单个(kr宝塔)
python3 fleet_monitor.py --quick # 快速检查(只看容器状态)
卡若账号:15880802661
@@ -30,11 +30,10 @@ from concurrent.futures import ThreadPoolExecutor, as_completed
RED = "\033[91m"; GREEN = "\033[92m"; YELLOW = "\033[93m"
BLUE = "\033[94m"; CYAN = "\033[96m"; NC = "\033[0m"
-# 已知设备列表
+# 已知设备列表(小型宝塔已下线)
KNOWN_DEVICES = [
- {"name": "小型宝塔", "ip": "42.194.232.22", "port": 22, "user": "root", "password": "Zhiqun1984"},
{"name": "存客宝", "ip": "42.194.245.239", "port": 22, "user": "root", "password": "Zhiqun1984"},
- {"name": "kr宝塔", "ip": "43.139.27.93", "port": 22, "user": "root", "password": "Zhiqun1984"},
+ {"name": "kr宝塔", "ip": "43.139.27.93", "port": 22022, "user": "root", "password": "Zhiqun1984"},
{"name": "公司NAS(CKB)", "ip": "192.168.1.201", "port": 22, "user": "fnvtk", "password": ""},
{"name": "家里NAS", "ip": "192.168.110.29", "port": 22, "user": "admin", "password": ""},
]
diff --git a/01_卡资(金)/金仓_存储备份/分布式算力管控/脚本/pcdn_auto_deploy.py b/01_卡资(金)/金仓_存储备份/分布式算力管控/脚本/pcdn_auto_deploy.py
index 2114df0b..96f8ceb0 100755
--- a/01_卡资(金)/金仓_存储备份/分布式算力管控/脚本/pcdn_auto_deploy.py
+++ b/01_卡资(金)/金仓_存储备份/分布式算力管控/脚本/pcdn_auto_deploy.py
@@ -72,9 +72,8 @@ DEFAULT_CREDENTIALS = [
# 已知设备(直接内置,不需要扫描就能部署)
KNOWN_DEVICES = [
- {"name": "小型宝塔", "ip": "42.194.232.22", "port": 22, "user": "root", "password": "Zhiqun1984", "type": "linux"},
{"name": "存客宝", "ip": "42.194.245.239", "port": 22, "user": "root", "password": "Zhiqun1984", "type": "linux"},
- {"name": "kr宝塔", "ip": "43.139.27.93", "port": 22, "user": "root", "password": "Zhiqun1984", "type": "linux"},
+ {"name": "kr宝塔", "ip": "43.139.27.93", "port": 22022, "user": "root", "password": "Zhiqun1984", "type": "linux"},
{"name": "公司NAS(CKB)", "ip": "192.168.1.201", "port": 22, "user": "fnvtk", "password": "", "type": "synology"},
{"name": "家里NAS(Station)", "ip": "192.168.110.29", "port": 22, "user": "admin", "password": "", "type": "synology"},
{"name": "公司NAS(外网)", "ip": "open.quwanzhi.com", "port": 22201, "user": "fnvtk", "password": "", "type": "synology"},
diff --git a/01_卡资(金)/金仓_存储备份/服务器管理/SKILL.md b/01_卡资(金)/金仓_存储备份/服务器管理/SKILL.md
index 44d4013e..3557d227 100644
--- a/01_卡资(金)/金仓_存储备份/服务器管理/SKILL.md
+++ b/01_卡资(金)/金仓_存储备份/服务器管理/SKILL.md
@@ -21,9 +21,8 @@ updated: "2026-02-16"
| 服务器 | IP | 配置 | 用途 | 宝塔面板 |
|--------|-----|------|------|----------|
| **本机 Docker 宝塔** | 127.0.0.1 | Docker 容器 | 本地建站、与腾讯云一致 | http://127.0.0.1:8888/btpanel |
-| **小型宝塔** | 42.194.232.22 | 2核4G 5M | 主力部署(Node项目) | https://42.194.232.22:9988/ckbpanel |
| **存客宝** | 42.194.245.239 | 2核16G 50M | 私域银行业务 | https://42.194.245.239:9988 |
-| **kr宝塔** | 43.139.27.93 | 2核4G 5M | 辅助服务器 | https://43.139.27.93:9988 |
+| **kr宝塔** | 43.139.27.93 | 2核4G 5M | Node 项目主力、辅助 | https://43.139.27.93:9988 |
### 凭证速查
@@ -36,19 +35,18 @@ updated: "2026-02-16"
# 启动: bash 01_卡资(金)/金仓_存储备份/服务器管理/scripts/本机Docker宝塔_启动.sh
# 数据目录: ~/baota_docker_data/(website_data、mysql_data、vhost)
-# SSH连接(小型宝塔为例)
-ssh root@42.194.232.22
+# SSH连接(kr宝塔为例,端口 22022)
+ssh -p 22022 root@43.139.27.93
密码: Zhiqun1984
-# 宝塔面板登录(小型宝塔)
-地址: https://42.194.232.22:9988/ckbpanel
+# 宝塔面板登录(kr宝塔)
+地址: https://43.139.27.93:9988
账号: ckb
密码: zhiqun1984
# 宝塔API密钥
-小型宝塔: hsAWqFSi0GOCrunhmYdkxy92tBXfqYjd
-存客宝: TNKjqDv5N1QLOU20gcmGVgr82Z4mXzRi
-kr宝塔: qcWubCdlfFjS2b2DMT1lzPFaDfmv1cBT
+存客宝: TNKjqDv5N1QLOU20gcmGVgr82Z4mXzRi
+kr宝塔: qcWubCdlfFjS2b2DMT1lzPFaDfmv1cBT
```
---
@@ -78,11 +76,11 @@ cd /项目路径
tar --exclude='node_modules' --exclude='.next' --exclude='.git' \
-czf /tmp/项目名_update.tar.gz .
-# 2. 上传到服务器
-sshpass -p 'Zhiqun1984' scp /tmp/项目名_update.tar.gz root@42.194.232.22:/tmp/
+# 2. 上传到服务器(kr宝塔)
+sshpass -p 'Zhiqun1984' scp -P 22022 /tmp/项目名_update.tar.gz root@43.139.27.93:/tmp/
# 3. SSH部署
-ssh root@42.194.232.22
+ssh -p 22022 root@43.139.27.93
cd /www/wwwroot/项目名
rm -rf app components lib public styles *.json *.js *.ts *.mjs *.md .next
tar -xzf /tmp/项目名_update.tar.gz
@@ -111,23 +109,23 @@ python3 "/Users/karuo/Documents/个人/卡若AI/01_卡资(金)/金仓_存储
- 本机快速检查:`ping 43.139.27.93`、`nc -zv 43.139.27.93 22022`
- 服务器内诊断:登录后执行文档中「2.2 一键诊断」命令块;若 SSH 被关闭可改用宝塔面板终端。
-### 5. 常用诊断命令(小型宝塔等)
+### 5. 常用诊断命令(kr宝塔等)
```bash
# 检查端口占用
-ssh root@42.194.232.22 "ss -tlnp | grep :3006"
+ssh -p 22022 root@43.139.27.93 "ss -tlnp | grep :3006"
# 检查PM2进程
-ssh root@42.194.232.22 "/www/server/nodejs/v22.14.0/bin/pm2 list"
+ssh -p 22022 root@43.139.27.93 "/www/server/nodejs/v22.14.0/bin/pm2 list"
# 测试HTTP响应
-ssh root@42.194.232.22 "curl -I http://localhost:3006"
+ssh -p 22022 root@43.139.27.93 "curl -I http://localhost:3006"
# 检查Nginx配置
-ssh root@42.194.232.22 "nginx -t"
+ssh -p 22022 root@43.139.27.93 "nginx -t"
# 重载Nginx
-ssh root@42.194.232.22 "nginx -s reload"
+ssh -p 22022 root@43.139.27.93 "nginx -s reload"
# DNS解析检查
dig soul.quwanzhi.com +short @8.8.8.8
@@ -135,7 +133,7 @@ dig soul.quwanzhi.com +short @8.8.8.8
---
-## 端口配置表(小型宝塔 42.194.232.22)
+## 端口配置表(kr宝塔 43.139.27.93)
| 端口 | 项目名 | 类型 | 域名 | 状态 |
|------|--------|------|------|------|
diff --git a/01_卡资(金)/金仓_存储备份/服务器管理/参考资料/端口配置表.md b/01_卡资(金)/金仓_存储备份/服务器管理/参考资料/端口配置表.md
index 27a7c9dd..cb5fc4dd 100644
--- a/01_卡资(金)/金仓_存储备份/服务器管理/参考资料/端口配置表.md
+++ b/01_卡资(金)/金仓_存储备份/服务器管理/参考资料/端口配置表.md
@@ -8,50 +8,7 @@
| 用途 | 端口 | 说明 |
|----------|-------|------|
| 宝塔面板 | 9988 | 三台宝塔统一 |
-| SSH(kr宝塔/存客宝) | 22022 或 22 | 小型宝塔已改为 22022;kr宝塔 SSH=22022 |
-
-## 小型宝塔 (42.194.232.22)
-
-### 服务器配置
-- **配置**: 2核4G,内存3.6G
-- **带宽**: 5M
-- **安全组**: 443端口开放,80端口受限
-- **注意**: 所有Node项目必须配置HTTPS
-
-### 端口分配表
-
-| 端口 | 项目名 | 类型 | 域名 | 启动命令 | 状态 |
-|------|--------|------|------|----------|------|
-| 3000 | cunkebao | Next.js | mckb.quwanzhi.com | dev | ✅ |
-| 3001 | ai_hair | NestJS | ai-hair.quwanzhi.com | start | ✅ |
-| 3002 | kr_wb | Next.js | kr_wb.quwanzhi.com | start | ✅ |
-| 3003 | hx | Vue | krjzk.quwanzhi.com | build | ⚠️ |
-| 3004 | dlmdashboard | Next.js | dlm.quwanzhi.com | dev | ✅ |
-| 3005 | document | Next.js | docc.quwanzhi.com | dev | ✅ |
-| 3006 | soul | Next.js | soul.quwanzhi.com | start | ✅ |
-| 3015 | 神射手 | Next.js | kr-users.quwanzhi.com | build | ⚠️ |
-| 3018 | zhaoping | Next.js | zp.quwanzhi.com | start | ✅ |
-| 3021 | is_phone | Next.js | is-phone.quwanzhi.com | dev | ✅ |
-| 3031 | word | Next.js | word.quwanzhi.com | start | ✅ |
-| 3036 | ymao | Next.js | ymao.quwanzhi.com | dev | ✅ |
-| 3043 | tongzhi | Next.js | touzhi.lkdie.com | start | ✅ |
-| 3045 | 玩值大屏 | Next.js | wz-screen.quwanzhi.com | start | ✅ |
-| 3050 | zhiji | Next.js | zhiji.quwanzhi.com | start | ✅ |
-| 3051 | zhiji1 | Next.js | zhiji1.quwanzhi.com | start | ✅ |
-| 3055 | wzdj | Next.js | wzdj.quwanzhi.com | start | ✅ |
-| 3305 | AITOUFA | Next.js | ai-tf.quwanzhi.com | start | ✅ |
-| 9528 | mbti | Vue | mbtiadmin.quwanzhi.com | dev | ✅ |
-
-### 域名Nginx配置对照表
-
-| 域名 | 反向代理端口 | SSL证书 |
-|------|-------------|---------|
-| soul.quwanzhi.com | 127.0.0.1:3006 | 通配符证书 |
-| zhiji.quwanzhi.com | 127.0.0.1:3050 | 通配符证书 |
-| touzhi.lkdie.com | 127.0.0.1:3043 | 通配符证书 |
-| mbtiadmin.quwanzhi.com | 127.0.0.1:9528 | 通配符证书 |
-
----
+| SSH(kr宝塔/存客宝) | 22022 或 22 | kr宝塔 SSH=22022 |
## kr宝塔 (43.139.27.93)
diff --git a/01_卡资(金)/金仓_存储备份/服务器管理/脚本/ssl证书检查.py b/01_卡资(金)/金仓_存储备份/服务器管理/脚本/ssl证书检查.py
index 4ac56952..e52f91c7 100644
--- a/01_卡资(金)/金仓_存储备份/服务器管理/脚本/ssl证书检查.py
+++ b/01_卡资(金)/金仓_存储备份/服务器管理/脚本/ssl证书检查.py
@@ -20,12 +20,8 @@ from datetime import datetime
# 禁用SSL警告
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
-# 服务器配置
+# 服务器配置(小型宝塔已下线)
服务器列表 = {
- "小型宝塔": {
- "面板地址": "https://42.194.232.22:9988",
- "密钥": "hsAWqFSi0GOCrunhmYdkxy92tBXfqYjd"
- },
"存客宝": {
"面板地址": "https://42.194.245.239:9988",
"密钥": "TNKjqDv5N1QLOU20gcmGVgr82Z4mXzRi"
diff --git a/01_卡资(金)/金仓_存储备份/服务器管理/脚本/一键部署.py b/01_卡资(金)/金仓_存储备份/服务器管理/脚本/一键部署.py
index 9d8bf32b..cdd30d83 100644
--- a/01_卡资(金)/金仓_存储备份/服务器管理/脚本/一键部署.py
+++ b/01_卡资(金)/金仓_存储备份/服务器管理/脚本/一键部署.py
@@ -17,9 +17,10 @@ import os
import subprocess
import time
-# 默认服务器配置
+# 默认服务器配置(kr宝塔,Node 项目主力)
默认配置 = {
- "服务器IP": "42.194.232.22",
+ "服务器IP": "43.139.27.93",
+ "SSH端口": "22022",
"SSH用户": "root",
"SSH密码": "Zhiqun1984",
"服务器根目录": "/www/wwwroot"
@@ -60,7 +61,7 @@ def 部署项目(项目名称: str, 本地路径: str):
# 步骤2: 上传到服务器
print("\n📤 步骤2: 上传到服务器...")
- 上传命令 = f"sshpass -p '{默认配置['SSH密码']}' scp -o StrictHostKeyChecking=no {压缩文件} {默认配置['SSH用户']}@{默认配置['服务器IP']}:/tmp/"
+ 上传命令 = f"sshpass -p '{默认配置['SSH密码']}' scp -P {默认配置.get('SSH端口', 22)} -o StrictHostKeyChecking=no {压缩文件} {默认配置['SSH用户']}@{默认配置['服务器IP']}:/tmp/"
code, _ = 执行命令(上传命令, False)
if code != 0:
print("❌ 上传失败")
@@ -70,7 +71,7 @@ def 部署项目(项目名称: str, 本地路径: str):
# 步骤3-6: SSH远程执行
print("\n🔧 步骤3-6: 服务器端操作...")
- SSH前缀 = f"sshpass -p '{默认配置['SSH密码']}' ssh -o StrictHostKeyChecking=no {默认配置['SSH用户']}@{默认配置['服务器IP']}"
+ SSH前缀 = f"sshpass -p '{默认配置['SSH密码']}' ssh -p {默认配置.get('SSH端口', 22)} -o StrictHostKeyChecking=no {默认配置['SSH用户']}@{默认配置['服务器IP']}"
# 清理旧文件
清理命令 = f"{SSH前缀} 'cd {服务器路径} && rm -rf app components lib public styles *.json *.js *.ts *.mjs *.md .next 2>/dev/null || true'"
@@ -101,7 +102,7 @@ def 部署项目(项目名称: str, 本地路径: str):
print("✅ 部署完成!")
print(f"{'='*60}")
print("\n⚠️ 请在宝塔面板手动重启项目:")
- print(f" 1. 登录 https://42.194.232.22:9988/ckbpanel")
+ print(f" 1. 登录 https://43.139.27.93:9988")
print(f" 2. 进入【网站】→【Node项目】")
print(f" 3. 找到 {项目名称},点击【重启】")
diff --git a/01_卡资(金)/金仓_存储备份/服务器管理/脚本/快速检查服务器.py b/01_卡资(金)/金仓_存储备份/服务器管理/脚本/快速检查服务器.py
index 5667788c..38df4675 100644
--- a/01_卡资(金)/金仓_存储备份/服务器管理/脚本/快速检查服务器.py
+++ b/01_卡资(金)/金仓_存储备份/服务器管理/脚本/快速检查服务器.py
@@ -17,12 +17,8 @@ import urllib3
# 禁用SSL警告
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
-# 服务器配置
+# 服务器配置(小型宝塔已下线,仅存客宝、kr宝塔)
服务器列表 = {
- "小型宝塔": {
- "面板地址": "https://42.194.232.22:9988",
- "密钥": "hsAWqFSi0GOCrunhmYdkxy92tBXfqYjd"
- },
"存客宝": {
"面板地址": "https://42.194.245.239:9988",
"密钥": "TNKjqDv5N1QLOU20gcmGVgr82Z4mXzRi"
diff --git a/01_卡资(金)/金仓_存储备份/服务器管理/脚本/按内网IP定位宝塔.py b/01_卡资(金)/金仓_存储备份/服务器管理/脚本/按内网IP定位宝塔.py
index fd70b339..1b6b400b 100644
--- a/01_卡资(金)/金仓_存储备份/服务器管理/脚本/按内网IP定位宝塔.py
+++ b/01_卡资(金)/金仓_存储备份/服务器管理/脚本/按内网IP定位宝塔.py
@@ -18,9 +18,8 @@ import re
import subprocess
import sys
-# 与 快速检查服务器.py 一致;从面板地址解析公网 IP
+# 与 快速检查服务器.py 一致;从面板地址解析公网 IP(小型宝塔已下线)
服务器列表 = {
- "小型宝塔": "42.194.232.22",
"存客宝": "42.194.245.239",
"kr宝塔": "43.139.27.93",
}
diff --git a/01_卡资(金)/金仓_存储备份/群晖NAS管理/SKILL.md b/01_卡资(金)/金仓_存储备份/群晖NAS管理/SKILL.md
index 5167bed9..7c76e042 100644
--- a/01_卡资(金)/金仓_存储备份/群晖NAS管理/SKILL.md
+++ b/01_卡资(金)/金仓_存储备份/群晖NAS管理/SKILL.md
@@ -193,6 +193,23 @@ ssh nas "/volume1/@appstore/ContainerManager/usr/bin/docker ps --format 'table {
> **macOS noVNC 卡顿**:见 `references/noVNC_macOS_VM流畅度优化.md`。优先用优化 URL:`http://IP:8007/?qualityLevel=3&compressionLevel=6&resize=scale`
+#### macOS VM 导出到本机(打包下载到「下载」文件夹)
+
+将 NAS 上 Docker 里的 macOS 虚拟机数据打包、实时显示大小/用时、下载到当前 Mac 的「下载」文件夹,并生成使用说明(含在 Windows / Linux 上运行方式)。
+
+```bash
+# 内网(与 CKB NAS 同网时)
+/Users/karuo/Documents/个人/卡若AI/01_卡资(金)/金仓_存储备份/群晖NAS管理/scripts/export_macos_vm_to_downloads.sh
+
+# 外网(用 frp 穿透的 SSH)
+export NAS_HOST=open.quwanzhi.com NAS_PORT=22201
+/Users/karuo/Documents/个人/卡若AI/01_卡资(金)/金仓_存储备份/群晖NAS管理/scripts/export_macos_vm_to_downloads.sh
+```
+
+- 需要本机已安装 `sshpass`(`brew install sshpass`)。
+- 导出物:`~/Downloads/macos_vm_export_日期时间.tar.gz` + `~/Downloads/macos_vm_使用说明.md`。
+- 说明里含:在 Linux/NAS 上挂载运行、传到 Windows 的注意点(需 Linux 虚拟机或 WSL2 等)。
+
#### docker-compose 示例 (Windows)
```yaml
@@ -452,9 +469,8 @@ API文档: http://192.168.1.201:8890/docs
| 服务器 | IP | 用途 |
|--------|-----|------|
-| 小型宝塔 | 42.194.232.22 | 通用项目 |
| 存客宝 | 42.194.245.239 | 私域银行 |
-| kr宝塔 | 43.139.27.93 | 特殊项目 |
+| kr宝塔 | 43.139.27.93 | Node/网关 |
---
@@ -694,6 +710,7 @@ ssh nas "netstat -tlnp | grep 27017"
| 脚本 | 功能 | 位置 | 快速运行 |
|------|------|------|----------|
| `time_machine_diskstation_auto.sh` | Time Machine → 家里 DiskStation 检测/验证,输出材料路径供按参考资料处理 | `./scripts/` | `./scripts/time_machine_diskstation_auto.sh` |
+| `export_macos_vm_to_downloads.sh` | CKB NAS 上 macOS VM 打包下载到本机「下载」文件夹,实时显示大小与用时,并生成使用说明 | `./scripts/` | 见下方「macOS VM 导出到本机」 |
| `optimize_macos_vm_compose.sh` | 本机→NAS:macOS VM 流畅度优化 | `./scripts/` | 需本机与 NAS 同网 |
| `optimize_macos_vm_on_nas.sh` | **NAS 上直接执行**:macOS VM 流畅度优化(外网推荐) | `./scripts/` | SSH 登录 NAS 后运行 |
| `nas_status.sh` | 一键检查NAS状态(内存/磁盘/容器/端口) | `./scripts/` | `./scripts/nas_status.sh` |
diff --git a/01_卡资(金)/金仓_存储备份/群晖NAS管理/scripts/export_macos_vm_to_downloads.sh b/01_卡资(金)/金仓_存储备份/群晖NAS管理/scripts/export_macos_vm_to_downloads.sh
new file mode 100755
index 00000000..f565ec7c
--- /dev/null
+++ b/01_卡资(金)/金仓_存储备份/群晖NAS管理/scripts/export_macos_vm_to_downloads.sh
@@ -0,0 +1,33 @@
+#!/bin/bash
+# ============================================
+# macOS Docker 安装包:从全网(Docker Hub)拉取并保存到本机「下载」文件夹
+# 唯一方案:最小、最快、最便捷,不依赖存客宝 NAS 导出
+# ============================================
+
+set -e
+OUT_DIR="${HOME}/Downloads"
+IMAGE="dockurr/macos:latest"
+TAR_NAME="dockurr-macos-image.tar"
+OUTFILE="${OUT_DIR}/${TAR_NAME}"
+
+echo "============================================"
+echo " macOS Docker 安装包(全网源)"
+echo "============================================"
+echo " 源: Docker Hub (dockurr/macos)"
+echo " 目标: ${OUTFILE}"
+echo "============================================"
+echo ""
+
+echo "[1/2] 拉取镜像(实时进度)..."
+docker pull "$IMAGE" 2>&1
+echo ""
+
+echo "[2/2] 导出为离线安装包..."
+docker save "$IMAGE" -o "$OUTFILE"
+SIZE=$(ls -lh "$OUTFILE" | awk '{print $5}')
+echo " 已保存: ${OUTFILE} (${SIZE})"
+echo ""
+
+echo "全部完成。可在 Mac 上使用:"
+echo " docker load -i ${OUTFILE}"
+echo " 详见 下载 文件夹内「macos_Docker安装包_复盘与说明.md」"
diff --git a/02_卡人(水)/水桥_平台对接/飞书管理/SKILL.md b/02_卡人(水)/水桥_平台对接/飞书管理/SKILL.md
index f4dd53dc..92a098fc 100755
--- a/02_卡人(水)/水桥_平台对接/飞书管理/SKILL.md
+++ b/02_卡人(水)/水桥_平台对接/飞书管理/SKILL.md
@@ -1,11 +1,11 @@
---
name: 飞书管理
description: 飞书日志/文档自动写入与知识库管理
-triggers: 飞书日志、写入飞书、飞书知识库、飞书运营报表、派对效果数据、104场写入
+triggers: 飞书日志、写入飞书、飞书知识库、飞书运营报表、派对效果数据、104场写入、运营报表填写、派对截图填表发群
owner: 水桥
group: 水
-version: "1.0"
-updated: "2026-02-16"
+version: "1.1"
+updated: "2026-02-20"
---
# 飞书日志写入 Skill
@@ -186,40 +186,78 @@ python3 /Users/karuo/Documents/个人/卡若AI/02_卡人(水)/飞书管理/s
---
-## 飞书运营报表(Soul 派对效果数据)
+## 运营报表(子技能)
-将 Soul 派对效果数据按**场次**写入飞书「火:运营报表」表格,**竖列**填入对应日期/场次列。
+专门处理 Soul 派对运营报表:**截图 → 填写表格 → 发飞书群** 全流程,以及会议纪要图片上传、月度统计。
+**独立说明**:见同目录 [运营报表_SKILL.md](./运营报表_SKILL.md)。
-### 填写规则(以后都按此逻辑)
+---
+
+### 一、全流程:截图 → 填表 → 发群
+
+| 步骤 | 动作 | 脚本/说明 |
+|:---|:---|:---|
+| 1 | **截图/数据** | 派对关闭页截图 + 小助手弹窗截图 + 可选 TXT 逐字稿(提炼主题) |
+| 2 | **填写表格** | 在 `soul_party_to_feishu_sheet.py` 的 `ROWS` 中配置该场 10 项数据;按**当天日期列**或「x场」列写入 |
+| 3 | **发飞书群** | 写入成功后自动推送到配置的 webhook;**发群内容为竖状格式**(见下) |
+
+**发群格式(竖状,不用一串)**:每行一项,与表格指标一致,便于阅读。
+
+```
+【Soul 派对运营报表】
+链接:https://cunkebao.feishu.cn/wiki/...
+
+105场(2月20日)已登记:
+主题:创业社群AI培训6980 电竞私域
+时长(分钟):138
+Soul推流人数:0
+进房人数:403
+人均时长(分钟):10
+互动数量:170
+礼物:2
+灵魂力:24
+增加关注:31
+最高在线:54
+数据来源:soul 派对 105场 20260220.txt
+```
+
+---
+
+### 二、填写规则(表格内)
| 规则 | 说明 |
|:---|:---|
-| **按数字填写** | 时长、推流、进房、互动、礼物、灵魂力、增加关注、最高在线 等均按**数字类型**写入,不按文本,便于表格公式与图表 |
-| **不填比率三项** | 推流进房率、1分钟进多少人、加微率 由表格内公式自动计算,**导入时不填** |
+| **按数字填写** | 时长、推流、进房、互动、礼物、灵魂力、增加关注、最高在线 均按**数字类型**写入,便于公式与图表 |
+| **不填比率三项** | 推流进房率、1分钟进多少人、加微率 由表内公式自动算,不写入 |
| **只填前 10 项** | 主题、时长、Soul推流人数、进房人数、人均时长、互动数量、礼物、灵魂力、增加关注、最高在线 |
-| **主题(标题)** | 从聊天记录提炼,**≤12 字**,须含**具体内容、干货与数值**(如:号商几毛卖十几 日销两万) |
-| **竖列写入** | 表格结构为 A 列指标名、各列为日期/场次,数据写入该场次列的第 3~12 行(竖列) |
+| **主题** | 从聊天/TXT 提炼,**≤12 字**,含干货与数值 |
+| **按日期列** | 表头第 1 行为日期 1、2…19、20…;该场对应日期(如 2月20日)则填在「20」列下 |
+| **竖列写入** | A 列为指标名,数据写入该日期/场次列的第 3~12 行 |
-### 一键写入
+---
-```bash
-# 写入 104 场(默认)
-python3 /Users/karuo/Documents/个人/卡若AI/02_卡人(水)/水桥_平台对接/飞书管理/脚本/soul_party_to_feishu_sheet.py
+### 三、脚本一览
-# 指定场次
-python3 .../soul_party_to_feishu_sheet.py 103
-python3 .../soul_party_to_feishu_sheet.py 104
-```
+| 脚本 | 用途 |
+|:---|:---|
+| `soul_party_to_feishu_sheet.py [场次]` | 将指定场次效果数据写入运营报表;部分场次(如 105)写入后自动发群(竖状格式) |
+| `feishu_write_minutes_to_sheet.py [内部图] [派对图]` | 将**内部会议纪要**、**派对今日总结**的**图片**上传到对应单元格(内部→2月20日列,派对→2月19日列),不发群 |
+| `feishu_sheet_monthly_stats.py [1\|2\|all]` | 统计指定月或全部月份运营数据(合计/有数据场次) |
-### 表格与配置
+**路径**:`02_卡人(水)/水桥_平台对接/飞书管理/脚本/`
+
+---
+
+### 四、表格与配置
| 项目 | 值 |
|:---|:---|
-| 运营报表 | https://cunkebao.feishu.cn/wiki/wikcnIgAGSNHo0t36idHJ668Gfd?sheet=7A3Cy9 |
+| 运营报表链接 | https://cunkebao.feishu.cn/wiki/wikcnIgAGSNHo0t36idHJ668Gfd?sheet=7A3Cy9 |
| 工作表 | 2026年2月 soul 书卡若创业派对(sheetId=7A3Cy9) |
-| Token | 使用同目录 `.feishu_tokens.json`(与 auto_log 共用) |
+| Token | 同目录 `.feishu_tokens.json` |
+| 发群 webhook | 脚本内 `FEISHU_GROUP_WEBHOOK` 或环境变量 |
-新增场次时在脚本内 `ROWS` 中增加对应场次与 10 项数据即可。
+新增场次:在 `ROWS` 与(按日期列时)`SESSION_DATE_COLUMN` 中增加;需发群则在 `_maybe_send_group` 中增加对应场次逻辑。
---
@@ -247,17 +285,19 @@ python3 scripts/wanzhi_feishu_project_sync.py
飞书管理/
├── SKILL.md # 本文档
├── references/
-│ ├── 飞书项目API_玩值电竞对接说明.md # 飞书项目接口说明
+│ ├── 飞书项目API_玩值电竞对接说明.md
│ └── ...
-└── scripts/
- ├── auto_log.py # 一键日志脚本(推荐)
- ├── write_today_custom.py # 自定义今日内容写入(写入后自动打开飞书)
- ├── soul_party_to_feishu_sheet.py # 飞书运营报表:Soul 派对效果数据(按场次竖列、数字、不填比率)
- ├── wanzhi_feishu_project_sync.py # 玩值电竞→飞书项目任务同步
+└── 脚本/
+ ├── auto_log.py # 一键日志(推荐)
+ ├── write_today_custom.py # 自定义今日内容写入
+ ├── soul_party_to_feishu_sheet.py # 运营报表:派对效果数据写入 + 发群(竖状格式)
+ ├── feishu_write_minutes_to_sheet.py # 运营报表:会议纪要/今日总结图片上传到单元格
+ ├── feishu_sheet_monthly_stats.py # 运营报表:本月/全部月份数据统计
├── feishu_api.py # 后端服务
├── feishu_video_clip.py # 视频智能切片
- ├── feishu_video_clip_README.md # 切片工具说明
- └── .feishu_tokens.json # Token存储
+ ├── feishu_video_clip_README.md
+ ├── wanzhi_feishu_project_sync.py # 玩值电竞→飞书项目同步
+ └── .feishu_tokens.json # Token 存储
```
---
@@ -292,5 +332,5 @@ python3 /Users/karuo/Documents/个人/卡若AI/02_卡人(水)/飞书管理/s
---
-**版本**: v3.2 | **更新**: 2026-01-30
-**特性**: 静默授权、倒序插入、TNTWF规范、四象限分类、**写入完成后自动打开飞书日志页面**
+**版本**: v3.3 | **更新**: 2026-02-20
+**特性**: 静默授权、倒序插入、TNTWF规范、四象限分类、**写入完成后自动打开飞书日志页面**、**运营报表子技能(截图→填表→发群竖状格式、会议纪要图片上传、月度统计)**
diff --git a/02_卡人(水)/水桥_平台对接/飞书管理/脚本/.feishu_tokens.json b/02_卡人(水)/水桥_平台对接/飞书管理/脚本/.feishu_tokens.json
index cbbcbe5b..ab527e48 100644
--- a/02_卡人(水)/水桥_平台对接/飞书管理/脚本/.feishu_tokens.json
+++ b/02_卡人(水)/水桥_平台对接/飞书管理/脚本/.feishu_tokens.json
@@ -1,6 +1,6 @@
{
- "access_token": "u-54M8YSO5daprUT9Aq1DGS6l5kOO5k1iroEaaVNw00xOn",
- "refresh_token": "ur-6pAv.4Dct8FH0EcZMWKMGTl5kUO5k1ippUaaYNA00wCn",
+ "access_token": "u-7yGMT9TatdKHnZCBE4NJ40l5koM5k1grNUaaIBQ00BTn",
+ "refresh_token": "ur-5C7Zm2OG12qbBr6qVlEex4l5kiqBk1oVVoaaUxM00AS3",
"name": "飞书用户",
"auth_time": "2026-02-19T17:28:30.836949"
}
\ No newline at end of file
diff --git a/02_卡人(水)/水桥_平台对接/飞书管理/脚本/feishu_sheet_monthly_stats.py b/02_卡人(水)/水桥_平台对接/飞书管理/脚本/feishu_sheet_monthly_stats.py
new file mode 100644
index 00000000..a95a1201
--- /dev/null
+++ b/02_卡人(水)/水桥_平台对接/飞书管理/脚本/feishu_sheet_monthly_stats.py
@@ -0,0 +1,359 @@
+#!/usr/bin/env python3
+"""读取飞书运营报表指定月份 sheet 或全部月份,汇总效果数据并输出统计。
+用法:python3 feishu_sheet_monthly_stats.py [月份|all]
+ 月份:1=第1个月(1月),2=第2个月(2月),默认 2
+ all(或 全部):遍历所有「x月」工作表,汇总总数据并分月展示
+"""
+import os
+import sys
+import json
+import requests
+from urllib.parse import quote
+
+FEISHU_SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
+TOKEN_FILE = os.path.join(FEISHU_SCRIPT_DIR, '.feishu_tokens.json')
+WIKI_NODE_OR_SPREADSHEET_TOKEN = os.environ.get('FEISHU_SPREADSHEET_TOKEN', 'wikcnIgAGSNHo0t36idHJ668Gfd')
+# 默认 2 月 sheet(未指定月份或未找到对应月份时使用)
+SHEET_ID_DEFAULT = os.environ.get('FEISHU_SHEET_ID', '7A3Cy9')
+
+# 效果数据行顺序:主题、时长、推流、进房、人均时长、互动、礼物、灵魂力、增加关注、最高在线
+LABELS = ['主题', '时长', 'Soul推流人数', '进房人数', '人均时长', '互动数量', '礼物', '灵魂力', '增加关注', '最高在线']
+
+
+def load_token():
+ if not os.path.exists(TOKEN_FILE):
+ return None
+ with open(TOKEN_FILE, 'r', encoding='utf-8') as f:
+ return json.load(f).get('access_token')
+
+
+def refresh_token():
+ with open(TOKEN_FILE, 'r', encoding='utf-8') as f:
+ data = json.load(f)
+ r = requests.post(
+ 'https://open.feishu.cn/open-apis/auth/v3/app_access_token/internal',
+ json={'app_id': 'cli_a48818290ef8100d', 'app_secret': 'dhjU0qWd5AzicGWTf4cTqhCWJOrnuCk4'},
+ timeout=10,
+ )
+ app_token = (r.json() or {}).get('app_access_token')
+ if not app_token:
+ return None
+ r2 = requests.post(
+ 'https://open.feishu.cn/open-apis/authen/v1/oidc/refresh_access_token',
+ headers={'Authorization': f'Bearer {app_token}', 'Content-Type': 'application/json'},
+ json={'grant_type': 'refresh_token', 'refresh_token': data.get('refresh_token')},
+ timeout=10,
+ )
+ out = r2.json()
+ if out.get('code') == 0 and out.get('data', {}).get('access_token'):
+ data['access_token'] = out['data']['access_token']
+ data['refresh_token'] = out['data'].get('refresh_token', data.get('refresh_token'))
+ with open(TOKEN_FILE, 'w', encoding='utf-8') as f:
+ json.dump(data, f, ensure_ascii=False, indent=2)
+ return data['access_token']
+ return None
+
+
+def get_sheets_list(token):
+ """返回 [(sheetId, title), ...]"""
+ url = f'https://open.feishu.cn/open-apis/sheets/v2/spreadsheets/{WIKI_NODE_OR_SPREADSHEET_TOKEN}/metainfo'
+ r = requests.get(url, headers={'Authorization': f'Bearer {token}'}, timeout=15)
+ if r.status_code != 200:
+ return []
+ body = r.json()
+ if body.get('code') != 0:
+ return []
+ sheets = (body.get('data') or {}).get('sheets') or []
+ return [(s.get('sheetId') or s.get('title'), (s.get('title') or '')) for s in sheets]
+
+
+def resolve_sheet_id_for_month(token, month_num):
+ """month_num 1=1月 2=2月。返回 (sheet_id, 月份标签)。"""
+ if month_num == 2:
+ return SHEET_ID_DEFAULT, '2月'
+ if month_num != 1:
+ return SHEET_ID_DEFAULT, '2月'
+ # 第1个月:找标题含 1月 的 sheet
+ for sheet_id, title in get_sheets_list(token):
+ if '1月' in title:
+ return sheet_id, '1月'
+ return None, '1月'
+
+
+def read_range(token, range_str):
+ url = f'https://open.feishu.cn/open-apis/sheets/v2/spreadsheets/{WIKI_NODE_OR_SPREADSHEET_TOKEN}/values/{quote(range_str, safe="")}'
+ r = requests.get(url, headers={'Authorization': f'Bearer {token}'}, timeout=15)
+ if r.status_code != 200:
+ return None
+ body = r.json()
+ if body.get('code') != 0:
+ return None
+ return (body.get('data') or {}).get('valueRange', {}).get('values') or []
+
+
+def num(s):
+ if s is None or s == '':
+ return 0
+ try:
+ return int(float(str(s).replace(',', '').strip()))
+ except (ValueError, TypeError):
+ return 0
+
+
+def get_month_sheets_sorted(token):
+ """返回标题含「x月」的工作表,按 1月、2月… 排序。[(sheet_id, title), ...]"""
+ import re
+ sheets = get_sheets_list(token)
+ month_sheets = []
+ for sid, title in sheets:
+ if not title or '月' not in title:
+ continue
+ m = re.search(r'(\d{1,2})月', title)
+ key = int(m.group(1)) if m else 99
+ month_sheets.append((sid, title, key))
+ month_sheets.sort(key=lambda x: x[2])
+ return [(x[0], x[1]) for x in month_sheets]
+
+
+def parse_sheet_vals(vals):
+ """从表格 values 解析场次与汇总。返回 (sessions, stats_dict) 或 (None, None) 若解析失败。"""
+ if not vals or len(vals) < 12:
+ return None, None
+ header_row_idx = None
+ for ri in (1, 0, 2):
+ if ri >= len(vals):
+ continue
+ for c in vals[ri]:
+ if '场' in str(c):
+ header_row_idx = ri
+ break
+ if header_row_idx is not None:
+ break
+ if header_row_idx is None:
+ return None, None
+ header = vals[header_row_idx]
+ data_start = header_row_idx + 1
+ sessions = []
+ for col_idx in range(len(header)):
+ cell = str(header[col_idx]).strip()
+ if '场' not in cell:
+ continue
+ row_vals = []
+ for row_offset in range(10):
+ ri = data_start + row_offset
+ if ri < len(vals) and col_idx < len(vals[ri]):
+ row_vals.append(vals[ri][col_idx])
+ else:
+ row_vals.append('')
+ sessions.append((cell, row_vals))
+ if not sessions:
+ return None, None
+ total_dur = total_push = total_room = total_interact = total_gift = total_soul = total_follow = 0
+ max_online = 0
+ avg_dur_list = []
+ for name, row in sessions:
+ total_dur += num(row[1])
+ total_push += num(row[2])
+ total_room += num(row[3])
+ if num(row[4]) > 0:
+ avg_dur_list.append(num(row[4]))
+ total_interact += num(row[5])
+ total_gift += num(row[6])
+ total_soul += num(row[7])
+ total_follow += num(row[8])
+ o = num(row[9])
+ if o > max_online:
+ max_online = o
+ avg_dur_list = [x for x in avg_dur_list if x and x > 0]
+ avg_dur = round(sum(avg_dur_list) / len(avg_dur_list), 1) if avg_dur_list else 0
+ with_data = [s[0] for s in sessions if num(s[1][1]) > 0]
+ stats = {
+ 'total_dur': total_dur, 'total_push': total_push, 'total_room': total_room,
+ 'total_interact': total_interact, 'total_gift': total_gift, 'total_soul': total_soul,
+ 'total_follow': total_follow, 'max_online': max_online, 'avg_dur': avg_dur,
+ 'sessions_count': len(sessions), 'with_data_count': len(with_data), 'with_data_names': with_data,
+ }
+ return sessions, stats
+
+
+def run_all_months(token):
+ """遍历所有月份 sheet,汇总总数据并分月展示。"""
+ month_sheets = get_month_sheets_sorted(token)
+ if not month_sheets:
+ print('❌ 未找到任何标题含「x月」的工作表')
+ return
+ grand = {
+ 'total_dur': 0, 'total_push': 0, 'total_room': 0, 'total_interact': 0,
+ 'total_gift': 0, 'total_soul': 0, 'total_follow': 0, 'max_online': 0,
+ 'avg_dur_sum': 0.0, 'avg_dur_n': 0, 'sessions_count': 0, 'with_data_count': 0,
+ }
+ per_month = []
+ for sheet_id, title in month_sheets:
+ vals = read_range(token, f'{sheet_id}!A1:AG15')
+ sessions, stats = parse_sheet_vals(vals) if vals else (None, None)
+ if not stats:
+ per_month.append((title, None))
+ continue
+ per_month.append((title, stats))
+ grand['total_dur'] += stats['total_dur']
+ grand['total_push'] += stats['total_push']
+ grand['total_room'] += stats['total_room']
+ grand['total_interact'] += stats['total_interact']
+ grand['total_gift'] += stats['total_gift']
+ grand['total_soul'] += stats['total_soul']
+ grand['total_follow'] += stats['total_follow']
+ if stats['max_online'] > grand['max_online']:
+ grand['max_online'] = stats['max_online']
+ if stats['avg_dur'] > 0:
+ grand['avg_dur_sum'] += stats['avg_dur'] * stats['with_data_count']
+ grand['avg_dur_n'] += stats['with_data_count']
+ grand['sessions_count'] += stats['sessions_count']
+ grand['with_data_count'] += stats['with_data_count']
+ grand_avg_dur = round(grand['avg_dur_sum'] / grand['avg_dur_n'], 1) if grand['avg_dur_n'] else 0
+ # 输出
+ print('=' * 60)
+ print('飞书运营报表 · 全部月份总数据汇总')
+ print('=' * 60)
+ print(f'涉及工作表:共 {len(month_sheets)} 个月 → {", ".join(t for _, t in month_sheets)}')
+ print()
+ print('【各月明细】')
+ print('-' * 60)
+ for title, stats in per_month:
+ if not stats:
+ print(f' {title}: 未解析到数据')
+ continue
+ print(f' {title}')
+ print(f' 有数据场次 {stats["with_data_count"]} 场 | 时长 {stats["total_dur"]} 分钟 | '
+ f'推流 {stats["total_push"]} | 进房 {stats["total_room"]} | '
+ f'互动 {stats["total_interact"]} | 礼物 {stats["total_gift"]} | '
+ f'灵魂力 {stats["total_soul"]} | 关注 {stats["total_follow"]} | 最高在线 {stats["max_online"]}')
+ print('-' * 60)
+ print('【全部月份合计】')
+ print(f' 总时长(分钟) {grand["total_dur"]}')
+ print(f' Soul推流人数 {grand["total_push"]}')
+ print(f' 进房人数 {grand["total_room"]}')
+ print(f' 互动数量 {grand["total_interact"]}')
+ print(f' 礼物 {grand["total_gift"]}')
+ print(f' 灵魂力 {grand["total_soul"]}')
+ print(f' 增加关注 {grand["total_follow"]}')
+ print('【全部月份取值】')
+ print(f' 最高在线(各场最大) {grand["max_online"]}')
+ print(f' 人均时长(加权平均) {grand_avg_dur} 分钟')
+ print(f' 表内场次列合计 {grand["sessions_count"]} 列')
+ print(f' 有数据场次合计 {grand["with_data_count"]} 场')
+ print('=' * 60)
+
+
+def main():
+ month_num = 2
+ run_all = False
+ if len(sys.argv) >= 2:
+ arg = str(sys.argv[1]).strip().lower()
+ if arg in ('all', '全部', 'all月'):
+ run_all = True
+ else:
+ try:
+ month_num = int(sys.argv[1])
+ if month_num not in (1, 2):
+ month_num = 2
+ except ValueError:
+ pass
+ token = load_token() or refresh_token()
+ if not token:
+ print('❌ 无法获取飞书 Token')
+ sys.exit(1)
+ if run_all:
+ run_all_months(token)
+ return
+ sheet_id, month_label = resolve_sheet_id_for_month(token, month_num)
+ if sheet_id is None:
+ print(f'❌ 未找到第1个月({month_label})对应的工作表,请确认飞书表格中存在标题含「1月」的 sheet')
+ sys.exit(1)
+ vals = read_range(token, f'{sheet_id}!A1:AG15')
+ if not vals or len(vals) < 12:
+ print('❌ 读取表格失败或数据行不足')
+ sys.exit(1)
+ # 找表头行:某行单元格含「场」
+ header_row_idx = None
+ for ri in (1, 0, 2):
+ if ri >= len(vals):
+ continue
+ row = vals[ri]
+ for c in row:
+ if '场' in str(c):
+ header_row_idx = ri
+ break
+ if header_row_idx is not None:
+ break
+ if header_row_idx is None:
+ print('❌ 未找到场次表头行')
+ sys.exit(1)
+ header = vals[header_row_idx]
+ # 数据从下一行开始,共10行:主题、时长、推流、进房、人均时长、互动、礼物、灵魂力、增加关注、最高在线
+ data_start = header_row_idx + 1
+ sessions = [] # [(场次名, [10个值]), ...]
+ for col_idx in range(len(header)):
+ cell = str(header[col_idx]).strip()
+ if '场' not in cell:
+ continue
+ row_vals = []
+ for row_offset in range(10):
+ ri = data_start + row_offset
+ if ri < len(vals) and col_idx < len(vals[ri]):
+ row_vals.append(vals[ri][col_idx])
+ else:
+ row_vals.append('')
+ sessions.append((cell, row_vals))
+ if not sessions:
+ print('❌ 未解析到任何场次数据')
+ sys.exit(1)
+ # 汇总:时长、推流、进房、互动、礼物、灵魂力、增加关注 相加;最高在线 取 max;人均时长 取非零平均
+ total_dur = total_push = total_room = total_interact = total_gift = total_soul = total_follow = 0
+ max_online = 0
+ avg_dur_list = []
+ for name, row in sessions:
+ duration = num(row[1])
+ push = num(row[2])
+ room = num(row[3])
+ avg_dur = num(row[4])
+ interact = num(row[5])
+ gift = num(row[6])
+ soul = num(row[7])
+ follow = num(row[8])
+ online = num(row[9])
+ total_dur += duration
+ total_push += push
+ total_room += room
+ total_interact += interact
+ total_gift += gift
+ total_soul += soul
+ total_follow += follow
+ if online > max_online:
+ max_online = online
+ if avg_dur > 0:
+ avg_dur_list.append(avg_dur)
+ avg_dur = round(sum(avg_dur_list) / len(avg_dur_list), 1) if avg_dur_list else 0
+ with_data = [(n, r) for n, r in sessions if num(r[1]) > 0] # 时长>0 视为有数据
+ # 输出
+ print('=' * 50)
+ print(f'飞书运营报表 · 第{month_num}个月({month_label})运营数据统计')
+ print('=' * 50)
+ print(f'表内场次列:共 {len(sessions)} 场')
+ print(f'有数据场次:共 {len(with_data)} 场 → {", ".join(s[0] for s in with_data)}')
+ print()
+ print('【合计】')
+ print(f' 时长(分钟) {total_dur}')
+ print(f' Soul推流人数 {total_push}')
+ print(f' 进房人数 {total_room}')
+ print(f' 互动数量 {total_interact}')
+ print(f' 礼物 {total_gift}')
+ print(f' 灵魂力 {total_soul}')
+ print(f' 增加关注 {total_follow}')
+ print('【取值】')
+ print(f' 最高在线(取各场最大) {max_online}')
+ print(f' 人均时长(非零场平均) {avg_dur} 分钟')
+ print('=' * 50)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/02_卡人(水)/水桥_平台对接/飞书管理/脚本/feishu_write_minutes_to_sheet.py b/02_卡人(水)/水桥_平台对接/飞书管理/脚本/feishu_write_minutes_to_sheet.py
new file mode 100644
index 00000000..ec6db44e
--- /dev/null
+++ b/02_卡人(水)/水桥_平台对接/飞书管理/脚本/feishu_write_minutes_to_sheet.py
@@ -0,0 +1,225 @@
+#!/usr/bin/env python3
+"""
+将「团队/内部会议纪要」与「派对今日总结」的图片上传到飞书运营报表对应单元格内。
+- 内部会议纪要:写在「内部会议纪要」这一行,按纪要上的日期(如 2月20日)填到该日期列。
+- 派对今日总结:写在「今日总结」这一行,按派对日期(如 2月19日)填到该日期列。
+不发飞书群。
+用法:python3 feishu_write_minutes_to_sheet.py [内部会议图片路径] [派对总结图片路径]
+ 默认:内部会议 20260220-094434.jpg → 2月20日列,派对总结 20260220-094442.png → 2月19日列
+"""
+import os
+import sys
+import json
+import requests
+from urllib.parse import quote
+
+FEISHU_SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
+TOKEN_FILE = os.path.join(FEISHU_SCRIPT_DIR, '.feishu_tokens.json')
+WIKI_TOKEN = os.environ.get('FEISHU_SPREADSHEET_TOKEN', 'wikcnIgAGSNHo0t36idHJ668Gfd')
+SHEET_ID = os.environ.get('FEISHU_SHEET_ID', '7A3Cy9')
+
+# 默认图片路径(内部会议 2月20日、派对总结 2月19日)
+DEFAULT_IMAGE_INTERNAL = '/Users/karuo/Downloads/20260220-094434.jpg'
+DEFAULT_IMAGE_PARTY = '/Users/karuo/Downloads/20260220-094442.png'
+
+# 飞书写入图片:单次请求 body 可能限制大小,图片过大时先压缩
+MAX_IMAGE_BYTES = 800 * 1024 # 800KB 以内较稳妥
+
+
+def load_token():
+ if not os.path.exists(TOKEN_FILE):
+ return None
+ with open(TOKEN_FILE, 'r', encoding='utf-8') as f:
+ return json.load(f).get('access_token')
+
+
+def refresh_token():
+ if not os.path.exists(TOKEN_FILE):
+ return None
+ with open(TOKEN_FILE, 'r', encoding='utf-8') as f:
+ data = json.load(f)
+ r = requests.post(
+ 'https://open.feishu.cn/open-apis/auth/v3/app_access_token/internal',
+ json={'app_id': 'cli_a48818290ef8100d', 'app_secret': 'dhjU0qWd5AzicGWTf4cTqhCWJOrnuCk4'},
+ timeout=10,
+ )
+ app_token = (r.json() or {}).get('app_access_token')
+ if not app_token:
+ return None
+ r2 = requests.post(
+ 'https://open.feishu.cn/open-apis/authen/v1/oidc/refresh_access_token',
+ headers={'Authorization': f'Bearer {app_token}', 'Content-Type': 'application/json'},
+ json={'grant_type': 'refresh_token', 'refresh_token': data.get('refresh_token')},
+ timeout=10,
+ )
+ out = r2.json()
+ if out.get('code') == 0 and out.get('data', {}).get('access_token'):
+ data['access_token'] = out['data']['access_token']
+ data['refresh_token'] = out['data'].get('refresh_token', data.get('refresh_token'))
+ with open(TOKEN_FILE, 'w', encoding='utf-8') as f:
+ json.dump(data, f, ensure_ascii=False, indent=2)
+ return data['access_token']
+ return None
+
+
+def read_range(token, range_str):
+ url = f'https://open.feishu.cn/open-apis/sheets/v2/spreadsheets/{WIKI_TOKEN}/values/{quote(range_str, safe="")}'
+ r = requests.get(url, headers={'Authorization': f'Bearer {token}'}, timeout=15)
+ if r.status_code != 200:
+ return None
+ body = r.json()
+ if body.get('code') != 0:
+ return None
+ return (body.get('data') or {}).get('valueRange', {}).get('values') or []
+
+
+def _col_letter(n):
+ s = ''
+ while True:
+ s = chr(65 + n % 26) + s
+ n = n // 26
+ if n <= 0:
+ break
+ return s
+
+
+def _resize_image_if_needed(path, max_bytes=MAX_IMAGE_BYTES):
+ """若图片超过 max_bytes,用 PIL 压缩后返回 bytes;否则直接读文件。"""
+ data = open(path, 'rb').read()
+ if len(data) <= max_bytes:
+ return data
+ try:
+ from PIL import Image
+ import io
+ img = Image.open(io.BytesIO(data))
+ if img.mode in ('RGBA', 'P'):
+ img = img.convert('RGB')
+ buf = io.BytesIO()
+ q = 85
+ while q >= 20:
+ buf.seek(0)
+ buf.truncate()
+ img.save(buf, 'JPEG', quality=q, optimize=True)
+ if buf.tell() <= max_bytes:
+ return buf.getvalue()
+ q -= 15
+ return buf.getvalue()
+ except Exception:
+ return data
+
+
+def write_image_to_cell(token, range_str, image_path, name=None):
+ """
+ 飞书 v2 写入图片到单元格:POST .../values_image,body 为 JSON,image 为整数数组(字节流)。
+ range 格式:sheetId!A1:A1(单个格子)
+ """
+ if not os.path.exists(image_path):
+ return 404, {'msg': f'文件不存在: {image_path}'}
+ name = name or os.path.basename(image_path)
+ data = _resize_image_if_needed(image_path)
+ # 飞书要求 image 为整数数组(图片二进制流)
+ image_arr = list(data)
+ url = f'https://open.feishu.cn/open-apis/sheets/v2/spreadsheets/{WIKI_TOKEN}/values_image'
+ payload = {
+ 'range': range_str if ':' in range_str else f'{range_str}:{range_str.split("!")[1]}',
+ 'name': name,
+ 'image': image_arr,
+ }
+ r = requests.post(
+ url,
+ headers={'Authorization': f'Bearer {token}', 'Content-Type': 'application/json'},
+ json=payload,
+ timeout=60,
+ )
+ try:
+ return r.status_code, r.json()
+ except Exception:
+ return r.status_code, {'msg': r.text[:200]}
+
+
+def main():
+ image_internal = (sys.argv[1] if len(sys.argv) > 1 else DEFAULT_IMAGE_INTERNAL).strip()
+ image_party = (sys.argv[2] if len(sys.argv) > 2 else DEFAULT_IMAGE_PARTY).strip()
+
+ token = load_token() or refresh_token()
+ if not token:
+ print('❌ 无法获取飞书 Token')
+ sys.exit(1)
+ vals = read_range(token, f'{SHEET_ID}!A1:AG50')
+ if not vals or len(vals) < 2:
+ print('❌ 读取表格失败')
+ sys.exit(1)
+ header = vals[0]
+ col_19 = col_20 = None
+ for idx, cell in enumerate(header):
+ c = str(cell).strip()
+ if c == '19':
+ col_19 = idx
+ if c == '20':
+ col_20 = idx
+ if col_19 is None or col_20 is None:
+ print('⚠️ 未找到日期列 19 或 20')
+ row_internal = None
+ row_party = None
+ for ri, row in enumerate(vals):
+ a1 = (row[0] if row and len(row) > 0 else '')
+ if a1 is None:
+ a1 = ''
+ a1 = str(a1).strip()
+ if not a1:
+ continue
+ if '内部会议' in a1 or ('团队' in a1 and '会议' in a1):
+ row_internal = ri + 1
+ if '今日总结' in a1:
+ row_party = ri + 1
+ if row_internal is None:
+ print('⚠️ 未找到「内部会议纪要」/「团队会议」行')
+ if row_party is None:
+ print('⚠️ 未找到「今日总结」行')
+
+ written = 0
+ if row_internal is not None and col_20 is not None and os.path.exists(image_internal):
+ range_cell = f'{SHEET_ID}!{_col_letter(col_20)}{row_internal}:{_col_letter(col_20)}{row_internal}'
+ code, body = write_image_to_cell(token, range_cell, image_internal, name='内部会议纪要_2月20.jpg')
+ if code == 200 and body.get('code') in (0, None):
+ print(f'✅ 已上传图片到「内部会议纪要」→ 2月20日列({range_cell})')
+ written += 1
+ else:
+ if code == 401 or body.get('code') in (99991677, 99991663):
+ token = refresh_token()
+ if token:
+ code, body = write_image_to_cell(token, range_cell, image_internal, name='内部会议纪要_2月20.jpg')
+ if code == 200 and body.get('code') in (0, None):
+ print('✅ 已上传图片到「内部会议纪要」→ 2月20日列')
+ written += 1
+ if not written:
+ print('❌ 上传内部会议图片失败:', code, body)
+ elif not os.path.exists(image_internal):
+ print('⚠️ 内部会议图片不存在:', image_internal)
+
+ if row_party is not None and col_19 is not None and os.path.exists(image_party):
+ range_cell = f'{SHEET_ID}!{_col_letter(col_19)}{row_party}:{_col_letter(col_19)}{row_party}'
+ code, body = write_image_to_cell(token, range_cell, image_party, name='派对今日总结_2月19.png')
+ if code == 200 and body.get('code') in (0, None):
+ print(f'✅ 已上传图片到「派对今日总结」→ 2月19日列({range_cell})')
+ written += 1
+ else:
+ if code == 401 or body.get('code') in (99991677, 99991663):
+ token = refresh_token()
+ if token:
+ code, body = write_image_to_cell(token, range_cell, image_party, name='派对今日总结_2月19.png')
+ if code == 200 and body.get('code') in (0, None):
+ print('✅ 已上传图片到「派对今日总结」→ 2月19日列')
+ written += 1
+ if not written:
+ print('❌ 上传派对总结图片失败:', code, body)
+ elif not os.path.exists(image_party):
+ print('⚠️ 派对总结图片不存在:', image_party)
+
+ if written == 0:
+ sys.exit(1)
+ print('(未发飞书群)')
+
+
+if __name__ == '__main__':
+ main()
diff --git a/02_卡人(水)/水桥_平台对接/飞书管理/脚本/soul_party_to_feishu_sheet.py b/02_卡人(水)/水桥_平台对接/飞书管理/脚本/soul_party_to_feishu_sheet.py
index b5156660..e82ba1cf 100644
--- a/02_卡人(水)/水桥_平台对接/飞书管理/脚本/soul_party_to_feishu_sheet.py
+++ b/02_卡人(水)/水桥_平台对接/飞书管理/脚本/soul_party_to_feishu_sheet.py
@@ -16,20 +16,28 @@ FEISHU_SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
TOKEN_FILE = os.path.join(FEISHU_SCRIPT_DIR, '.feishu_tokens.json')
WIKI_NODE_OR_SPREADSHEET_TOKEN = os.environ.get('FEISHU_SPREADSHEET_TOKEN', 'wikcnIgAGSNHo0t36idHJ668Gfd')
SHEET_ID = os.environ.get('FEISHU_SHEET_ID', '7A3Cy9')
+# 飞书群机器人 webhook(推送运营报表链接与场次数据)
+FEISHU_GROUP_WEBHOOK = os.environ.get('FEISHU_GROUP_WEBHOOK', 'https://open.feishu.cn/open-apis/bot/v2/hook/34b762fc-5b9b-4abb-a05a-96c8fb9599f1')
+OPERATION_REPORT_LINK = 'https://cunkebao.feishu.cn/wiki/wikcnIgAGSNHo0t36idHJ668Gfd?sheet=7A3Cy9'
# 写入列数:仅前 10 项(比率三项不填,表内公式自动算)
EFFECT_COLS = 10
# 各场效果数据(主题≤12字且含干货与数值、时长、推流、进房…)— 比率不写入
+# 主题写分析内容最核心干货;来源TXT可写在飞书群消息中
ROWS = {
- '96': [ '', 0, 0, 0, 0, 0, 0, 0, 0, 0 ], # 96场(无记录,占位;有数据后替换)
- '97': [ '', 0, 0, 0, 0, 0, 0, 0, 0, 0 ], # 97场(无记录,占位)
- '98': [ '', 0, 0, 0, 0, 0, 0, 0, 0, 0 ], # 98场(无记录,占位)
- '99': [ '', 116, 16976, 208, 0, 0, 4, 166, 12, 39 ], # 99场(派对已关闭截图)
- '100': [ '', 0, 0, 0, 0, 0, 0, 0, 0, 0 ], # 100场(无记录,占位)
+ '96': [ '', 0, 0, 0, 0, 0, 0, 0, 0, 0 ], # 96场(无记录,占位)
+ '97': [ '', 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
+ '98': [ '', 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
+ '99': [ '', 116, 16976, 208, 0, 0, 4, 166, 12, 39 ],
+ '100': [ '', 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
'103': [ '号商几毛卖十几 日销两万', 155, 46749, 545, 7, 34, 1, 8, 13, 47 ],
'104': [ 'AI创业最赚钱一月分享', 140, 36221, 367, 7, 49, 0, 0, 11, 38 ],
+ # 105场 2026-02-20:截图 138分钟/403进房/54最高在线/31关注/2礼物/24灵魂力,小助手 人均10min/互动170;推流截图中无填0
+ '105': [ '创业社群AI培训6980 电竞私域', 138, 0, 403, 10, 170, 2, 24, 31, 54 ],
}
+# 场次→按日期列填写时的日期(表头为当月日期 1~31),如 105场 对应 2月20日 → 列名 "20"
+SESSION_DATE_COLUMN = {'105': '20'} # 105场 填在 2月20日 列下
def load_token():
@@ -185,26 +193,45 @@ def _to_cell_value(v):
return str(v)
+def send_feishu_group_message(webhook_url, text):
+ """飞书群机器人:发送文本(msg_type=text)。"""
+ if not webhook_url or not text:
+ return False, None
+ payload = {'msg_type': 'text', 'content': {'text': text}}
+ try:
+ r = requests.post(webhook_url, json=payload, timeout=10)
+ return r.status_code == 200, r.json() if r.text else None
+ except Exception as e:
+ return False, str(e)
+
+
def main():
session = (sys.argv[1] if len(sys.argv) > 1 else '104').strip()
row = ROWS.get(session)
if not row:
- print('❌ 未知场次,可用: 96, 97, 98, 99, 100, 103, 104')
+ print('❌ 未知场次,可用: 96, 97, 98, 99, 100, 103, 104, 105')
sys.exit(1)
token = load_token() or refresh_and_load_token()
if not token:
sys.exit(1)
- # 只取前 10 项,并按数字类型写入(主题可为空字符串)
raw = (row + [None] * EFFECT_COLS)[:EFFECT_COLS]
values = [_to_cell_value(raw[0])] + [_to_cell_value(raw[i]) for i in range(1, EFFECT_COLS)]
spreadsheet_token = WIKI_NODE_OR_SPREADSHEET_TOKEN
sheet_id = SHEET_ID
- range_read = f"{sheet_id}!A1:Z30"
+ range_read = f"{sheet_id}!A1:AG30"
vals, read_code, read_body = read_sheet_range(token, spreadsheet_token, range_read)
- # 表格结构:第1行表头(2月、1、19),第2行「一、效果数据」+「104场」在某一列,A列是指标名(主题、时长...),数据填在 104场 那一列的 3~15 行
+ # 优先按当天日期列填:表头第1行多为 2月、1、2、…、20、…(日期),105场 填在 2月20日 → 找列 "20"
target_col_0based = None
- if vals and len(vals) >= 2:
- for row_idx in (1, 0): # 先查第2行再第1行
+ date_col = SESSION_DATE_COLUMN.get(session)
+ if vals and date_col:
+ row0 = vals[0] if len(vals) > 0 else []
+ for col_idx, cell in enumerate(row0):
+ if str(cell).strip() == date_col:
+ target_col_0based = col_idx
+ break
+ # 否则按「x场」列名找
+ if target_col_0based is None and vals and len(vals) >= 2:
+ for row_idx in (1, 0):
row_cells = vals[row_idx] if row_idx < len(vals) else []
for col_idx, cell in enumerate(row_cells):
if f"{session}场" in str(cell).strip():
@@ -214,14 +241,37 @@ def main():
break
if read_code != 200 or (read_body.get('code') not in (0, None)) and not vals:
print('⚠️ 读取表格失败:', read_code, read_body.get('msg', read_body))
+ # 发群消息用竖状格式(每行一项,便于阅读)
+ LABELS_GROUP = ['主题', '时长(分钟)', 'Soul推流人数', '进房人数', '人均时长(分钟)', '互动数量', '礼物', '灵魂力', '增加关注', '最高在线']
+
+ def _maybe_send_group(sess, raw_vals):
+ if sess != '105':
+ return
+ lines = [
+ '【Soul 派对运营报表】',
+ f'链接:{OPERATION_REPORT_LINK}',
+ '',
+ '105场(2月20日)已登记:',
+ ]
+ for i, label in enumerate(LABELS_GROUP):
+ val = raw_vals[i] if i < len(raw_vals) else ''
+ lines.append(f'{label}:{val}')
+ lines.append('数据来源:soul 派对 105场 20260220.txt')
+ msg = '\n'.join(lines)
+ ok, _ = send_feishu_group_message(FEISHU_GROUP_WEBHOOK, msg)
+ if ok:
+ print('✅ 已同步推送到飞书群(竖状格式)')
+ else:
+ print('⚠️ 飞书群推送失败(请检查 webhook)')
+
if target_col_0based is not None:
col_letter = _col_letter(target_col_0based)
- # 竖列写入:T3:T15 一列,values 为 [[v1],[v2],...[v13]]
range_col = f"{sheet_id}!{col_letter}3:{col_letter}{2 + len(values)}"
values_vertical = [[v] for v in values]
code, body = update_sheet_range(token, spreadsheet_token, range_col, values_vertical)
if code == 200 and body.get('code') == 0:
print(f'✅ 已写入飞书表格:{session}场 效果数据(竖列 {col_letter}3:{col_letter}{2+len(values)},共{len(values)}格)')
+ _maybe_send_group(session, raw)
return
if code == 401 or body.get('code') in (99991677, 99991663):
token = refresh_and_load_token()
@@ -229,8 +279,8 @@ def main():
code, body = update_sheet_range(token, spreadsheet_token, range_col, values_vertical)
if code == 200 and body.get('code') == 0:
print(f'✅ 已写入飞书表格:{session}场 效果数据(竖列 {col_letter})')
+ _maybe_send_group(session, raw)
return
- # 单列多行若报 90202(columns of value>range),则逐格写入
err = body.get('code')
if err == 90202 or (err and 'range' in str(body.get('msg', '')).lower()):
all_ok = True
@@ -248,11 +298,13 @@ def main():
break
if all_ok:
print(f'✅ 已写入飞书表格:{session}场 效果数据(竖列 {col_letter}3:{col_letter}{2+len(values)} 逐格)')
+ _maybe_send_group(session, raw)
return
print('❌ 按列更新失败:', code, body)
code, body = write_sheet_row(token, spreadsheet_token, sheet_id, values)
if code == 200 and (body.get('code') == 0 or body.get('code') is None):
print(f'✅ 已追加一行:{session}场 效果数据')
+ _maybe_send_group(session, raw)
return
if code == 401 or body.get('code') in (99991677, 99991663):
token = refresh_and_load_token()
@@ -260,6 +312,7 @@ def main():
code, body = write_sheet_row(token, spreadsheet_token, sheet_id, values)
if code == 200 and (body.get('code') == 0 or body.get('code') is None):
print(f'✅ 已追加一行:{session}场 效果数据')
+ _maybe_send_group(session, raw)
return
print('❌ 写入失败:', code, body)
if body.get('code') in (99991663, 99991677):
diff --git a/02_卡人(水)/水桥_平台对接/飞书管理/脚本/write_feb15_summary.py b/02_卡人(水)/水桥_平台对接/飞书管理/脚本/write_feb15_summary.py
index fbc1e4c7..8d605c22 100644
--- a/02_卡人(水)/水桥_平台对接/飞书管理/脚本/write_feb15_summary.py
+++ b/02_卡人(水)/水桥_平台对接/飞书管理/脚本/write_feb15_summary.py
@@ -26,13 +26,13 @@ TASKS = [
"分布式算力矩阵→三次对话吸收+资产全景+安全加固 📊 (85%)",
"全量扫描→33.9万IP防断网跑完+6984验证+1281高价值主机 🔍 (100%)",
"Soul派对→101场(2/16)与102场(2/17)纪要+主题迭代 🎙️ (100%)",
- "安全运维→小型宝塔攻击链处理+SSH加固待办+CKB NAS绑定 🛡️ (70%)",
+ "安全运维→宝塔攻击链处理+SSH加固待办+CKB NAS绑定 🛡️ (70%)",
],
"n_process": [
"【算力矩阵】2/15三次Agent对话吸收→资产清单(公司NAS/家NAS/存客宝/kr宝塔)→PCDN收益模型→规模化测算→部署路线(Docker/chroot)→紧急待办P0-P2",
"【全量扫描】2/16 33.9万IP、并发2000防断网→TCP存活8257、协议验证6984、高价值1281→反填04暴力破解→家宽优化SKILL吸收",
"【Soul派对】101场(程序员AI工具链×电动车民宿×金融)、102场(过年第一个红包发给谁×人生三贵人)→纪要产出+长图→话题迭代",
- "【安全】小型宝塔XMRig/后门清理→攻击IP封禁→存客宝/kr宝塔SSH待开→CKB NAS网心云绑定15880802661待执行",
+ "【安全】宝塔XMRig/后门清理→攻击IP封禁→存客宝/kr宝塔SSH待开→CKB NAS网心云绑定15880802661待执行",
],
"t_thoughts": [
"算力矩阵先摸清资产与安全,再规模化;家宽降并发可跑完全程",
diff --git a/02_卡人(水)/水桥_平台对接/飞书管理/运营报表_SKILL.md b/02_卡人(水)/水桥_平台对接/飞书管理/运营报表_SKILL.md
new file mode 100644
index 00000000..20300e0e
--- /dev/null
+++ b/02_卡人(水)/水桥_平台对接/飞书管理/运营报表_SKILL.md
@@ -0,0 +1,94 @@
+---
+name: 飞书运营报表
+description: Soul 派对运营报表全流程——截图→填表→发群;会议纪要图片上传;月度统计
+triggers: 运营报表、派对填表、派对截图填表发群、会议纪要上传、本月运营数据、全部月份统计
+parent: 飞书管理
+owner: 水桥
+group: 水
+version: "1.0"
+updated: "2026-02-20"
+---
+
+# 飞书运营报表 Skill
+
+> 截图 → 填写表格 → 发群(竖状格式);会议纪要图片入格;月度统计。
+
+---
+
+## 一、全流程:截图 → 填表 → 发群
+
+| 步骤 | 做什么 | 说明 |
+|:---|:---|:---|
+| **1. 截图/数据** | 派对关闭页 + 小助手弹窗 + 可选 TXT | 从截图取:时长、进房、最高在线、关注、礼物、灵魂力、人均时长、互动;主题从 TXT 提炼 ≤12 字 |
+| **2. 填表** | 在脚本 `ROWS` 里配好该场 10 项数据,按日期列或「x场」列写入 | 见下方「填写规则」 |
+| **3. 发群** | 写入成功后自动推送到飞书群 webhook | **发群内容必须用竖状格式**(每行一项,不用一串) |
+
+### 发群格式(竖状)
+
+发到群里的内容格式示例,**竖状**便于阅读:
+
+```
+【Soul 派对运营报表】
+链接:https://cunkebao.feishu.cn/wiki/wikcnIgAGSNHo0t36idHJ668Gfd?sheet=7A3Cy9
+
+105场(2月20日)已登记:
+主题:创业社群AI培训6980 电竞私域
+时长(分钟):138
+Soul推流人数:0
+进房人数:403
+人均时长(分钟):10
+互动数量:170
+礼物:2
+灵魂力:24
+增加关注:31
+最高在线:54
+数据来源:soul 派对 105场 20260220.txt
+```
+
+---
+
+## 二、填写规则(表格内)
+
+- **只填前 10 项**:主题、时长、Soul推流人数、进房人数、人均时长、互动数量、礼物、灵魂力、增加关注、最高在线
+- **按数字类型**写入,不填推流进房率、1分钟进多少人、加微率(表内公式自动算)
+- **主题** ≤12 字,含干货与数值
+- **按日期列**:表头为 1、2…19、20…,该场对应几号就填在几号列下
+- 数据竖列写入该列第 3~12 行
+
+---
+
+## 三、脚本与命令
+
+| 脚本 | 用途 |
+|:---|:---|
+| `soul_party_to_feishu_sheet.py [场次]` | 写入该场效果数据到运营报表;部分场次写入后自动发群(竖状) |
+| `feishu_write_minutes_to_sheet.py [内部图] [派对图]` | 内部会议纪要、派对今日总结**图片**上传到对应单元格(不发群) |
+| `feishu_sheet_monthly_stats.py [1\|2\|all]` | 统计第 1 月 / 第 2 月 / 全部月份运营数据 |
+
+**路径**:`02_卡人(水)/水桥_平台对接/飞书管理/脚本/`
+
+```bash
+# 写入 105 场并发群(竖状)
+python3 .../脚本/soul_party_to_feishu_sheet.py 105
+
+# 上传会议纪要图片到单元格
+python3 .../脚本/feishu_write_minutes_to_sheet.py
+
+# 本月 / 全部月份统计
+python3 .../脚本/feishu_sheet_monthly_stats.py 2
+python3 .../脚本/feishu_sheet_monthly_stats.py all
+```
+
+---
+
+## 四、配置
+
+| 项目 | 值 |
+|:---|:---|
+| 运营报表链接 | https://cunkebao.feishu.cn/wiki/wikcnIgAGSNHo0t36idHJ668Gfd?sheet=7A3Cy9 |
+| Token | 脚本同目录 `.feishu_tokens.json` |
+| 发群 webhook | 脚本内 `FEISHU_GROUP_WEBHOOK` 或环境变量 |
+
+---
+
+**父 Skill**:飞书管理(`SKILL.md`)
diff --git a/运营中枢/参考资料/iPhone12当Mac扩展屏_操作指南.md b/运营中枢/参考资料/iPhone12当Mac扩展屏_操作指南.md
new file mode 100644
index 00000000..4237032f
--- /dev/null
+++ b/运营中枢/参考资料/iPhone12当Mac扩展屏_操作指南.md
@@ -0,0 +1,85 @@
+# iPhone 12 当 Mac 扩展屏 — 操作指南
+
+> 苹果官方「随航」仅支持 iPad,本指南通过**第三方软件**让 iPhone 12 成为 Mac 的扩展屏。
+> 适用:MacBook(Intel / Apple Silicon)+ iPhone 12,同一 Wi‑Fi 或 USB 连接。
+
+---
+
+## 方案一:Duet Display(推荐,体验最好)
+
+**特点**:延迟低、支持触控、有线/无线均可;**明确支持 iPhone** 作为第二显示器。
+
+### 1. 下载安装
+
+| 设备 | 操作 |
+|------|------|
+| **Mac** | 打开 [Duet 官网下载页](https://www.duetdisplay.com/zh/onboarding/download-apps-basic),按你的 Mac 类型选:
• **Apple Silicon (M1/M2/M3 等)**:
• **Intel Mac**:
下载后把 Duet 拖到「应用程序」即可。 |
+| **iPhone 12** | 在 App Store 搜索 **「Duet Display」** 安装(付费应用,约 68–98 元一次性,或含 Pro 订阅)。 |
+
+### 2. 连接与权限(首次必做)
+
+1. **数据线连接**(推荐,延迟最低):用 **Lightning 转 USB** 线把 iPhone 12 连到 Mac。
+2. **Mac 上**:打开 Duet,菜单栏出现 Duet 图标;若提示「添加助手」或信任设备,按提示在 **iPhone 上输入锁屏密码** 完成配对。
+3. **授予权限**:
+ **系统设置 → 隐私与安全性 → 辅助功能** → 勾选 **Duet**(或 Duet Display)。
+ 若系统要求「屏幕录制」也勾选 Duet。
+4. **无线用法**(可选):同一 Wi‑Fi 下,Mac 与 iPhone 都打开 Duet,在 Duet 里选择「无线」连接(延迟会比有线略高)。
+
+### 3. 当扩展屏使用
+
+- 连接成功后,Mac 会把 **iPhone 12 识别为第二块显示器**。
+- 在 **系统设置 → 显示器** 里可调整「排列」:把 iPhone 放在主屏的左边/右边/上下,拖窗口到 iPhone 上即可当扩展屏用。
+- 在 Duet 菜单里可切换「**扩展桌面**」或「镜像」,以及分辨率等。
+
+### 4. 常见问题
+
+- **不识别 iPhone**:确认线缆可传数据(非仅充电线)、已在 iPhone 上点「信任此电脑」;重启 Duet 或重插线再试。
+- **卡顿**:优先用 **USB 有线**;关掉其他占带宽的应用。
+- **权限被收回**:系统更新后若失效,再到「辅助功能」「屏幕录制」里重新勾选 Duet。
+
+---
+
+## 方案二:Yam Display / Yam Air(成本更低)
+
+**特点**:Mac 端免费,iOS 端约 **¥58 一次性**;支持 USB 有线(Yam Display)或无线(Yam Air);**支持 iPhone**。
+
+### 1. 下载安装
+
+| 设备 | 操作 |
+|------|------|
+| **Mac** | 官网或 Mac 应用商店搜索 **Yam Display**,安装 Mac 版(免费)。 |
+| **iPhone 12** | App Store 搜索 **Yam Display** 或 **Yam Air** 安装(约 ¥58 买断)。 |
+
+### 2. 连接与使用
+
+- **有线**:用 Lightning 数据线连接 iPhone 与 Mac,打开 Mac 端与 iPhone 端 Yam Display,按提示信任设备;Mac 会多出一块「显示器」。
+- **无线**:使用 **Yam Air**,Mac 与 iPhone 在同一 Wi‑Fi 下,两端打开应用即可配对,iPhone 作为扩展屏。
+- 在 **系统设置 → 显示器** 中排列两块屏的位置,即可把窗口拖到 iPhone 上。
+
+### 3. 注意
+
+- 无线模式下延迟和画质会随网络波动;需要稳定体验建议用 USB 有线。
+
+---
+
+## 方案对比(简要)
+
+| 项目 | Duet Display | Yam Display / Yam Air |
+|------|--------------|------------------------|
+| iPhone 支持 | ✅ 支持 | ✅ 支持 |
+| 价格 | iOS 约 68–98 元起,可选 Pro 订阅 | Mac 免费,iOS 约 ¥58 买断 |
+| 有线/无线 | 都支持 | Yam 有线 / Yam Air 无线 |
+| 延迟 | 有线接近「零延迟」 | 有线较好,无线一般 |
+| 适用 | 追求体验、常当副屏用 | 预算敏感、偶尔当副屏 |
+
+---
+
+## 推荐执行顺序(iPhone 12 + 本机 MacBook)
+
+1. **优先试 Duet Display**:按上面「方案一」在 Mac 与 iPhone 12 装好、用 **USB 线** 连接并给好权限,确认能在「显示器」里看到第二块屏并拖窗口过去。
+2. 若 Duet 不符合预算或不想付费,再试 **Yam Display(有线)** 或 **Yam Air(无线)**。
+3. 日常使用:需要低延迟就保持 **有线连接**;临时用一下可用 **无线**(Duet 或 Yam Air)。
+
+---
+
+*文档生成:卡若AI · 运营中枢 | 依据公开资料与官网整理,供本机 iPhone 12 当 Mac 扩展屏使用。*
diff --git a/运营中枢/参考资料/卡若AI执行流程与对话全流程.md b/运营中枢/参考资料/卡若AI执行流程与对话全流程.md
new file mode 100644
index 00000000..09bb3b76
--- /dev/null
+++ b/运营中枢/参考资料/卡若AI执行流程与对话全流程.md
@@ -0,0 +1,201 @@
+# 卡若AI 执行流程与对话全流程
+
+> 一份文档说清:**卡若AI 内部执行流程** + **与你对话时的完整执行与回复流程**。
+> 版本:1.0 | 更新:2026-02-19
+
+---
+
+## 一、总览:两条线
+
+| 维度 | 内容 |
+|------|------|
+| **执行流程** | AI 接到任务后,内部「怎么想、怎么找技能、怎么干、怎么验、怎么收尾」的固定步骤。 |
+| **对话全流程** | 从你发出一条消息,到 AI 读完上下文、执行、回复(含复盘)的整条对话链路。 |
+
+二者关系:**对话全流程 = 你在对话里看到的「执行流程」的完整呈现**;每次对话都按同一套执行流程跑一遍,并在回复里按步骤让你看到。
+
+---
+
+## 二、卡若AI 内部执行流程(七步)
+
+以下为 AI 接到任务后**内部必须遵循**的步骤,来源于 `BOOTSTRAP.md` 第四节与 `卡若AI交互流程与强制执行条件.md`。
+
+```
+┌─────────────────────────────────────────────────────────────────────────────┐
+│ 卡若AI 内部执行流程(强制) │
+└─────────────────────────────────────────────────────────────────────────────┘
+
+ 你的输入(任务/问题)
+ │
+ ▼
+ ┌─────────────────────────────────────────────────────────────────────────┐
+ │ 1. 启动加载(只读必要的) │
+ │ 读 BOOTSTRAP.md → 读 SKILL_REGISTRY.md → 按需读对应 SKILL.md │
+ └─────────────────────────────────────────────────────────────────────────┘
+ │
+ ▼
+ ┌─────────────────────────────────────────────────────────────────────────┐
+ │ 2. 先思考,并简洁输出在对话框(强制) │
+ │ 目标是什么、该谁干、怎么干、可能卡在哪;结合 5 负责人、14 成员、54 技能 │
+ │ → 把结论用几句话输出,再动手。禁止不思考直接动手。 │
+ └─────────────────────────────────────────────────────────────────────────┘
+ │
+ ▼
+ ┌─────────────────────────────────────────────────────────────────────────┐
+ │ 3. 技能路由与方案扩展 │
+ │ 查 SKILL_REGISTRY.md 按触发词匹配 → 找到技能路径 → 读 SKILL.md │
+ │ 多技能按 金→水→木→火→土 优先级;可搜索扩展执行方案、验收标准。 │
+ └─────────────────────────────────────────────────────────────────────────┘
+ │
+ ▼
+ ┌─────────────────────────────────────────────────────────────────────────┐
+ │ 4. 执行 │
+ │ 理解 → 拆解 → 读取上下文 → 按 SKILL 步骤执行 → 每步简短总结 │
+ └─────────────────────────────────────────────────────────────────────────┘
+ │
+ ▼
+ ┌─────────────────────────────────────────────────────────────────────────┐
+ │ 5. 反复验证结果(强制) │
+ │ 结果是否与用户一开始的命令/目标匹配? │
+ │ · 匹配 → 进入对话结尾(复盘) │
+ │ · 不匹配 → 回溯 → 搜索(GitHub/Skill/网上) → 再思考 → 再执行 → 再验证 │
+ │ 循环直到达成或明确说明无法达成。 │
+ └─────────────────────────────────────────────────────────────────────────┘
+ │
+ ▼
+ ┌─────────────────────────────────────────────────────────────────────────┐
+ │ 6. 结果交付 │
+ │ 交付物/结论与目标一致;若无法达成则说明差距、原因、可选下一步。 │
+ └─────────────────────────────────────────────────────────────────────────┘
+ │
+ ▼
+ ┌─────────────────────────────────────────────────────────────────────────┐
+ │ 7. 对话结尾 = 强制复盘 │
+ │ 每次对话最终回复必须以「卡若复盘」完整块收尾;格式见复盘格式_固定规则 │
+ │ 多轮对话每轮结尾建议带简版复盘(🎯 + ▶)。 │
+ └─────────────────────────────────────────────────────────────────────────┘
+ │
+ ▼
+ 你的输出(结果 + 复盘)
+
+ 可选:有文件变更时执行 Gitea 同步;有可沉淀经验时写入 水溪/经验库/待沉淀/
+```
+
+---
+
+## 三、与你对话时的完整流程(你看到什么)
+
+从**你发出一条消息**到**收到带复盘的最终回复**,整条对话链路如下;AI 会在回复中按步骤呈现,方便你对照验收。
+
+```
+┌─────────────────────────────────────────────────────────────────────────────┐
+│ 与卡若AI 对话的完整执行与回复流程 │
+└─────────────────────────────────────────────────────────────────────────────┘
+
+ 你:输入任务(例如:「分析电脑情况并优化」)
+ │
+ ▼
+ ┌─────────────────────────────────────────────────────────────────────────┐
+ │ 步骤 1 · 导航与阅读(在回复中会写「已读…」) │
+ │ AI 读取:BOOTSTRAP、SKILL_REGISTRY、本交互流程、与任务相关的 SKILL 等 │
+ │ → 回复里一句话摘要:读了什么、为什么读。 │
+ └─────────────────────────────────────────────────────────────────────────┘
+ │
+ ▼
+ ┌─────────────────────────────────────────────────────────────────────────┐
+ │ 步骤 2 · 思考与扩展(在回复中会写「目标 / 执行方案」) │
+ │ AI 思考:目标、谁干、怎么干、卡点;在已有资料中搜索、扩展子步骤与验收标准 │
+ │ → 回复里写出:目标、执行方案(或「打算怎么干」)。 │
+ └─────────────────────────────────────────────────────────────────────────┘
+ │
+ ▼
+ ┌─────────────────────────────────────────────────────────────────────────┐
+ │ 步骤 3 · 任务分配(在回复中会写「本任务由…执行」) │
+ │ 单技能 → 读对应 SKILL 执行;多技能 → 金→水→木→火→土 依次或并行 │
+ │ → 回复里写出:路由到谁(如金仓/水溪/火炬)或「本步由卡若AI 直接执行」。 │
+ └─────────────────────────────────────────────────────────────────────────┘
+ │
+ ▼
+ ┌─────────────────────────────────────────────────────────────────────────┐
+ │ 步骤 4 · 执行与验证(在回复中按步列出做了什么、每步结果) │
+ │ 按 SKILL 步骤执行;每步简短总结;验证是否与你的目标匹配 │
+ │ → 不通过则回溯、再执行,最多 5 轮。 │
+ └─────────────────────────────────────────────────────────────────────────┘
+ │
+ ▼
+ ┌─────────────────────────────────────────────────────────────────────────┐
+ │ 步骤 5 · 结果交付(在回复中给出交付物或结论) │
+ │ 交付物路径、结论、或「未完全达成」时的差距与下一步。 │
+ └─────────────────────────────────────────────────────────────────────────┘
+ │
+ ▼
+ ┌─────────────────────────────────────────────────────────────────────────┐
+ │ 步骤 6 · 沉淀(可选,若有会注明) │
+ │ 写入开发文档、references 或 水溪/经验库/待沉淀/ 时在回复中注明路径。 │
+ └─────────────────────────────────────────────────────────────────────────┘
+ │
+ ▼
+ ┌─────────────────────────────────────────────────────────────────────────┐
+ │ 步骤 7 · 对话结尾 = 强制复盘 │
+ │ [卡若复盘](YYYY-MM-DD HH:mm) │
+ │ 🎯 目标·结果·达成率(一行,含百分比) │
+ │ 📌 过程(1 2 3) │
+ │ 💡 反思(1~3 点) │
+ │ 📝 总结 │
+ │ ▶ 下一步执行(含未完成/待跟进项,无则写「无」) │
+ └─────────────────────────────────────────────────────────────────────────┘
+ │
+ ▼
+ 你:收到完整回复(结果 + 复盘)
+```
+
+---
+
+## 四、对照表:执行流程 ↔ 对话中的呈现
+
+| 内部执行步骤 | 在与你对话中的呈现 |
+|--------------|--------------------|
+| 1. 启动加载 | 回复开头「已读 BOOTSTRAP、SKILL_REGISTRY、xxx SKILL」等 |
+| 2. 先思考并输出 | 回复中「目标:…」「执行方案:…」或「打算怎么干:…」 |
+| 3. 技能路由与扩展 | 「本任务由 金仓/水溪/… 执行」或「路由到 xxx,读 xxx/SKILL.md」 |
+| 4. 执行 | 按步列出「①…✓ ②…✓」或「执行了…」 |
+| 5. 反复验证 | 「验证:结果与目标匹配」或「不匹配,回溯后…」 |
+| 6. 结果交付 | 交付物路径、结论、或差距与下一步 |
+| 7. 强制复盘 | 回复末尾的 [卡若复盘] 完整块(🎯📌💡📝▶) |
+
+简单任务时,AI 可能把「步骤 1+2」合并、「步骤 3+4+5」合并,但**目标结果、交付、复盘**必须有。
+
+---
+
+## 五、标准命令(对话中可触发)
+
+你在对话里说这些,会触发固定动作(见 `BOOTSTRAP.md` 第五节):
+
+| 你说的大意 | AI 会做 |
+|------------|--------|
+| 任何需求/任务 | 查 SKILL_REGISTRY → 找技能 → 读 SKILL.md 执行 |
+| 复盘 | 按复盘格式输出(每轮可简版 🎯+▶,对话结束必须完整复盘) |
+| 沉淀 | 有价值经验写入 `02_卡人(水)/水溪_整理归档/经验库/待沉淀/` |
+| 有文件变更 | 对话结束前执行 `bash 01_卡资(金)/金仓_存储备份/Gitea管理/脚本/自动同步.sh` |
+| 新项目上线/内容发布/日常运维 | 读 `运营中枢/参考资料/Pipeline执行清单.md` 按步骤执行 |
+| 报告/导出/生成图片 | 输出到 `/Users/karuo/Documents/卡若Ai的文件夹/` 对应子目录,图片登记到 `图片/图片索引.md` |
+
+---
+
+## 六、小结
+
+- **执行流程**:启动加载 → 先思考并输出 → 技能路由与扩展 → 执行 → 反复验证 → 结果交付 → **强制复盘**(+ 可选沉淀与 Gitea 同步)。
+- **对话全流程**:你的输入 → AI 按「导航与阅读 → 思考与扩展 → 任务分配 → 执行与验证 → 结果交付 → 沉淀(可选) → **复盘**」在回复中呈现,你看到的是同一套执行流程的完整体现。
+- **强制**:先思考再动手、结果必须验证、**每次对话结尾必须用卡若复盘收尾**。复盘格式唯一标准:`运营中枢/参考资料/卡若复盘格式_固定规则.md`。
+
+---
+
+## 七、相关文件
+
+| 文件 | 路径 | 用途 |
+|------|------|------|
+| 启动指令 | `BOOTSTRAP.md` | 身份、团队、执行流程、标准命令 |
+| 技能注册表 | `SKILL_REGISTRY.md` | 按触发词查技能路径 |
+| 交互流程与强制条件 | `运营中枢/参考资料/卡若AI交互流程与强制执行条件.md` | 六步对接、对话形式、敏感任务协议 |
+| 复盘格式 | `运营中枢/参考资料/卡若复盘格式_固定规则.md` | 复盘块书写规范 |
+| 执行流程详细说明 | `运营中枢/参考资料/执行流程详细说明.md` | 统一流程简要索引 |
diff --git a/运营中枢/工作台/00_账号与API索引.md b/运营中枢/工作台/00_账号与API索引.md
index 4cde3e66..1a0610f8 100644
--- a/运营中枢/工作台/00_账号与API索引.md
+++ b/运营中枢/工作台/00_账号与API索引.md
@@ -135,22 +135,21 @@
| 名称 | IP | 配置 | 用途 | 宝塔面板地址 |
|------|-----|------|------|--------------|
-| 小型宝塔 | 42.194.232.22 | 2核4G 5M | 主力部署(Node 项目) | https://42.194.232.22:9988/ckbpanel |
| 存客宝 | 42.194.245.239 | 2核16G 50M | 私域银行业务 | https://42.194.245.239:9988 |
-| kr宝塔 | 43.139.27.93 | 2核4G 5M | 辅助服务器 | https://43.139.27.93:9988 |
+| kr宝塔 | 43.139.27.93 | 2核4G 5M | Node 项目主力 | https://43.139.27.93:9988 |
### SSH 登录(root)
| 项 | 值 |
|----|-----|
| 密码(通用) | `Zhiqun1984` |
-| 示例 | `ssh root@42.194.232.22` |
+| 示例(kr宝塔) | `ssh -p 22022 root@43.139.27.93` |
-### 宝塔面板登录(小型宝塔为例)
+### 宝塔面板登录(kr宝塔为例)
| 项 | 值 |
|----|-----|
-| 地址 | https://42.194.232.22:9988/ckbpanel |
+| 地址 | https://43.139.27.93:9988 |
| 账号 | `ckb` |
| 密码 | `zhiqun1984` |
@@ -158,7 +157,6 @@
| 服务器 | API 密钥 |
|--------|----------|
-| 小型宝塔 | `hsAWqFSi0GOCrunhmYdkxy92tBXfqYjd` |
| 存客宝 | `TNKjqDv5N1QLOU20gcmGVgr82Z4mXzRi` |
| kr宝塔 | `qcWubCdlfFjS2b2DMT1lzPFaDfmv1cBT` |
diff --git a/运营中枢/工作台/gitea_push_log.md b/运营中枢/工作台/gitea_push_log.md
index 5e0ab268..77dc4f77 100644
--- a/运营中枢/工作台/gitea_push_log.md
+++ b/运营中枢/工作台/gitea_push_log.md
@@ -38,3 +38,4 @@
| 2026-02-19 19:40:16 | 🔄 卡若AI 同步 2026-02-19 19:40 | 更新:金仓、水桥平台对接、运营中枢工作台 | 排除 >20MB: 5 个 |
| 2026-02-19 20:11:22 | 🔄 卡若AI 同步 2026-02-19 20:11 | 更新:金仓、运营中枢工作台 | 排除 >20MB: 5 个 |
| 2026-02-20 07:09:16 | 🔄 卡若AI 同步 2026-02-20 07:09 | 更新:金仓、水桥平台对接、运营中枢参考资料、运营中枢工作台 | 排除 >20MB: 5 个 |
+| 2026-02-20 07:15:11 | 🔄 卡若AI 同步 2026-02-20 07:15 | 更新:金仓、运营中枢工作台 | 排除 >20MB: 5 个 |
diff --git a/运营中枢/工作台/代码管理.md b/运营中枢/工作台/代码管理.md
index 936e0f6a..af2d7165 100644
--- a/运营中枢/工作台/代码管理.md
+++ b/运营中枢/工作台/代码管理.md
@@ -41,3 +41,4 @@
| 2026-02-19 19:40:16 | 成功 | 成功 | 🔄 卡若AI 同步 2026-02-19 19:40 | 更新:金仓、水桥平台对接、运营中枢工作台 | 排除 >20MB: 5 个 | [仓库](http://open.quwanzhi.com:3000/fnvtk/karuo-ai) [百科](http://open.quwanzhi.com:3000/fnvtk/karuo-ai/wiki) |
| 2026-02-19 20:11:22 | 成功 | 成功 | 🔄 卡若AI 同步 2026-02-19 20:11 | 更新:金仓、运营中枢工作台 | 排除 >20MB: 5 个 | [仓库](http://open.quwanzhi.com:3000/fnvtk/karuo-ai) [百科](http://open.quwanzhi.com:3000/fnvtk/karuo-ai/wiki) |
| 2026-02-20 07:09:16 | 成功 | 成功 | 🔄 卡若AI 同步 2026-02-20 07:09 | 更新:金仓、水桥平台对接、运营中枢参考资料、运营中枢工作台 | 排除 >20MB: 5 个 | [仓库](http://open.quwanzhi.com:3000/fnvtk/karuo-ai) [百科](http://open.quwanzhi.com:3000/fnvtk/karuo-ai/wiki) |
+| 2026-02-20 07:15:11 | 成功 | 成功 | 🔄 卡若AI 同步 2026-02-20 07:15 | 更新:金仓、运营中枢工作台 | 排除 >20MB: 5 个 | [仓库](http://open.quwanzhi.com:3000/fnvtk/karuo-ai) [百科](http://open.quwanzhi.com:3000/fnvtk/karuo-ai/wiki) |
diff --git a/运营中枢/工作台/存客宝宝塔服务器_配置与性能优化报告.md b/运营中枢/工作台/存客宝宝塔服务器_配置与性能优化报告.md
index 879899cb..a9f92a7e 100644
--- a/运营中枢/工作台/存客宝宝塔服务器_配置与性能优化报告.md
+++ b/运营中枢/工作台/存客宝宝塔服务器_配置与性能优化报告.md
@@ -22,7 +22,7 @@
| 项目 | 配置 | 说明 |
|------|------|------|
-| **CPU** | 2 核 | 与小型宝塔、kr宝塔同规格,算力适中 |
+| **CPU** | 2 核 | 与 kr宝塔同规格,算力适中 |
| **内存** | 16 GB | 三台宝塔中最高,适合跑数据库与多应用 |
| **系统盘** | 以控制台/实际挂载为准 | 建议保留 ≥20% 可用空间 |
| **操作系统** | 以宝塔/镜像为准 | 常见为 CentOS 7/8 或 TencentOS |
@@ -35,7 +35,7 @@
| **带宽类型** | 以腾讯云控制台为准 | 可能为包月或按量,影响计费 |
| **内网 IP** | 以实例详情为准 | 同地域 CVM 互通走内网 |
-- **与另两台对比**:小型宝塔、kr宝塔均为 5M;存客宝 50M 带宽单价与流量成本明显更高,是消费与优化重点。
+- **与 kr宝塔对比**:kr宝塔 5M;存客宝 50M 带宽单价与流量成本明显更高,是消费与优化重点。
### 1.4 宝塔与访问
diff --git a/运营中枢/工作台/宝塔与存客宝服务器_消费与流量说明.md b/运营中枢/工作台/宝塔与存客宝服务器_消费与流量说明.md
index 64ad1ac3..0dfe0efe 100644
--- a/运营中枢/工作台/宝塔与存客宝服务器_消费与流量说明.md
+++ b/运营中枢/工作台/宝塔与存客宝服务器_消费与流量说明.md
@@ -39,9 +39,8 @@ python3 "01_卡资(金)/金仓_存储备份/服务器管理/scripts/tencent_
| 服务器 | IP | 配置 | 带宽 | 用途 |
|----------|----------------|-------------|------|----------------|
-| 小型宝塔 | 42.194.232.22 | 2核4G 5M | 5M | 主力 Node 部署 |
| **存客宝** | **42.194.245.239** | **2核16G 50M** | **50M** | **私域银行业务** |
-| kr宝塔 | 43.139.27.93 | 2核4G 5M | 5M | 辅助/网关 |
+| kr宝塔 | 43.139.27.93 | 2核4G 5M | 5M | Node 项目/网关 |
- **存客宝** 是 **50M 带宽**,带宽费或按量流量费通常比 5M 机器高很多,是消费重点排查对象。
- 流量/带宽使用情况:
@@ -61,7 +60,7 @@ python3 "01_卡资(金)/金仓_存储备份/服务器管理/scripts/tencent_
- **建议**:在腾讯云「费用」里看「按产品」明细,重点看「云服务器」「公网网络」;必要时设流量/费用告警。
3. **多台机器同时跑**
- - 三台(小型宝塔、存客宝、kr宝塔)都在腾讯云时,月费叠加。存客宝配置最高,通常占比最大。
+ - 两台(存客宝、kr宝塔)都在腾讯云时,月费叠加。存客宝配置最高,通常占比最大。
- **建议**:在账单里按实例/项目拆分,确认是哪台、哪项消费涨了。
4. **新业务或活动**
@@ -93,7 +92,7 @@ python3 "01_卡资(金)/金仓_存储备份/服务器管理/scripts/tencent_
### 5.2 本机已执行的检查(当前结果)
-- **快速检查三台宝塔**:已执行 `脚本/快速检查服务器.py`。结果:小型宝塔 API 连接异常;存客宝、kr宝塔 返回 **IP校验失败**(当前本机 IP 未加入宝塔 API 白名单)。
+- **快速检查两台宝塔**:已执行 `脚本/快速检查服务器.py`。结果:存客宝、kr宝塔 返回 **IP校验失败**(当前本机 IP 未加入宝塔 API 白名单)。
- **SSH 存客宝**:已用 `sshpass` 尝试,连接仍被服务器关闭(可能已禁用密码登录、仅允许密钥或安全策略限制),需你在可登录的环境执行下方命令。
### 5.3 你需要直接执行的命令(按顺序做)