feat: 完成2026-06-09版本迭代更新
此版本包含: 1. 新增位置消息发送与展示功能 2. 完善多语言本地化文案 3. 新增安卓端管理空间Activity与图标背景 4. 优化摇一摇开关逻辑与深度链接配置 5. 新增信息流平台过滤与A/B测试后台功能 6. 更新签名配置与构建脚本 7. 修复若干已知问题与代码优化
This commit is contained in:
19
Scripts/read_db_config.py
Normal file
19
Scripts/read_db_config.py
Normal file
@@ -0,0 +1,19 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""读取服务器数据库配置"""
|
||||
import paramiko
|
||||
|
||||
HOST = '123.207.67.197'
|
||||
PORT = 22
|
||||
USER = 'root'
|
||||
PASS = '520Kiss123'
|
||||
|
||||
ssh = paramiko.SSHClient()
|
||||
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
ssh.connect(HOST, port=PORT, username=USER, password=PASS, timeout=15)
|
||||
|
||||
# 读取数据库配置
|
||||
stdin, stdout, stderr = ssh.exec_command('cat /www/wwwroot/tools.wktyl.com/application/database.php')
|
||||
print(stdout.read().decode())
|
||||
|
||||
ssh.close()
|
||||
221
Scripts/test_platform_filter.py
Normal file
221
Scripts/test_platform_filter.py
Normal file
@@ -0,0 +1,221 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
@name 平台过滤接口测试脚本
|
||||
@desc 测试后台全平台/全分类关闭后,API接口是否正确返回空数据
|
||||
@created 2026-06-09
|
||||
@updated 2026-06-09
|
||||
"""
|
||||
|
||||
import requests
|
||||
import json
|
||||
import sys
|
||||
import time
|
||||
|
||||
BASE_URL = "https://tools.wktyl.com"
|
||||
PLATFORM = "android"
|
||||
|
||||
results = {"passed": 0, "failed": 0}
|
||||
|
||||
|
||||
def record_pass():
|
||||
results["passed"] += 1
|
||||
|
||||
def record_fail():
|
||||
results["failed"] += 1
|
||||
|
||||
|
||||
def test_api(name, url, expect_empty_list=False, expect_empty_channels=False, check_platform_field=False, headers=None):
|
||||
"""测试API接口"""
|
||||
try:
|
||||
h = headers or {}
|
||||
resp = requests.get(url, headers=h, timeout=20)
|
||||
data = resp.json()
|
||||
code = data.get("code", 0)
|
||||
|
||||
if code != 1:
|
||||
print(f" ✗ {name}: 接口返回错误 code={code}, msg={data.get('msg', '')}")
|
||||
record_fail()
|
||||
return data
|
||||
|
||||
result = data.get("data", {})
|
||||
|
||||
if expect_empty_list:
|
||||
items = result.get("list", [])
|
||||
if len(items) > 0:
|
||||
print(f" ✗ {name}: 期望空列表,但返回了 {len(items)} 条数据")
|
||||
record_fail()
|
||||
else:
|
||||
print(f" ✓ {name}: 正确返回空列表")
|
||||
record_pass()
|
||||
|
||||
if expect_empty_channels:
|
||||
channels = result.get("channels", [])
|
||||
if len(channels) > 0:
|
||||
print(f" ✗ {name}: 期望空频道列表,但返回了 {len(channels)} 个频道")
|
||||
record_fail()
|
||||
else:
|
||||
print(f" ✓ {name}: 正确返回空频道列表")
|
||||
record_pass()
|
||||
|
||||
if check_platform_field:
|
||||
plat = result.get("platform", "")
|
||||
if plat == PLATFORM:
|
||||
print(f" ✓ {name}: platform字段正确 ({plat})")
|
||||
record_pass()
|
||||
else:
|
||||
print(f" ✗ {name}: platform字段不正确 (期望={PLATFORM}, 实际={plat})")
|
||||
record_fail()
|
||||
|
||||
return result
|
||||
|
||||
except Exception as e:
|
||||
print(f" ✗ {name}: 请求异常 - {e}")
|
||||
record_fail()
|
||||
return None
|
||||
|
||||
|
||||
def test_data_count(name, url, headers=None):
|
||||
"""测试接口返回的数据条数"""
|
||||
try:
|
||||
h = headers or {}
|
||||
resp = requests.get(url, headers=h, timeout=20)
|
||||
data = resp.json()
|
||||
if data.get("code") != 1:
|
||||
print(f" ✗ {name}: 接口返回错误 code={data.get('code')}")
|
||||
record_fail()
|
||||
return -1
|
||||
result = data.get("data", {})
|
||||
items = result.get("list", [])
|
||||
count = len(items)
|
||||
print(f" ✓ {name}: 返回 {count} 条数据")
|
||||
record_pass()
|
||||
return count
|
||||
except Exception as e:
|
||||
print(f" ✗ {name}: 请求异常 - {e}")
|
||||
record_fail()
|
||||
return -1
|
||||
|
||||
|
||||
def main():
|
||||
print("=" * 60)
|
||||
print("平台过滤接口测试")
|
||||
print(f"测试平台: {PLATFORM}")
|
||||
print(f"基础URL: {BASE_URL}")
|
||||
print("=" * 60)
|
||||
|
||||
headers_with_platform = {"X-Platform": PLATFORM}
|
||||
|
||||
# ============================================================
|
||||
# 第一步:测试正常状态(有启用分类时)
|
||||
# ============================================================
|
||||
print("\n--- 第一步:测试正常状态(有启用分类) ---")
|
||||
|
||||
print("\n[1] channels接口 - platform参数")
|
||||
test_api("channels(platform)",
|
||||
f"{BASE_URL}/api/feed/channels?platform={PLATFORM}",
|
||||
check_platform_field=True)
|
||||
|
||||
print("\n[2] list接口 - channel=all + platform")
|
||||
test_data_count("list(all+platform)",
|
||||
f"{BASE_URL}/api/feed/list?channel=all&platform={PLATFORM}&limit=5")
|
||||
|
||||
print("\n[3] mix接口 - platform参数")
|
||||
test_data_count("mix(+platform)",
|
||||
f"{BASE_URL}/api/feed/mix?platform={PLATFORM}&limit=5")
|
||||
|
||||
print("\n[4] trending接口 - platform参数")
|
||||
test_data_count("trending(+platform)",
|
||||
f"{BASE_URL}/api/feed/trending?platform={PLATFORM}&limit=5")
|
||||
|
||||
print("\n[5] recommend接口 - platform参数")
|
||||
test_data_count("recommend(+platform)",
|
||||
f"{BASE_URL}/api/feed/recommend?platform={PLATFORM}&limit=5")
|
||||
|
||||
print("\n[6] random接口 - platform参数")
|
||||
test_data_count("random(+platform)",
|
||||
f"{BASE_URL}/api/feed/random?platform={PLATFORM}&limit=5")
|
||||
|
||||
print("\n[7] list接口 - 指定频道poetry + platform")
|
||||
test_data_count("list(poetry+platform)",
|
||||
f"{BASE_URL}/api/feed/list?channel=poetry&platform={PLATFORM}&limit=5")
|
||||
|
||||
# ============================================================
|
||||
# 第二步:测试向后兼容性(不传platform参数)
|
||||
# ============================================================
|
||||
print("\n--- 第二步:测试向后兼容性(不传platform) ---")
|
||||
|
||||
print("\n[8] channels接口 - 无platform参数")
|
||||
test_data_count("channels(无platform)",
|
||||
f"{BASE_URL}/api/feed/channels")
|
||||
|
||||
print("\n[9] list接口 - 无platform参数")
|
||||
test_data_count("list(无platform)",
|
||||
f"{BASE_URL}/api/feed/list?channel=all&limit=5")
|
||||
|
||||
# ============================================================
|
||||
# 第三步:测试X-Platform请求头
|
||||
# ============================================================
|
||||
print("\n--- 第三步:测试X-Platform请求头 ---")
|
||||
|
||||
test_data_count("channels(X-Platform头)",
|
||||
f"{BASE_URL}/api/feed/channels",
|
||||
headers=headers_with_platform)
|
||||
|
||||
test_data_count("list(X-Platform头)",
|
||||
f"{BASE_URL}/api/feed/list?channel=all&limit=5",
|
||||
headers=headers_with_platform)
|
||||
|
||||
# ============================================================
|
||||
# 第四步:测试platform_config接口
|
||||
# ============================================================
|
||||
print("\n--- 第四步:测试platform_config接口 ---")
|
||||
|
||||
try:
|
||||
resp = requests.get(f"{BASE_URL}/api/feed/platform_config?platform={PLATFORM}", timeout=15)
|
||||
data = resp.json()
|
||||
if data.get("code") == 1:
|
||||
result = data.get("data", {})
|
||||
enabled = result.get("enabled_count", 0)
|
||||
disabled = result.get("disabled_count", 0)
|
||||
print(f" ✓ platform_config: 启用={enabled}, 禁用={disabled}")
|
||||
record_pass()
|
||||
else:
|
||||
print(f" ✗ platform_config: 接口返回错误")
|
||||
record_fail()
|
||||
except Exception as e:
|
||||
print(f" ✗ platform_config: 请求异常 - {e}")
|
||||
record_fail()
|
||||
|
||||
# ============================================================
|
||||
# 第五步:测试无效平台参数(应忽略,正常返回数据)
|
||||
# ============================================================
|
||||
print("\n--- 第五步:测试无效平台参数 ---")
|
||||
|
||||
try:
|
||||
resp = requests.get(f"{BASE_URL}/api/feed/list?channel=all&platform=invalid_platform&limit=5", timeout=15)
|
||||
data = resp.json()
|
||||
items = data.get("data", {}).get("list", [])
|
||||
print(f" ✓ 无效platform参数: 返回 {len(items)} 条数据(应忽略无效平台)")
|
||||
record_pass()
|
||||
except Exception as e:
|
||||
print(f" ✗ 无效platform参数: 请求异常 - {e}")
|
||||
record_fail()
|
||||
|
||||
# ============================================================
|
||||
# 结果汇总
|
||||
# ============================================================
|
||||
print("\n" + "=" * 60)
|
||||
print(f"测试结果: ✓ 通过={results['passed']}, ✗ 失败={results['failed']}")
|
||||
print("=" * 60)
|
||||
|
||||
if results["failed"] > 0:
|
||||
print("\n⚠ 有测试失败,请检查!")
|
||||
sys.exit(1)
|
||||
else:
|
||||
print("\n✓ 全部测试通过!")
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
267
Scripts/test_platform_filter_full.py
Normal file
267
Scripts/test_platform_filter_full.py
Normal file
@@ -0,0 +1,267 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
@name 平台过滤核心场景测试(SSH版)
|
||||
@desc 通过SSH操作数据库,关闭所有平台后验证API返回空数据,然后恢复
|
||||
@created 2026-06-09
|
||||
@updated 2026-06-09
|
||||
"""
|
||||
|
||||
import requests
|
||||
import json
|
||||
import sys
|
||||
import time
|
||||
import paramiko
|
||||
|
||||
BASE_URL = "https://tools.wktyl.com"
|
||||
PLATFORM = "android"
|
||||
|
||||
# 服务器配置
|
||||
HOST = '123.207.67.197'
|
||||
PORT = 22
|
||||
USER = 'root'
|
||||
PASS = '520Kiss123'
|
||||
|
||||
results = {"passed": 0, "failed": 0}
|
||||
|
||||
|
||||
def record_pass():
|
||||
results["passed"] += 1
|
||||
|
||||
def record_fail():
|
||||
results["failed"] += 1
|
||||
|
||||
|
||||
def ssh_exec(cmd):
|
||||
"""执行SSH命令"""
|
||||
ssh = paramiko.SSHClient()
|
||||
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
ssh.connect(HOST, port=PORT, username=USER, password=PASS, timeout=15)
|
||||
stdin, stdout, stderr = ssh.exec_command(cmd)
|
||||
out = stdout.read().decode()
|
||||
err = stderr.read().decode()
|
||||
ssh.close()
|
||||
return out, err
|
||||
|
||||
|
||||
def clear_cache():
|
||||
"""清除服务器运行时缓存"""
|
||||
ssh_exec('rm -rf /www/wwwroot/tools.wktyl.com/runtime/cache/*')
|
||||
|
||||
|
||||
def backup_platform_enabled():
|
||||
"""备份当前platform_enabled字段"""
|
||||
cmd = """mysql -u tools -p'tools' tools -N -e "SELECT GROUP_CONCAT(CONCAT(id,':',platform_enabled) SEPARATOR '|||') FROM tool_feed_weight_config" """
|
||||
out, err = ssh_exec(cmd)
|
||||
return out.strip()
|
||||
|
||||
|
||||
def close_all_platforms():
|
||||
"""关闭所有平台 - 将所有记录的platform_enabled设为全false"""
|
||||
cmd = """mysql -u tools -p'tools' tools -e "UPDATE tool_feed_weight_config SET platform_enabled='{\\\"android\\\":false,\\\"ios\\\":false,\\\"harmony\\\":false,\\\"macos\\\":false,\\\"win\\\":false,\\\"web\\\":false,\\\"other\\\":false}'" """
|
||||
out, err = ssh_exec(cmd)
|
||||
if err and "ERROR" in err:
|
||||
print(f" ✗ 关闭所有平台失败: {err[:200]}")
|
||||
return False
|
||||
print(" ✓ 所有平台已关闭")
|
||||
return True
|
||||
|
||||
|
||||
def restore_platform_enabled(backup):
|
||||
"""恢复platform_enabled字段"""
|
||||
if not backup or backup == "NULL" or backup == "":
|
||||
print(" ⚠ 无备份数据,使用全开启恢复")
|
||||
cmd = """mysql -u tools -p'tools' tools -e "UPDATE tool_feed_weight_config SET platform_enabled='{\\\"android\\\":true,\\\"ios\\\":true,\\\"harmony\\\":true,\\\"macos\\\":true,\\\"win\\\":true,\\\"web\\\":true,\\\"other\\\":true}'" """
|
||||
out, err = ssh_exec(cmd)
|
||||
return
|
||||
|
||||
# 逐条恢复
|
||||
pairs = backup.split("|||")
|
||||
for pair in pairs:
|
||||
if ":" not in pair:
|
||||
continue
|
||||
parts = pair.split(":", 1)
|
||||
id_val = parts[0].strip()
|
||||
pe_val = parts[1].strip() if len(parts) > 1 else ""
|
||||
# 转义单引号
|
||||
pe_escaped = pe_val.replace("'", "\\'")
|
||||
if not pe_escaped or pe_escaped == "NULL":
|
||||
pe_escaped = ""
|
||||
cmd = f"""mysql -u tools -p'tools' tools -e "UPDATE tool_feed_weight_config SET platform_enabled='{pe_escaped}' WHERE id={id_val}" """
|
||||
ssh_exec(cmd)
|
||||
print(" ✓ 平台设置已恢复")
|
||||
|
||||
|
||||
def test_empty_result(name, url):
|
||||
"""测试接口是否返回空列表"""
|
||||
try:
|
||||
resp = requests.get(url, timeout=20)
|
||||
data = resp.json()
|
||||
if data.get("code") != 1:
|
||||
print(f" ✗ {name}: 接口返回错误 code={data.get('code')}, msg={data.get('msg', '')}")
|
||||
record_fail()
|
||||
return
|
||||
|
||||
result = data.get("data", {})
|
||||
items = result.get("list", result.get("channels", []))
|
||||
count = len(items)
|
||||
|
||||
if count == 0:
|
||||
print(f" ✓ {name}: 正确返回空数据 (0条)")
|
||||
record_pass()
|
||||
else:
|
||||
print(f" ✗ {name}: 期望空数据,但返回了 {count} 条")
|
||||
# 打印前2条数据的feed_type帮助调试
|
||||
for i, item in enumerate(items[:2]):
|
||||
print(f" 样本[{i}]: feed_type={item.get('feed_type', '?')}, title={item.get('title', '?')[:30]}")
|
||||
record_fail()
|
||||
|
||||
except Exception as e:
|
||||
print(f" ✗ {name}: 请求异常 - {e}")
|
||||
record_fail()
|
||||
|
||||
|
||||
def test_has_data(name, url):
|
||||
"""测试接口是否返回数据"""
|
||||
try:
|
||||
resp = requests.get(url, timeout=20)
|
||||
data = resp.json()
|
||||
if data.get("code") != 1:
|
||||
print(f" ✗ {name}: 接口返回错误 code={data.get('code')}")
|
||||
record_fail()
|
||||
return
|
||||
|
||||
result = data.get("data", {})
|
||||
items = result.get("list", result.get("channels", []))
|
||||
count = len(items)
|
||||
|
||||
if count > 0:
|
||||
print(f" ✓ {name}: 正确返回数据 ({count}条)")
|
||||
record_pass()
|
||||
else:
|
||||
print(f" ✗ {name}: 期望有数据,但返回了0条")
|
||||
record_fail()
|
||||
|
||||
except Exception as e:
|
||||
print(f" ✗ {name}: 请求异常 - {e}")
|
||||
record_fail()
|
||||
|
||||
|
||||
def main():
|
||||
print("=" * 60)
|
||||
print("平台过滤核心场景测试(SSH版)")
|
||||
print(f"测试场景: 后台全平台关闭 → API应返回空数据")
|
||||
print(f"测试平台: {PLATFORM}")
|
||||
print("=" * 60)
|
||||
|
||||
# 备份当前设置
|
||||
print("\n--- 备份当前平台设置 ---")
|
||||
backup = backup_platform_enabled()
|
||||
print(f" 备份完成 ({len(backup)} 字符)")
|
||||
|
||||
try:
|
||||
# ============================================================
|
||||
# 核心测试:全平台关闭
|
||||
# ============================================================
|
||||
print("\n--- 核心测试:关闭所有平台 ---")
|
||||
if not close_all_platforms():
|
||||
print("关闭平台失败,终止测试")
|
||||
sys.exit(1)
|
||||
|
||||
# 清除缓存
|
||||
print("\n 清除服务器缓存...")
|
||||
clear_cache()
|
||||
time.sleep(2)
|
||||
|
||||
print("\n--- 验证:全平台关闭后API应返回空数据 ---")
|
||||
|
||||
print("\n[1] channels接口 - platform=android")
|
||||
test_empty_result("channels(全关闭)",
|
||||
f"{BASE_URL}/api/feed/channels?platform={PLATFORM}")
|
||||
|
||||
print("\n[2] list接口 - channel=all + platform=android")
|
||||
test_empty_result("list(全关闭)",
|
||||
f"{BASE_URL}/api/feed/list?channel=all&platform={PLATFORM}&limit=5")
|
||||
|
||||
print("\n[3] mix接口 - platform=android")
|
||||
test_empty_result("mix(全关闭)",
|
||||
f"{BASE_URL}/api/feed/mix?platform={PLATFORM}&limit=5")
|
||||
|
||||
print("\n[4] trending接口 - platform=android")
|
||||
test_empty_result("trending(全关闭)",
|
||||
f"{BASE_URL}/api/feed/trending?platform={PLATFORM}&limit=5")
|
||||
|
||||
print("\n[5] recommend接口 - platform=android")
|
||||
test_empty_result("recommend(全关闭)",
|
||||
f"{BASE_URL}/api/feed/recommend?platform={PLATFORM}&limit=5")
|
||||
|
||||
print("\n[6] random接口 - platform=android")
|
||||
test_empty_result("random(全关闭)",
|
||||
f"{BASE_URL}/api/feed/random?platform={PLATFORM}&limit=5")
|
||||
|
||||
print("\n[7] list接口 - 指定频道poetry + platform=android")
|
||||
test_empty_result("list(poetry+全关闭)",
|
||||
f"{BASE_URL}/api/feed/list?channel=poetry&platform={PLATFORM}&limit=5")
|
||||
|
||||
print("\n[8] platform_config接口 - platform=android")
|
||||
try:
|
||||
resp = requests.get(f"{BASE_URL}/api/feed/platform_config?platform={PLATFORM}", timeout=15)
|
||||
data = resp.json()
|
||||
if data.get("code") == 1:
|
||||
result = data.get("data", {})
|
||||
enabled = result.get("enabled_count", 0)
|
||||
if enabled == 0:
|
||||
print(f" ✓ platform_config: 启用分类=0 (正确)")
|
||||
record_pass()
|
||||
else:
|
||||
print(f" ✗ platform_config: 启用分类={enabled} (期望0)")
|
||||
record_fail()
|
||||
except Exception as e:
|
||||
print(f" ✗ platform_config: 请求异常 - {e}")
|
||||
record_fail()
|
||||
|
||||
# ============================================================
|
||||
# 恢复:恢复平台设置
|
||||
# ============================================================
|
||||
print("\n--- 恢复:恢复平台设置 ---")
|
||||
restore_platform_enabled(backup)
|
||||
|
||||
# 清除缓存
|
||||
print("\n 清除服务器缓存...")
|
||||
clear_cache()
|
||||
time.sleep(2)
|
||||
|
||||
print("\n--- 验证:恢复后API应返回数据 ---")
|
||||
|
||||
print("\n[9] channels接口 - 恢复后")
|
||||
test_has_data("channels(恢复后)",
|
||||
f"{BASE_URL}/api/feed/channels?platform={PLATFORM}")
|
||||
|
||||
print("\n[10] list接口 - 恢复后")
|
||||
test_has_data("list(恢复后)",
|
||||
f"{BASE_URL}/api/feed/list?channel=all&platform={PLATFORM}&limit=5")
|
||||
|
||||
except Exception as e:
|
||||
print(f"\n⚠ 测试过程异常: {e}")
|
||||
# 尝试恢复
|
||||
print("尝试恢复平台设置...")
|
||||
restore_platform_enabled(backup)
|
||||
clear_cache()
|
||||
|
||||
# ============================================================
|
||||
# 结果汇总
|
||||
# ============================================================
|
||||
print("\n" + "=" * 60)
|
||||
print(f"测试结果: ✓ 通过={results['passed']}, ✗ 失败={results['failed']}")
|
||||
print("=" * 60)
|
||||
|
||||
if results["failed"] > 0:
|
||||
print("\n⚠ 有测试失败,请检查!")
|
||||
sys.exit(1)
|
||||
else:
|
||||
print("\n✓ 全部测试通过!")
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
72
Scripts/upload_ab_test.py
Normal file
72
Scripts/upload_ab_test.py
Normal file
@@ -0,0 +1,72 @@
|
||||
#!/usr/bin/env python3
|
||||
"""上传A/B测试相关文件到服务器"""
|
||||
import paramiko
|
||||
import os
|
||||
|
||||
HOST = '123.207.67.197'
|
||||
USER = 'root'
|
||||
PASS = '520Kiss123'
|
||||
|
||||
LOCAL_BASE = r'e:\project\flutter\f\xianyan\docs\toolsapi\application'
|
||||
REMOTE_BASE = '/www/wwwroot/tools.wktyl.com/application/'
|
||||
JS_LOCAL = r'e:\project\flutter\f\xianyan\docs\toolsapi\public\assets\js\backend'
|
||||
JS_REMOTE = '/www/wwwroot/tools.wktyl.com/public/assets/js/backend/'
|
||||
|
||||
FILES = [
|
||||
('admin/controller/AbTest.php', 'admin/controller/AbTest.php'),
|
||||
('admin/view/ab_test/index.html', 'admin/view/ab_test/index.html'),
|
||||
('admin/view/ab_test/add.html', 'admin/view/ab_test/add.html'),
|
||||
('admin/view/ab_test/edit.html', 'admin/view/ab_test/edit.html'),
|
||||
('admin/lang/zh-cn/ab_test.php', 'admin/lang/zh-cn/ab_test.php'),
|
||||
('api/controller/Feed.php', 'api/controller/Feed.php'),
|
||||
]
|
||||
|
||||
JS_FILES = [
|
||||
('ab_test.js', 'ab_test.js'),
|
||||
('feed_weight.js', 'feed_weight.js'),
|
||||
]
|
||||
|
||||
ssh = paramiko.SSHClient()
|
||||
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
ssh.connect(HOST, port=22, username=USER, password=PASS, timeout=15)
|
||||
sftp = ssh.open_sftp()
|
||||
|
||||
success = 0
|
||||
for local_name, remote_name in FILES:
|
||||
local_path = os.path.join(LOCAL_BASE, local_name)
|
||||
remote_path = REMOTE_BASE + remote_name
|
||||
if not os.path.exists(local_path):
|
||||
print(f" SKIP: {local_name} (not found)")
|
||||
continue
|
||||
# 创建远程目录
|
||||
remote_dir = os.path.dirname(remote_path).replace('\\', '/')
|
||||
try:
|
||||
sftp.stat(remote_dir)
|
||||
except:
|
||||
ssh.exec_command(f'mkdir -p {remote_dir}')
|
||||
import time; time.sleep(0.5)
|
||||
try:
|
||||
sftp.put(local_path, remote_path)
|
||||
print(f" OK: {local_name}")
|
||||
success += 1
|
||||
except Exception as e:
|
||||
print(f" FAIL: {local_name}: {e}")
|
||||
|
||||
for local_name, remote_name in JS_FILES:
|
||||
local_path = os.path.join(JS_LOCAL, local_name)
|
||||
remote_path = JS_REMOTE + remote_name
|
||||
if not os.path.exists(local_path):
|
||||
print(f" SKIP: {local_name} (not found)")
|
||||
continue
|
||||
try:
|
||||
sftp.put(local_path, remote_path)
|
||||
print(f" OK: JS/{local_name}")
|
||||
success += 1
|
||||
except Exception as e:
|
||||
print(f" FAIL: JS/{local_name}: {e}")
|
||||
|
||||
# 清除缓存
|
||||
ssh.exec_command('rm -rf /www/wwwroot/tools.wktyl.com/runtime/cache/* /www/wwwroot/tools.wktyl.com/runtime/temp/*')
|
||||
sftp.close()
|
||||
ssh.close()
|
||||
print(f"\nDone: {success}/{len(FILES)+len(JS_FILES)}")
|
||||
67
Scripts/upload_feed_fix.py
Normal file
67
Scripts/upload_feed_fix.py
Normal file
@@ -0,0 +1,67 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
@name 上传Feed控制器到服务器
|
||||
@desc SFTP上传修复后的Feed.php到服务器
|
||||
@created 2026-06-09
|
||||
@updated 2026-06-09
|
||||
"""
|
||||
|
||||
import paramiko
|
||||
import os
|
||||
|
||||
# 服务器配置
|
||||
HOST = '123.207.67.197'
|
||||
PORT = 22
|
||||
USER = 'root'
|
||||
PASS = '520Kiss123'
|
||||
|
||||
# 本地文件 -> 远程路径映射
|
||||
UPLOAD_MAP = {
|
||||
r'docs\toolsapi\application\api\controller\Feed.php': '/www/wwwroot/tools.wktyl.com/application/api/controller/Feed.php',
|
||||
r'docs\toolsapi\application\admin\controller\FeedWeight.php': '/www/wwwroot/tools.wktyl.com/application/admin/controller/FeedWeight.php',
|
||||
r'docs\toolsapi\application\admin\view\feed_weight\index.html': '/www/wwwroot/tools.wktyl.com/application/admin/view/feed_weight/index.html',
|
||||
r'docs\toolsapi\public\assets\js\backend\feed_weight.js': '/www/wwwroot/tools.wktyl.com/public/assets/js/backend/feed_weight.js',
|
||||
}
|
||||
|
||||
def upload():
|
||||
local_base = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
print(f"本地项目根目录: {local_base}")
|
||||
|
||||
ssh = paramiko.SSHClient()
|
||||
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
|
||||
print(f"连接服务器 {HOST}:{PORT}...")
|
||||
ssh.connect(HOST, port=PORT, username=USER, password=PASS, timeout=15)
|
||||
sftp = ssh.open_sftp()
|
||||
print("连接成功!")
|
||||
|
||||
for local_rel, remote_path in UPLOAD_MAP.items():
|
||||
local_path = os.path.join(local_base, local_rel)
|
||||
if not os.path.exists(local_path):
|
||||
print(f"[跳过] 本地文件不存在: {local_path}")
|
||||
continue
|
||||
|
||||
# 确保远程目录存在
|
||||
remote_dir = os.path.dirname(remote_path)
|
||||
try:
|
||||
sftp.stat(remote_dir)
|
||||
except FileNotFoundError:
|
||||
print(f" 创建远程目录: {remote_dir}")
|
||||
|
||||
print(f"上传: {local_rel} -> {remote_path}")
|
||||
sftp.put(local_path, remote_path)
|
||||
print(f" ✓ 上传成功")
|
||||
|
||||
sftp.close()
|
||||
|
||||
# 清除服务器缓存
|
||||
print("\n清除服务器运行时缓存...")
|
||||
stdin, stdout, stderr = ssh.exec_command('rm -rf /www/wwwroot/tools.wktyl.com/runtime/cache/*')
|
||||
print(f" 缓存清除: {stdout.read().decode()}")
|
||||
|
||||
ssh.close()
|
||||
print("\n✓ 全部上传完成!")
|
||||
|
||||
if __name__ == '__main__':
|
||||
upload()
|
||||
75
Scripts/upload_platform_filter.py
Normal file
75
Scripts/upload_platform_filter.py
Normal file
@@ -0,0 +1,75 @@
|
||||
|
||||
#!/usr/bin/env python3
|
||||
"""上传平台过滤相关PHP代码到服务器"""
|
||||
import paramiko
|
||||
import os
|
||||
|
||||
HOST = '123.207.67.197'
|
||||
PORT = 22
|
||||
USER = 'root'
|
||||
PASS = '520Kiss123'
|
||||
REMOTE_BASE = '/www/wwwroot/tools.wktyl.com/application/'
|
||||
LOCAL_BASE = os.path.join(os.path.dirname(__file__), '..', 'docs', 'toolsapi', 'application')
|
||||
|
||||
UPLOAD_FILES = [
|
||||
('admin/controller/FeedWeight.php', 'admin/controller/FeedWeight.php'),
|
||||
('admin/model/FeedWeightConfig.php', 'admin/model/FeedWeightConfig.php'),
|
||||
('admin/view/feed_weight/index.html', 'admin/view/feed_weight/index.html'),
|
||||
('admin/view/feed_weight/edit.html', 'admin/view/feed_weight/edit.html'),
|
||||
('admin/lang/zh-cn/feed_weight.php', 'admin/lang/zh-cn/feed_weight.php'),
|
||||
('api/controller/Feed.php', 'api/controller/Feed.php'),
|
||||
]
|
||||
|
||||
# JS文件在不同目录
|
||||
JS_LOCAL_BASE = os.path.join(os.path.dirname(__file__), '..', 'docs', 'toolsapi', 'public', 'assets', 'js', 'backend')
|
||||
JS_REMOTE_BASE = '/www/wwwroot/tools.wktyl.com/public/assets/js/backend/'
|
||||
JS_FILES = [
|
||||
('feed_weight.js', 'feed_weight.js'),
|
||||
]
|
||||
|
||||
def main():
|
||||
local_base = os.path.abspath(LOCAL_BASE)
|
||||
print(f"本地代码目录: {local_base}")
|
||||
print(f"待上传文件: {len(UPLOAD_FILES)} 个\n")
|
||||
|
||||
ssh = paramiko.SSHClient()
|
||||
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||
ssh.connect(HOST, port=PORT, username=USER, password=PASS, timeout=15)
|
||||
sftp = ssh.open_sftp()
|
||||
|
||||
success_count = 0
|
||||
for local_rel, remote_rel in UPLOAD_FILES:
|
||||
local_path = os.path.join(local_base, local_rel.replace('/', os.sep))
|
||||
remote_path = REMOTE_BASE + remote_rel
|
||||
if not os.path.exists(local_path):
|
||||
print(f" ⚠️ 本地文件不存在: {local_path}")
|
||||
continue
|
||||
try:
|
||||
sftp.put(local_path, remote_path)
|
||||
print(f" ✅ {local_rel}")
|
||||
success_count += 1
|
||||
except Exception as e:
|
||||
print(f" ❌ {local_rel}: {e}")
|
||||
|
||||
# 上传JS文件
|
||||
js_local_base = os.path.abspath(JS_LOCAL_BASE)
|
||||
for local_name, remote_name in JS_FILES:
|
||||
local_path = os.path.join(js_local_base, local_name)
|
||||
remote_path = JS_REMOTE_BASE + remote_name
|
||||
if not os.path.exists(local_path):
|
||||
print(f" ⚠️ 本地JS文件不存在: {local_path}")
|
||||
continue
|
||||
try:
|
||||
sftp.put(local_path, remote_path)
|
||||
print(f" ✅ JS: {local_name}")
|
||||
success_count += 1
|
||||
except Exception as e:
|
||||
print(f" ❌ JS: {local_name}: {e}")
|
||||
|
||||
sftp.close()
|
||||
ssh.exec_command('rm -rf /www/wwwroot/tools.wktyl.com/runtime/cache/*')
|
||||
ssh.close()
|
||||
print(f"\n✅ 上传完成: {success_count}/{len(UPLOAD_FILES) + len(JS_FILES)}")
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in New Issue
Block a user