update 2025-01-30 09:22:45

This commit is contained in:
kenzok8 2025-01-30 09:22:45 +08:00
parent c2a12659a1
commit 38173d7ab3
9 changed files with 672 additions and 157 deletions

View File

@ -6,7 +6,7 @@ include $(TOPDIR)/rules.mk
PKG_MAINTAINER:=Thaolga <https://github.com/Thaolga/luci-app-nekobox>
PKG_NAME:=luci-app-nekobox
PKG_VERSION:=1.7.2
PKG_VERSION:=1.7.3
PKG_RELEASE:=cn
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)

View File

@ -128,3 +128,446 @@ body {
background-color: #00bfff;
color: #fff;
}
.btn-purple {
background-color: #6f42c1;
color: #fff;
border: 1px solid #6f42c1;
border-radius: 4px;
padding: 8px 16px;
font-size: 18px;
font-weight: 600;
text-align: center;
cursor: pointer;
transition: all 0.3s ease;
}
.btn-purple:hover {
background-color: #5a32a3;
color: #fff;
border-color: #5a32a3;
transform: translateY(-2px);
}
.btn-purple:active {
background-color: #4c2791;
color: #fff;
border-color: #4c2791;
transform: translateY(2px);
}
.btn-purple:disabled {
background-color: #e0e0e0;
color: #9e9e9e;
border-color: #bdbdbd;
cursor: not-allowed;
}
.btn-orange {
background-color: #fd7e14;
color: #fff;
border: 1px solid #fd7e14;
border-radius: 6px;
padding: 8px 16px;
font-weight: 600;
text-align: center;
cursor: pointer;
transition: all 0.3s ease;
}
.btn-orange:hover {
background-color: #e76d07;
color: #fff;
border-color: #e76d07;
transform: translateY(-2px);
}
.btn-orange:active {
background-color: #d65c04;
color: #fff;
border-color: #d65c04;
transform: translateY(2px);
}
.btn-orange:disabled {
background-color: #e0e0e0;
color: #9e9e9e;
border-color: #bdbdbd;
cursor: not-allowed;
}
.btn-teal {
background-color: #20c997;
color: #fff;
border: 1px solid #20c997;
border-radius: 4px;
padding: 8px 16px;
font-size: 14px;
font-weight: 600;
text-align: center;
cursor: pointer;
transition: all 0.3s ease;
}
.btn-teal:hover {
background-color: #1aa085;
color: #fff;
border-color: #1aa085;
transform: translateY(-2px);
}
.btn-teal:active {
background-color: #148d66;
color: #fff;
border-color: #148d66;
transform: translateY(2px);
}
.btn-teal:disabled {
background-color: #e0e0e0;
color: #9e9e9e;
border-color: #bdbdbd;
cursor: not-allowed;
}
.btn-lightblue {
background-color: #17a2b8;
color: #fff;
border: 1px solid #17a2b8;
border-radius: 4px;
padding: 8px 16px;
font-size: 14px;
font-weight: 600;
text-align: center;
cursor: pointer;
transition: all 0.3s ease;
}
.btn-lightblue:hover {
background-color: #138496;
color: #fff;
border-color: #138496;
transform: translateY(-2px);
}
.btn-lightblue:active {
background-color: #117a8b;
color: #fff;
border-color: #117a8b;
transform: translateY(2px);
}
.btn-lightblue:disabled {
background-color: #e0e0e0;
color: #9e9e9e;
border-color: #bdbdbd;
cursor: not-allowed;
}
.btn-gold {
background-color: #ffc107;
color: #fff;
border: 1px solid #ffc107;
border-radius: 4px;
padding: 8px 16px;
font-size: 14px;
font-weight: 600;
text-align: center;
cursor: pointer;
transition: all 0.3s ease;
}
.btn-gold:hover {
background-color: #e0a800;
color: #fff;
border-color: #e0a800;
transform: translateY(-2px);
}
.btn-gold:active {
background-color: #c69500;
color: #fff;
border-color: #c69500;
transform: translateY(2px);
}
.btn-gold:disabled {
background-color: #e0e0e0;
color: #9e9e9e;
border-color: #bdbdbd;
cursor: not-allowed;
}
.btn-teal {
background-color: #20c997;
color: #fff;
border: 1px solid #20c997;
border-radius: 4px;
padding: 8px 16px;
font-size: 14px;
font-weight: 600;
text-align: center;
cursor: pointer;
transition: all 0.3s ease;
}
.btn-teal:hover {
background-color: #17a085;
color: #fff;
border-color: #17a085;
transform: translateY(-2px);
}
.btn-teal:active {
background-color: #138f6a;
color: #fff;
border-color: #138f6a;
transform: translateY(2px);
}
.btn-teal:disabled {
background-color: #e0e0e0;
color: #9e9e9e;
border-color: #bdbdbd;
cursor: not-allowed;
}
.btn-darkred {
background-color: #8b0000;
color: #fff;
border: 1px solid #8b0000;
border-radius: 4px;
padding: 8px 16px;
font-size: 14px;
font-weight: 600;
text-align: center;
cursor: pointer;
transition: all 0.3s ease;
}
.btn-darkred:hover {
background-color: #7a0000;
color: #fff;
border-color: #7a0000;
transform: translateY(-2px);
}
.btn-darkred:active {
background-color: #660000;
color: #fff;
border-color: #660000;
transform: translateY(2px);
}
.btn-darkred:disabled {
background-color: #e0e0e0;
color: #9e9e9e;
border-color: #bdbdbd;
cursor: not-allowed;
}
.btn-darkblue {
background-color: #003366;
color: #fff;
border: 1px solid #003366;
border-radius: 4px;
padding: 8px 16px;
font-size: 14px;
font-weight: 600;
text-align: center;
cursor: pointer;
transition: all 0.3s ease;
}
.btn-darkblue:hover {
background-color: #00264d;
color: #fff;
border-color: #00264d;
transform: translateY(-2px);
}
.btn-darkblue:active {
background-color: #001a33;
color: #fff;
border-color: #001a33;
transform: translateY(2px);
}
.btn-darkblue:disabled {
background-color: #e0e0e0;
color: #9e9e9e;
border-color: #bdbdbd;
cursor: not-allowed;
}
.btn-darkgreen {
background-color: #006400;
color: #fff;
border: 1px solid #006400;
border-radius: 4px;
padding: 8px 16px;
font-size: 14px;
font-weight: 600;
text-align: center;
cursor: pointer;
transition: all 0.3s ease;
}
.btn-darkgreen:hover {
background-color: #004d00;
color: #fff;
border-color: #004d00;
transform: translateY(-2px);
}
.btn-darkgreen:active {
background-color: #003300;
color: #fff;
border-color: #003300;
transform: translateY(2px);
}
.btn-darkgreen:disabled {
background-color: #e0e0e0;
color: #9e9e9e;
border-color: #bdbdbd;
cursor: not-allowed;
}
.btn-brown {
background-color: #8B4513;
color: #fff;
border: 1px solid #8B4513;
border-radius: 4px;
padding: 8px 16px;
font-size: 14px;
font-weight: 600;
text-align: center;
cursor: pointer;
transition: all 0.3s ease;
}
.btn-brown:hover {
background-color: #7a3c0f;
color: #fff;
border-color: #7a3c0f;
transform: translateY(-2px);
}
.btn-brown:active {
background-color: #682a0f;
color: #fff;
border-color: #682a0f;
transform: translateY(2px);
}
.btn-brown:disabled {
background-color: #e0e0e0;
color: #9e9e9e;
border-color: #bdbdbd;
cursor: not-allowed;
}
.btn-aquamarine {
background-color: #7fffd4;
color: #fff;
border: 1px solid #7fffd4;
border-radius: 4px;
padding: 8px 16px;
font-size: 14px;
font-weight: 600;
text-align: center;
cursor: pointer;
transition: all 0.3s ease;
}
.btn-aquamarine:hover {
background-color: #66e0b3;
color: #fff;
border-color: #66e0b3;
transform: translateY(-2px);
}
.btn-aquamarine:active {
background-color: #55c39f;
color: #fff;
border-color: #55c39f;
transform: translateY(2px);
}
.btn-aquamarine:disabled {
background-color: #e0e0e0;
color: #9e9e9e;
border-color: #bdbdbd;
cursor: not-allowed;
}
.btn-fuchsia {
background-color: #d500f9;
color: #fff;
border: 1px solid #d500f9;
border-radius: 4px;
padding: 8px 16px;
font-size: 14px;
font-weight: 600;
text-align: center;
cursor: pointer;
transition: all 0.3s ease;
}
.btn-fuchsia:hover {
background-color: #b400d1;
color: #fff;
border-color: #b400d1;
transform: translateY(-2px);
}
.btn-fuchsia:active {
background-color: #9a00b3;
color: #fff;
border-color: #9a00b3;
transform: translateY(2px);
}
.btn-fuchsia:disabled {
background-color: #e0e0e0;
color: #9e9e9e;
border-color: #bdbdbd;
cursor: not-allowed;
}
.btn-rose-gold {
background-color: #b76e79;
color: #fff;
border: 1px solid #b76e79;
border-radius: 4px;
padding: 8px 16px;
font-size: 14px;
font-weight: 600;
text-align: center;
cursor: pointer;
transition: all 0.3s ease;
}
.btn-rose-gold:hover {
background-color: #a05a66;
color: #fff;
border-color: #a05a66;
transform: translateY(-2px);
}
.btn-rose-gold:active {
background-color: #8a4b58;
color: #fff;
border-color: #8a4b58;
transform: translateY(2px);
}
.btn-rose-gold:disabled {
background-color: #e0e0e0;
color: #9e9e9e;
border-color: #bdbdbd;
cursor: not-allowed;
}

View File

@ -1,5 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="186" height="20" role="img" aria-label="Latest Version: v1.7.2">
<title>Latest Version: v1.7.2</title>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="186" height="20" role="img" aria-label="Latest Version: v1.7.3">
<title>Latest Version: v1.7.3</title>
<linearGradient id="s" x2="0" y2="100%">
<stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
<stop offset="1" stop-opacity=".1"/>
@ -15,7 +15,7 @@
<g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110">
<text aria-hidden="true" x="495" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="700" style="letter-spacing: -5;">Latest Version</text>
<text x="495" y="140" transform="scale(.1)" fill="#fff" textLength="700" style="letter-spacing: -5;">Latest Version</text>
<text aria-hidden="true" x="1405" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="600" style="letter-spacing: -3;">v1.7.2</text>
<text x="1405" y="140" transform="scale(.1)" fill="#fff" textLength="600" style="letter-spacing: -3;">v1.7.2</text>
<text aria-hidden="true" x="1405" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="600" style="letter-spacing: -3;">v1.7.3</text>
<text x="1405" y="140" transform="scale(.1)" fill="#fff" textLength="600" style="letter-spacing: -3;">v1.7.3</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -1,5 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="186" height="20" role="img" aria-label="Current Version: v1.7.2">
<title>Current Version: v1.7.2</title>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="186" height="20" role="img" aria-label="Current Version: v1.7.3">
<title>Current Version: v1.7.3</title>
<linearGradient id="s" x2="0" y2="100%">
<stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
<stop offset="1" stop-opacity=".1"/>
@ -15,7 +15,7 @@
<g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110">
<text aria-hidden="true" x="495" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="700" style="letter-spacing: -5;">Current Version</text>
<text x="495" y="140" transform="scale(.1)" fill="#fff" textLength="700" style="letter-spacing: -5;">Current Version</text>
<text aria-hidden="true" x="1405" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="600" style="letter-spacing: -3;">v1.7.2</text>
<text x="1405" y="140" transform="scale(.1)" fill="#fff" textLength="600" style="letter-spacing: -3;">v1.7.2</text>
<text aria-hidden="true" x="1405" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="600" style="letter-spacing: -3;">v1.7.3</text>
<text x="1405" y="140" transform="scale(.1)" fill="#fff" textLength="600" style="letter-spacing: -3;">v1.7.3</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -21,6 +21,8 @@
--bs-check-bg: #0eaf3e;
--bs-label-bg: #0eaf3e;
--bs-line-bg: #f515f9;
--bs-disabled-bg: #23407e;
--bs-radius-bg: #24f086;
--bs-primary-border-subtle: #1815d1;
--bs-tertiary: #46e1ec;
@ -65,10 +67,10 @@
h5 { color: var(--bs-heading-5) !important; }
h6 { color: var(--bs-heading-6) !important; }
input::placeholder { color: #ffffff !important; }
input::placeholder { color: var(--log-text-color) !important; }
.table, .form-control, .card, button, label, li, td, th, blockquote, q, code, pre {
background-color: transparent;
color: #ffffff;
color: var(--log-text-color);
}
input::placeholder {
@ -76,6 +78,11 @@
font-weight: bold;
}
input.form-control:disabled {
background-color: var(--bs-disabled-bg) !important;
}
#lineColumnDisplay, #charCountDisplay {
color: var(--bs-line-bg) !important;
}
@ -109,12 +116,12 @@
}
.close {
color: white !important;
color: var(--log-text-color) !important;
}
.close:hover,
.close:focus {
color: white !important;
color: var(--log-text-color) !important;
text-decoration: none;
}
@ -137,14 +144,14 @@
.form-select {
background-color: var(--bs-form-select);
color: white !important;
color: var(--bs-radius-bg) !important;
border: 1px solid gray;
border-radius: 5px;
}
.form-select option {
background-color: var(--bs-form-select);
color: white !important;
color: var(--bs-radius-bg) !important;
}
.form-control {
@ -347,7 +354,7 @@
.container-sm.container-bg.callout a::after { content: ''; position: absolute; bottom: 0; left: 0; width: 100%; height: 2px; background-color: var(--bs-primary); transform: scaleX(0); transition: transform var(--bs-transition-speed); }
.container-sm.container-bg.callout a:hover, .container-sm.container-bg.callout a:focus, .container-sm.container-bg.callout a.active { color: var(--bs-secondary); } .container-sm.container-bg.callout a:hover::after, .container-sm.container-bg.callout a:focus::after, .container-sm.container-bg.callout a.active::after { transform: scaleX(1); }
.royal-style { font-family: 'Cinzel Decorative', cursive; font-weight: 900; font-size: 80px; color: var(--bs-primary); text-shadow: 2px 2px 4px rgba(142, 68, 173, 0.7); letter-spacing: 4px; text-align: center; margin-top: 20px; }
.royal-style { font-family: 'Cinzel Decorative', cursive; font-weight: 900; font-size: 80px; letter-spacing: 4px; text-align: center; margin-top: 20px; }
.royal-style:hover { transform: skew(-5deg); }
@media (max-width: 991.98px) { .container-sm.container-bg.callout { flex-direction: column; align-items: center; } .container-sm.container-bg.callout a { margin: 0.5rem 0; } }
h1 { color: var(--bs-heading-1); font-size: 2.5rem; }
@ -361,7 +368,7 @@
.text-3d:hover { transform: rotateY(15deg) rotateX(15deg); text-shadow: 3px 3px 1px rgba(0, 0, 0, 0.3), 4px 4px 2px rgba(0, 0, 0, 0.25), 5px 5px 3px rgba(0, 0, 0, 0.2); }
.card { border-radius: 12px; overflow: hidden; box-shadow: var(--bs-shadow-medium); }
.card-header { background-color: var(--bs-primary); color: #fff; }
.royal-style { font-family: 'Cinzel Decorative', cursive; font-weight: 900; font-size: 80px; color: var(--bs-primary); text-shadow: 2px 2px 4px rgba(142, 68, 173, 0.7), 0 0 20px rgba(142, 68, 173, 0.3); letter-spacing: 4px; text-align: center; margin-top: 20px; transition: all var(-- bs-transition-speed); }
.royal-style { font-family: 'Cinzel Decorative', cursive; font-weight: 900; font-size: 80px; letter-spacing: 4px; text-align: center; margin-top: 20px; transition: all var(-- bs-transition-speed); }
.royal-style:hover { transform: skew(-5deg); text-shadow: 3px 3px 6px rgba(0,0,0,0.2); }
@media (max-width: 991.98px) {
.container-sm.container-bg.callout {
@ -449,10 +456,6 @@
font-family: 'Cinzel Decorative', cursive;
font-weight: 900;
font-size: 80px;
color: var(--bs-primary);
text-shadow:
2px 2px 4px rgba(142, 68, 173, 0.7),
0 0 20px rgba(142, 68, 173, 0.3);
letter-spacing: 4px;
text-align: center;
margin-top: 20px;

View File

@ -173,8 +173,6 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET' && isset($_GET['downloadFile'], $_GET['
?>
<?php
session_start();
$subscriptionPath = '/etc/neko/proxy_provider/';
$subscriptionFile = $subscriptionPath . 'subscriptions.json';
$notificationMessage = "";
@ -208,51 +206,77 @@ if (!$subscriptions) {
if (isset($_POST['update'])) {
$index = intval($_POST['index']);
$url = $_POST['subscription_url'] ?? '';
$customFileName = $_POST['custom_file_name'] ?? "subscription_" . ($index + 1) . ".yaml";
$url = trim($_POST['subscription_url'] ?? '');
$customFileName = trim($_POST['custom_file_name'] ?? "subscription_" . ($index + 1) . ".yaml");
$subscriptions[$index]['url'] = $url;
$subscriptions[$index]['file_name'] = $customFileName;
if (!empty($url)) {
$tempPath = $subscriptionPath . $customFileName . ".temp";
$finalPath = $subscriptionPath . $customFileName;
$command = "wget -q --show-progress -O {$finalPath} {$url}";
$command = "curl -s -L -o {$tempPath} {$url}";
exec($command . ' 2>&1', $output, $return_var);
if ($return_var !== 0) {
$command = "curl -s -o {$finalPath} {$url}";
$command = "wget -q --show-progress -O {$tempPath} {$url}";
exec($command . ' 2>&1', $output, $return_var);
}
if ($return_var === 0) {
$_SESSION['update_logs'] = array();
storeUpdateLog('<strong>✅ 更新成功:</strong> 订阅 ' . htmlspecialchars($url) . ' 已下载并保存为 ' . htmlspecialchars($customFileName));
$_SESSION['update_logs'] = [];
storeUpdateLog("✅ 订阅 " . htmlspecialchars($url) . " 已下载并保存到临时文件: " . htmlspecialchars($tempPath));
$fileContent = file_get_contents($finalPath);
$decodedContent = base64_decode($fileContent);
$fileContent = file_get_contents($tempPath);
if ($decodedContent === false) {
storeUpdateLog("⚠️ Base64 解码失败,请检查下载的文件内容是否有效!");
$notificationMessage = "Base64 解码失败";
} else {
$clashFile = $subscriptionPath . $customFileName;
file_put_contents($clashFile, "# Clash Meta Config\n\n" . $decodedContent);
storeUpdateLog("📂 配置已解码并保存到: " . htmlspecialchars($clashFile));
if (base64_encode(base64_decode($fileContent, true)) === $fileContent) {
$decodedContent = base64_decode($fileContent);
if ($decodedContent !== false && strlen($decodedContent) > 0) {
file_put_contents($finalPath, "# Clash Meta Config\n\n" . $decodedContent);
storeUpdateLog("📂 Base64 解码成功,配置已保存到: " . htmlspecialchars($finalPath));
unlink($tempPath);
$notificationMessage = '更新成功';
$updateCompleted = true;
} else {
storeUpdateLog("⚠️ Base64 解码失败,请检查订阅链接内容!");
unlink($tempPath);
$notificationMessage = '更新失败';
}
}
elseif (substr($fileContent, 0, 2) === "\x1f\x8b") {
$decompressedContent = gzdecode($fileContent);
if ($decompressedContent !== false) {
file_put_contents($finalPath, "# Clash Meta Config\n\n" . $decompressedContent);
storeUpdateLog("📂 Gzip 解压成功,配置已保存到: " . htmlspecialchars($finalPath));
unlink($tempPath);
$notificationMessage = '更新成功';
$updateCompleted = true;
} else {
storeUpdateLog("⚠️ Gzip 解压失败,请检查订阅链接格式!");
unlink($tempPath);
$notificationMessage = '更新失败';
}
}
else {
rename($tempPath, $finalPath);
storeUpdateLog("✅ 订阅内容已成功下载,无需解码");
$notificationMessage = '更新成功';
$updateCompleted = true;
}
} else {
storeUpdateLog("❌ 配置更新失败!错误信息: " . implode("\n", $output));
storeUpdateLog("❌ 订阅更新失败!错误信息: " . implode("\n", $output));
unlink($tempPath);
$notificationMessage = '更新失败';
}
} else {
storeUpdateLog("⚠️ 订阅链接为空!");
storeUpdateLog("⚠️ " . ($index + 1) . "订阅链接为空!");
$notificationMessage = '更新失败';
}
file_put_contents($subscriptionFile, json_encode($subscriptions));
}
?>
<?php
@ -266,59 +290,82 @@ if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$shellScriptContent = <<<EOL
#!/bin/bash
LOG_FILE="$LOG_FILE"
JSON_FILE="$JSON_FILE"
SAVE_DIR="$SAVE_DIR"
LOG_FILE="/etc/neko/tmp/log.txt"
JSON_FILE="/etc/neko/proxy_provider/subscriptions.json"
SAVE_DIR="/etc/neko/proxy_provider"
log() {
echo "$(date '+[ %H:%M:%S ]') \$1" >> "\$LOG_FILE"
}
log "开始处理订阅更新任务..."
if [ ! -f "\$JSON_FILE" ]; then
echo "\$(date '+[ %H:%M:%S ]') 错误: JSON 文件不存在: \$JSON_FILE" >> "\$LOG_FILE"
log " 错误: JSON 文件不存在: \$JSON_FILE"
exit 1
fi
echo "\$(date '+[ %H:%M:%S ]') 开始处理订阅链接..." >> "\$LOG_FILE"
jq -c '.[]' "\$JSON_FILE" | while read -r ITEM; do
URL=\$(echo "\$ITEM" | jq -r '.url')
FILE_NAME=\$(echo "\$ITEM" | jq -r '.file_name')
if [ -z "\$URL" ] || [ "\$URL" == "null" ]; then
echo "\$(date '+[ %H:%M:%S ]') 跳过空的 URL,文件名: \$FILE_NAME" >> "\$LOG_FILE"
log "⚠️ 跳过空的订阅链接,文件名: \$FILE_NAME"
continue
fi
if [ -z "\$FILE_NAME" ] || [ "\$FILE_NAME" == "null" ]; then
echo "\$(date '+[ %H:%M:%S ]') 错误: 文件名为空,跳过此链接: \$URL" >> "\$LOG_FILE"
log " 错误: 文件名为空,跳过此链接: \$URL"
continue
fi
SAVE_PATH="\$SAVE_DIR/\$FILE_NAME"
TEMP_PATH="\$SAVE_PATH.temp"
echo "\$(date '+[ %H:%M:%S ]') 正在下载链接: \$URL 到临时文件: \$TEMP_PATH" >> "\$LOG_FILE"
wget -q -O "\$TEMP_PATH" "\$URL"
log "🔄 正在下载: \$URL 到临时文件: \$TEMP_PATH"
curl -s -L -o "\$TEMP_PATH" "\$URL"
if [ \$? -ne 0 ]; then
wget -q -O "\$TEMP_PATH" "\$URL"
fi
if [ \$? -eq 0 ]; then
echo "\$(date '+[ %H:%M:%S ]') 文件下载成功: \$TEMP_PATH" >> "\$LOG_FILE"
base64 -d "\$TEMP_PATH" > "\$SAVE_PATH"
log "✅ 文件下载成功: \$TEMP_PATH"
if [ \$? -eq 0 ]; then
echo "\$(date '+[ %H:%M:%S ]') 文件解码成功: \$SAVE_PATH" >> "\$LOG_FILE"
if base64 -d "\$TEMP_PATH" > /dev/null 2>&1; then
base64 -d "\$TEMP_PATH" > "\$SAVE_PATH"
if [ \$? -eq 0 ]; then
log "📂 Base64 解码成功,配置已保存: \$SAVE_PATH"
rm -f "\$TEMP_PATH"
else
log "⚠️ Base64 解码失败: \$SAVE_PATH"
rm -f "\$TEMP_PATH"
fi
elif file "\$TEMP_PATH" | grep -q "gzip compressed"; then
gunzip -c "\$TEMP_PATH" > "\$SAVE_PATH"
if [ \$? -eq 0 ]; then
log "📂 Gzip 解压成功,配置已保存: \$SAVE_PATH"
rm -f "\$TEMP_PATH"
else
log "⚠️ Gzip 解压失败: \$SAVE_PATH"
rm -f "\$TEMP_PATH"
fi
else
echo "\$(date '+[ %H:%M:%S ]') 错误: 文件解码失败: \$SAVE_PATH" >> "\$LOG_FILE"
mv "\$TEMP_PATH" "\$SAVE_PATH"
log "✅ 订阅内容已成功下载,无需解码"
fi
rm -f "\$TEMP_PATH"
else
echo "\$(date '+[ %H:%M:%S ]') 错误: 文件下载失败: \$URL" >> "\$LOG_FILE"
log "❌ 订阅更新失败: \$URL"
rm -f "\$TEMP_PATH"
fi
done
echo "\$(date '+[ %H:%M:%S ]') 所有订阅链接处理完成。" >> "\$LOG_FILE"
log "🚀 所有订阅链接更新完成!"
EOL;
if (file_put_contents($shellScriptPath, $shellScriptContent) !== false) {
chmod($shellScriptPath, 0755);
chmod($shellScriptPath, 0755);
echo "<div class='alert alert-success'>Shell 脚本已创建成功!路径: $shellScriptPath</div>";
} else {
echo "<div class='alert alert-danger'>无法创建 Shell 脚本,请检查权限。</div>";
@ -1224,11 +1271,11 @@ function initializeAceEditor() {
<button type="submit" name="createShellScript" value="true" class="btn btn-success mx-2">
<i class="bi bi-terminal"></i> 生成更新脚本
</button>
<button type="button" class="btn btn-warning mx-2" data-bs-toggle="modal" data-bs-target="#downloadModal">
<button type="button" class="btn btn-cyan mx-2" data-bs-toggle="modal" data-bs-target="#downloadModal">
<i class="bi bi-download"></i> 更新数据库
</button>
<td>
<a class="btn btn-pink btn-sm text-white mx-2" target="_blank" href="./filekit.php" style="font-size: 14px; font-weight: bold;">
<a class="btn btn-orange btn-sm text-white mx-2" target="_blank" href="./filekit.php" style="font-size: 14px; font-weight: bold;">
<i class="bi bi-file-earmark-text"></i> 打开文件助手
</a>
</td>

View File

@ -627,115 +627,123 @@ $razordVersion = getRazordVersion();
<div class="modal-body">
<form method="POST" action="theme.php" id="themeForm" enctype="multipart/form-data">
<div class="row">
<div class="col-md-6 mb-3">
<div class="col-md-4 mb-3">
<label for="primaryColor" class="form-label">导航栏文本色</label>
<input type="color" class="form-control" name="primaryColor" id="primaryColor" value="#0ceda2">
</div>
<div class="col-md-6 mb-3">
<div class="col-md-4 mb-3">
<label for="secondaryColor" class="form-label">导航栏悬停文本色</label>
<input type="color" class="form-control" name="secondaryColor" id="secondaryColor" value="#00ffff">
</div>
<div class="col-md-6 mb-3">
<div class="col-md-4 mb-3">
<label for="bodyBgColor" class="form-label">主背景色</label>
<input type="color" class="form-control" name="bodyBgColor" id="bodyBgColor" value="#23407e">
</div>
<div class="col-md-6 mb-3">
<div class="col-md-4 mb-3">
<label for="infoBgSubtle" class="form-label">信息背景色</label>
<input type="color" class="form-control" name="infoBgSubtle" id="infoBgSubtle" value="#23407e">
</div>
<div class="col-md-6 mb-3">
<div class="col-md-4 mb-3">
<label for="backgroundColor" class="form-label">表格背景色</label>
<input type="color" class="form-control" name="backgroundColor" id="backgroundColor" value="#20cdd9">
</div>
<div class="col-md-6 mb-3">
<div class="col-md-4 mb-3">
<label for="primaryBorderSubtle" class="form-label">表格文本色</label>
<input type="color" class="form-control" name="primaryBorderSubtle" id="primaryBorderSubtle" value="#1815d1">
</div>
<div class="col-md-6 mb-3">
<div class="col-md-4 mb-3">
<label for="checkColor" class="form-label">主标题文本色 1</label>
<input type="color" class="form-control" name="checkColor" id="checkColor" value="#0eaf3e">
</div>
<div class="col-md-6 mb-3">
<div class="col-md-4 mb-3">
<label for="labelColor" class="form-label">主标题文本色 2</label>
<input type="color" class="form-control" name="labelColor" id="labelColor" value="#0eaf3e">
</div>
<div class="col-md-6 mb-3">
<div class="col-md-4 mb-3">
<label for="lineColor" class="form-label">行数文本色</label>
<input type="color" class="form-control" name="lineColor" id="lineColor" value="#f515f9">
</div>
<div class="col-md-6 mb-3">
<div class="col-md-4 mb-3">
<label for="controlColor" class="form-label">输入框文本色 1</label>
<input type="color" class="form-control" name="controlColor" id="controlColor" value="#0eaf3e">
</div>
<div class="col-md-6 mb-3">
<div class="col-md-4 mb-3">
<label for="placeholderColor" class="form-label">输入框文本色 2</label>
<input type="color" class="form-control" name="placeholderColor" id="placeholderColor" value="#f82af2">
</div>
<div class="col-md-6 mb-3">
<div class="col-md-4 mb-3">
<label for="disabledColor" class="form-label">显示框背景色</label>
<input type="color" class="form-control" name="disabledColor" id="disabledColor" value="#23407e">
</div>
<div class="col-md-4 mb-3">
<label for="logTextColor" class="form-label">日志文本色</label>
<input type="color" class="form-control" name="logTextColor" id="logTextColor" value="#f8f9fa">
</div>
<div class="col-md-6 mb-3">
<div class="col-md-4 mb-3">
<label for="selectColor" class="form-label">主边框背景色</label>
<input type="color" class="form-control" name="selectColor" id="selectColor" value="#23407e">
</div>
<div class="col-md-6 mb-3">
<div class="col-md-4 mb-3">
<label for="radiusColor" class="form-label">主边框文本色</label>
<input type="color" class="form-control" name="radiusColor" id="radiusColor" value="#24f086">
</div>
<div class="col-md-4 mb-3">
<label for="bodyColor" class="form-label">表格文本色 1</label>
<input type="color" class="form-control" name="bodyColor" id="bodyColor" value="#04f153">
</div>
<div class="col-md-6 mb-3">
<div class="col-md-4 mb-3">
<label for="tertiaryColor" class="form-label">表格文本色 2</label>
<input type="color" class="form-control" name="tertiaryColor" id="tertiaryColor" value="#46e1ec">
</div>
<div class="col-md-6 mb-3">
<div class="col-md-4 mb-3">
<label for="tertiaryRgbColor" class="form-label">表格文本色 3</label>
<input type="color" class="form-control" name="tertiaryRgbColor" id="tertiaryRgbColor" value="#1e90ff">
</div>
<div class="col-md-6 mb-3">
<div class="col-md-4 mb-3">
<label for="outlineColor" class="form-label">按键色(青色)</label>
<input type="color" class="form-control" name="outlineColor" id="outlineColor" value="#0dcaf0">
</div>
<div class="col-md-6 mb-3">
<div class="col-md-4 mb-3">
<label for="successColor" class="form-label">按键色(绿色)</label>
<input type="color" class="form-control" name="successColor" id="successColor" value="#28a745">
</div>
<div class="col-md-6 mb-3">
<div class="col-md-4 mb-3">
<label for="infoColor" class="form-label">按键色(蓝色)</label>
<input type="color" class="form-control" name="infoColor" id="infoColor" value="#0ca2ed">
</div>
<div class="col-md-6 mb-3">
<div class="col-md-4 mb-3">
<label for="warningColor" class="form-label">按键色(黄色)</label>
<input type="color" class="form-control" name="warningColor" id="warningColor" value="#ffc107">
</div>
<div class="col-md-6 mb-3">
<div class="col-md-4 mb-3">
<label for="pinkColor" class="form-label">按键色(粉红色)</label>
<input type="color" class="form-control" name="pinkColor" id="pinkColor" value="#f82af2">
</div>
<div class="col-md-6 mb-3">
<div class="col-md-4 mb-3">
<label for="dangerColor" class="form-label">按键色(红色)</label>
<input type="color" class="form-control" name="dangerColor" id="dangerColor" value="#dc3545">
</div>
<div class="col-md-6 mb-3">
<div class="col-md-4 mb-3">
<label for="heading1Color" class="form-label">标题色 1</label>
<input type="color" class="form-control" name="heading1Color" id="heading1Color" value="#21e4f2">
</div>
<div class="col-md-6 mb-3">
<div class="col-md-4 mb-3">
<label for="heading2Color" class="form-label">标题色 2</label>
<input type="color" class="form-control" name="heading2Color" id="heading2Color" value="#65f1fb">
</div>
<div class="col-md-6 mb-3">
<div class="col-md-4 mb-3">
<label for="heading3Color" class="form-label">标题色 3</label>
<input type="color" class="form-control" name="heading3Color" id="heading3Color" value="#ffcc00">
</div>
<div class="col-md-6 mb-3">
<div class="col-md-4 mb-3">
<label for="heading4Color" class="form-label">标题色 4</label>
<input type="color" class="form-control" name="heading4Color" id="heading4Color" value="#00fbff">
</div>
<div class="col-md-6 mb-3">
<div class="col-md-4 mb-3">
<label for="heading5Color" class="form-label">标题色 5</label>
<input type="color" class="form-control" name="heading5Color" id="heading5Color" value="#ba13f6">
</div>
<div class="col-md-6 mb-3">
<div class="col-md-4 mb-3">
<label for="heading6Color" class="form-label">标题色 6</label>
<input type="color" class="form-control" name="heading6Color" id="heading6Color" value="#00ffff">
</div>
@ -980,32 +988,33 @@ function formatSize($size) {
document.getElementById('primaryColor').value = '#0ceda2';
document.getElementById('secondaryColor').value = '#00ffff';
document.getElementById('bodyBgColor').value = '#23407e';
document.getElementById('bodyColor').value = '#04f153';
document.getElementById('infoBgSubtle').value = '#23407e';
document.getElementById('selectColor').value = '#23407e';
document.getElementById('tertiaryColor').value = '#46e1ec';
document.getElementById('controlColor').value = '#0eaf3e';
document.getElementById('backgroundColor').value = '#20cdd9';
document.getElementById('primaryBorderSubtle').value = '#1815d1';
document.getElementById('checkColor').value = '#0eaf3e';
document.getElementById('labelColor').value = '#0eaf3e';
document.getElementById('lineColor').value = '#f515f9';
document.getElementById('tertiaryRgbColor').value = '#1e90ff';
document.getElementById('heading1Color').value = '#21e4f2';
document.getElementById('heading2Color').value = '#65f1fb';
document.getElementById('heading3Color').value = '#ffcc00';
document.getElementById('heading4Color').value = '#00fbff';
document.getElementById('heading5Color').value = '#ba13f6';
document.getElementById('heading6Color').value = '#00ffff';
document.getElementById('primaryBorderSubtle').value = '#1815d1';
document.getElementById('backgroundColor').value = '#20cdd9';
document.getElementById('controlColor').value = '#0eaf3e';
document.getElementById('placeholderColor').value = '#f82af2';
document.getElementById('disabledColor').value = '#23407e';
document.getElementById('logTextColor').value = '#f8f9fa';
document.getElementById('selectColor').value = '#23407e';
document.getElementById('radiusColor').value = '#14b863';
document.getElementById('bodyColor').value = '#04f153';
document.getElementById('tertiaryColor').value = '#46e1ec';
document.getElementById('outlineColor').value = '#0dcaf0';
document.getElementById('successColor').value = '#28a745';
document.getElementById('infoColor').value = '#0ca2ed';
document.getElementById('warningColor').value = '#ffc107';
document.getElementById('pinkColor').value = '#f82af2';
document.getElementById('dangerColor').value = '#dc3545';
document.getElementById('tertiaryRgbColor').value = '#1e90ff';
document.getElementById('heading1Color').value = '#21e4f2';
document.getElementById('heading2Color').value = '#65f1fb';
document.getElementById('heading3Color').value = '#ffcc00';
document.getElementById('heading4Color').value = '#00fbff';
document.getElementById('heading5Color').value = '#ba13f6';
document.getElementById('heading6Color').value = '#00ffff';
localStorage.clear();
});
@ -1015,31 +1024,32 @@ function formatSize($size) {
secondaryColor: document.getElementById('secondaryColor').value,
bodyBgColor: document.getElementById('bodyBgColor').value,
infoBgSubtle: document.getElementById('infoBgSubtle').value,
selectColor: document.getElementById('selectColor').value,
bodyColor: document.getElementById('bodyColor').value,
tertiaryColor: document.getElementById('tertiaryColor').value,
tertiaryRgbColor: document.getElementById('tertiaryRgbColor').value,
controlColor: document.getElementById('controlColor').value,
backgroundColor: document.getElementById('backgroundColor').value,
primaryBorderSubtle: document.getElementById('primaryBorderSubtle').value,
checkColor: document.getElementById('checkColor').value,
labelColor: document.getElementById('labelColor').value,
lineColor: document.getElementById('lineColor').value,
heading1Color: document.getElementById('heading1Color').value,
heading2Color: document.getElementById('heading2Color').value,
heading3Color: document.getElementById('heading3Color').value,
heading4Color: document.getElementById('heading4Color').value,
heading5Color: document.getElementById('heading5Color').value,
heading6Color: document.getElementById('heading6Color').value,
controlColor: document.getElementById('controlColor').value,
placeholderColor: document.getElementById('placeholderColor').value,
disabledColor: document.getElementById('disabledColor').value,
logTextColor: document.getElementById('logTextColor').value,
selectColor: document.getElementById('selectColor').value,
radiusColor: document.getElementById('radiusColor').value,
bodyColor: document.getElementById('bodyColor').value,
tertiaryColor: document.getElementById('tertiaryColor').value,
tertiaryRgbColor: document.getElementById('tertiaryRgbColor').value,
outlineColor: document.getElementById('outlineColor').value,
successColor: document.getElementById('successColor').value,
infoColor: document.getElementById('infoColor').value,
warningColor: document.getElementById('warningColor').value,
pinkColor: document.getElementById('pinkColor').value,
dangerColor: document.getElementById('dangerColor').value,
primaryBorderSubtle: document.getElementById('primaryBorderSubtle').value,
backgroundColor: document.getElementById('backgroundColor').value,
placeholderColor: document.getElementById('placeholderColor').value,
logTextColor: document.getElementById('logTextColor').value,
heading1Color: document.getElementById('heading1Color').value,
heading2Color: document.getElementById('heading2Color').value,
heading3Color: document.getElementById('heading3Color').value,
heading4Color: document.getElementById('heading4Color').value,
heading5Color: document.getElementById('heading5Color').value,
heading6Color: document.getElementById('heading6Color').value,
useBackgroundImage: document.getElementById('useBackgroundImage').checked,
backgroundImage: document.getElementById('backgroundImage').value
};
@ -1062,30 +1072,32 @@ function formatSize($size) {
document.getElementById('secondaryColor').value = settings.secondaryColor;
document.getElementById('bodyBgColor').value = settings.bodyBgColor;
document.getElementById('infoBgSubtle').value = settings.infoBgSubtle;
document.getElementById('selectColor').value = settings.selectColor;
document.getElementById('bodyColor').value = settings.bodyColor;
document.getElementById('tertiaryColor').value = settings.tertiaryColor;
document.getElementById('tertiaryRgbColor').value = settings.tertiaryRgbColor;
document.getElementById('controlColor').value = settings.controlColor;
document.getElementById('backgroundColor').value = settings.backgroundColor;
document.getElementById('primaryBorderSubtle').value = settings.primaryBorderSubtle;
document.getElementById('checkColor').value = settings.checkColor;
document.getElementById('labelColor').value = settings.labelColor;
document.getElementById('lineColor').value = settings.lineColor;
document.getElementById('heading1Color').value = settings.heading1Color;
document.getElementById('heading2Color').value = settings.heading2Color;
document.getElementById('heading3Color').value = settings.heading3Color;
document.getElementById('heading4Color').value = settings.heading4Color;
document.getElementById('heading5Color').value = settings.heading5Color;
document.getElementById('heading6Color').value = settings.heading6Color;
document.getElementById('controlColor').value = settings.controlColor;
document.getElementById('placeholderColor').value = settings.placeholderColor;
document.getElementById('disabledColor').value = settings.disabledColor;
document.getElementById('logTextColor').value = settings.logTextColor;
document.getElementById('selectColor').value = settings.selectColor;
document.getElementById('radiusColor').value = settings.radiusColor;
document.getElementById('bodyColor').value = settings.bodyColor;
document.getElementById('tertiaryColor').value = settings.tertiaryColor;
document.getElementById('tertiaryRgbColor').value = settings.tertiaryRgbColor;
document.getElementById('outlineColor').value = settings.outlineColor;
document.getElementById('successColor').value = settings.successColor;
document.getElementById('infoColor').value = settings.infoColor;
document.getElementById('warningColor').value = settings.warningColor;
document.getElementById('pinkColor').value = settings.pinkColor;
document.getElementById('dangerColor').value = settings.dangerColor;
document.getElementById('primaryBorderSubtle').value = settings.primaryBorderSubtle;
document.getElementById('backgroundColor').value = settings.backgroundColor;
document.getElementById('placeholderColor').value = settings.placeholderColor;
document.getElementById('logTextColor').value = settings.logTextColor;
document.getElementById('heading1Color').value = settings.heading1Color;
document.getElementById('heading2Color').value = settings.heading2Color;
document.getElementById('heading3Color').value = settings.heading3Color;
document.getElementById('heading4Color').value = settings.heading4Color;
document.getElementById('heading5Color').value = settings.heading5Color;
document.getElementById('heading6Color').value = settings.heading6Color;
document.getElementById('useBackgroundImage').checked = settings.useBackgroundImage;
const backgroundImageContainer = document.getElementById('backgroundImageContainer');
@ -1096,31 +1108,32 @@ function formatSize($size) {
localStorage.setItem('secondaryColor', settings.secondaryColor);
localStorage.setItem('bodyBgColor', settings.bodyBgColor);
localStorage.setItem('infoBgSubtle', settings.infoBgSubtle);
localStorage.setItem('selectColor', settings.selectColor);
localStorage.setItem('bodyColor', settings.bodyColor);
localStorage.setItem('tertiaryColor', settings.tertiaryColor);
localStorage.setItem('tertiaryRgbColor', settings.tertiaryRgbColor);
localStorage.setItem('controlColor', settings.controlColor);
localStorage.setItem('backgroundColor', settings.backgroundColor);
localStorage.setItem('primaryBorderSubtle', settings.primaryBorderSubtle);
localStorage.setItem('checkColor', settings.checkColor);
localStorage.setItem('labelColor', settings.labelColor);
localStorage.setItem('lineColor', settings.lineColor);
localStorage.setItem('heading1Color', settings.heading1Color);
localStorage.setItem('heading2Color', settings.heading2Color);
localStorage.setItem('heading3Color', settings.heading3Color);
localStorage.setItem('heading4Color', settings.heading4Color);
localStorage.setItem('heading5Color', settings.heading5Color);
localStorage.setItem('heading6Color', settings.heading6Color);
localStorage.setItem('controlColor', settings.controlColor);
localStorage.setItem('placeholderColor', settings.placeholderColor);
localStorage.setItem('disabledColor', settings.disabledColor);
localStorage.setItem('logTextColor', settings.logTextColor);
localStorage.setItem('selectColor', settings.selectColor);
localStorage.setItem('radiusColor', settings.radiusColor);
localStorage.setItem('bodyColor', settings.bodyColor);
localStorage.setItem('tertiaryColor', settings.tertiaryColor);
localStorage.setItem('tertiaryRgbColor', settings.tertiaryRgbColor);
localStorage.setItem('outlineColor', settings.outlineColor);
localStorage.setItem('successColor', settings.successColor);
localStorage.setItem('infoColor', settings.infoColor);
localStorage.setItem('warningColor', settings.warningColor);
localStorage.setItem('pinkColor', settings.pinkColor);
localStorage.setItem('dangerColor', settings.dangerColor);
localStorage.setItem('primaryBorderSubtle', settings.primaryBorderSubtle);
localStorage.setItem('backgroundColor', settings.backgroundColor);
localStorage.setItem('placeholderColor', settings.placeholderColor);
localStorage.setItem('logTextColor', settings.logTextColor);
localStorage.setItem('heading1Color', settings.heading1Color);
localStorage.setItem('heading2Color', settings.heading2Color);
localStorage.setItem('heading3Color', settings.heading3Color);
localStorage.setItem('heading4Color', settings.heading4Color);
localStorage.setItem('heading5Color', settings.heading5Color);
localStorage.setItem('heading6Color', settings.heading6Color);
localStorage.setItem('useBackgroundImage', settings.useBackgroundImage);
localStorage.setItem('backgroundImage', settings.backgroundImage);
};
@ -1499,7 +1512,7 @@ function checkVersion(outputId, updateFiles, currentVersions) {
Promise.all(requests).then(() => {
modalContent.innerHTML = `
<table class="table table-striped table-bordered">
<table class="table table-striped table-bordered">
<thead>
<tr>
<th class="text-center">组件名称</th>

View File

@ -28,9 +28,11 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$checkColor = $_POST['checkColor'] ?? '#0eaf3e';
$labelColor = $_POST['labelColor'] ?? '#0eaf3e';
$lineColor = $_POST['lineColor'] ?? '#f515f9';
$disabledColor = $_POST['disabledColor'] ?? '#23407e';
$radiusColor = $_POST['radiusColor'] ?? '#14b863';
$themeName = isset($_POST['themeName']) ? $_POST['themeName'] : 'transparent';
$themeName = preg_replace('/[\p{Han}]/u', '', $themeName);
$themeName = preg_replace('/[^a-zA-Z0-9_\-一-龯]/u', '', $themeName);
if (empty($themeName)) {
$themeName = 'transparent';
}
@ -73,6 +75,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
--bs-check-bg: $checkColor;
--bs-label-bg: $labelColor;
--bs-line-bg: $lineColor;
--bs-disabled-bg: $disabledColor;
--bs-radius-bg: $radiusColor;
--bs-primary-border-subtle: $primaryBorderSubtle;
--bs-tertiary: $tertiaryColor;
@ -128,6 +132,11 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
font-weight: bold;
}
input.form-control:disabled {
background-color: var(--bs-disabled-bg) !important;
}
#lineColumnDisplay, #charCountDisplay {
color: var(--bs-line-bg) !important;
}
@ -185,14 +194,14 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
.form-select {
background-color: var(--bs-form-select);
color: var(--bs-controlr-bg) !important;
color: var(--bs-radius-bg) !important;
border: 1px solid gray;
border-radius: 5px;
}
.form-select option {
background-color: var(--bs-form-select);
color: var(--bs-controlr-bg) !important;
color: var(--bs-radius-bg) !important;
}
.form-control {

View File

@ -1 +1 @@
V1.7.2-cn
V1.7.3-cn