update 2025-02-04 14:16:01

This commit is contained in:
kenzok8 2025-02-04 14:16:01 +08:00
parent 1aa62b3f85
commit 6dbf0c5a5e
10 changed files with 2271 additions and 1346 deletions

View File

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

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.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.6">
<title>Latest Version: v1.7.5</title> <title>Latest Version: v1.7.6</title>
<linearGradient id="s" x2="0" y2="100%"> <linearGradient id="s" x2="0" y2="100%">
<stop offset="0" stop-color="#bbb" stop-opacity=".1"/> <stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
<stop offset="1" 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"> <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 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 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.5</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.6</text>
<text x="1405" y="140" transform="scale(.1)" fill="#fff" textLength="600" style="letter-spacing: -3;">v1.7.5</text> <text x="1405" y="140" transform="scale(.1)" fill="#fff" textLength="600" style="letter-spacing: -3;">v1.7.6</text>
</g> </g>
</svg> </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.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.6">
<title>Current Version: v1.7.5</title> <title>Current Version: v1.7.6</title>
<linearGradient id="s" x2="0" y2="100%"> <linearGradient id="s" x2="0" y2="100%">
<stop offset="0" stop-color="#bbb" stop-opacity=".1"/> <stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
<stop offset="1" 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"> <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 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 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.5</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.6</text>
<text x="1405" y="140" transform="scale(.1)" fill="#fff" textLength="600" style="letter-spacing: -3;">v1.7.5</text> <text x="1405" y="140" transform="scale(.1)" fill="#fff" textLength="600" style="letter-spacing: -3;">v1.7.6</text>
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -119,12 +119,6 @@
color: var(--bs-heading-5) !important; color: var(--bs-heading-5) !important;
} }
.container-sm {
width: var(--container-width);
max-width: 100%;
margin: 0 auto;
}
.form-label { .form-label {
color: var(--bs-check-bg) color: var(--bs-check-bg)
} }

View File

@ -824,6 +824,15 @@ $(document).ready(function() {
margin-bottom: 20px; margin-bottom: 20px;
} }
.custom-icon {
width: 20px !important;
height: 20px !important;
vertical-align: middle !important;
margin-right: 5px !important;
stroke: #FF00FF !important;
fill: none !important;
}
@media (max-width: 768px) { @media (max-width: 768px) {
.section-container { .section-container {
padding-left: 15px; padding-left: 15px;
@ -926,7 +935,7 @@ $(document).ready(function() {
</td> </td>
</tr> </tr>
<tr> <tr>
<td style="width:150px; line-height: 2;"><i data-feather="box"></i> Mihomo</td> <td style="width:150px; line-height: 2;"><i class="fas fa-box custom-icon"></i> Mihomo</td>
<td class="d-grid"> <td class="d-grid">
<form action="index.php" method="post" style="display: inline-block; width: 100%; margin-bottom: 10px;"> <form action="index.php" method="post" style="display: inline-block; width: 100%; margin-bottom: 10px;">
<div class="form-group"> <div class="form-group">
@ -976,7 +985,7 @@ $(document).ready(function() {
</td> </td>
</tr> </tr>
<tr> <tr>
<td style="width:150px; line-height: 2;"><i data-feather="settings"></i> 运行模式</td> <td style="width:150px; line-height: 2;"><i class="fas fa-cog custom-icon"></i> 运行模式</td>
<td class="d-grid"> <td class="d-grid">
<?php <?php
$mode_placeholder = ''; $mode_placeholder = '';
@ -994,36 +1003,6 @@ $(document).ready(function() {
</tbody> </tbody>
</table> </table>
<div class="modal fade" id="singboxModal" tabindex="-1" aria-labelledby="singboxModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="singboxModalLabel">Sing-box 启动提示</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<p>如遇启动失败,请前往文件管理 更新数据库 下载 cache.db 缓存数据。</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">关闭</button>
</div>
</div>
</div>
</div>
<script>
$(document).ready(function() {
var lastShown = localStorage.getItem('singboxModalLastShown');
var currentTime = new Date().getTime();
if (!lastShown || (currentTime - lastShown) > 12 * 60 * 60 * 1000) {
$('#singboxModal').modal('show');
}
localStorage.setItem('singboxModalLastShown', currentTime);
});
</script>
<script> <script>
document.addEventListener("DOMContentLoaded", function() { document.addEventListener("DOMContentLoaded", function() {
const savedConfig = localStorage.getItem("configSelection"); const savedConfig = localStorage.getItem("configSelection");
@ -1235,46 +1214,12 @@ window.onload = function() {
</div> </div>
<button type="submit" name="clear_singbox_log" class="btn btn-danger me-2"><i class="bi bi-trash"></i> 清空日志</button> <button type="submit" name="clear_singbox_log" class="btn btn-danger me-2"><i class="bi bi-trash"></i> 清空日志</button>
<button type="button" class="btn btn-primary me-2" data-toggle="modal" data-target="#cronModal"><i class="bi bi-clock"></i> 定时重启</button> <button type="button" class="btn btn-primary me-2" data-toggle="modal" data-target="#cronModal"><i class="bi bi-clock"></i> 定时重启</button>
<button id="showHelpButton" class="btn btn-info" data-bs-toggle="modal" data-bs-target="#helpModal" type="button"><i class="bi bi-keyboard"></i> 键盘说明</button>
</form> </form>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="modal fade" id="helpModal" tabindex="-1" aria-labelledby="helpModalLabel" aria-hidden="true" data-bs-backdrop="static" data-bs-keyboard="false">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="helpModalLabel">键盘操作说明</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<ul>
<li><strong>鼠标左键:</strong> 双击打开播放器界面</li>
<li><strong>F9键:</strong> 切换播放/暂停</li>
<li><strong>上下箭头键:</strong> 切换上一首/下一首</li>
<li><strong>左右箭头键:</strong> 快进/快退 10 </li>
<li><strong>ESC键:</strong> 返回播放列表的第一首</li>
<li><strong>F2键:</strong> 切换循环播放和顺序播放模式</li>
<li><strong>F8键:</strong> 启动网站连通性检查</li>
<li><strong>F4键:</strong> 开启天气信息播报</li>
<li><strong>Ctrl + F6键:</strong> 启动/停止雪花动画 </li>
<li><strong>Ctrl + F7键:</strong> 启动/停止方块灯光动画 </li>
<li><strong>Ctrl + F10键:</strong> 启动/停止方块动画 </li>
<li><strong>Ctrl + F11键:</strong> 启动/停止光点动画 </li>
<li><strong>Ctrl + Shift + C键:</strong> 清空缓存</li>
<li><strong>Ctrl + Shift + V键:</strong> 定制播放列表</li>
<li><strong>Ctrl + Shift + X键:</strong> 设置城市</li>
</ul>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">关闭</button>
</div>
</div>
</div>
</div>
<div class="modal fade" id="cronModal" tabindex="-1" role="dialog" aria-labelledby="cronModalLabel" aria-hidden="true" data-backdrop="static" data-keyboard="false"> <div class="modal fade" id="cronModal" tabindex="-1" role="dialog" aria-labelledby="cronModalLabel" aria-hidden="true" data-backdrop="static" data-keyboard="false">
<div class="modal-dialog modal-dialog-centered modal-lg" role="document"> <div class="modal-dialog modal-dialog-centered modal-lg" role="document">
<div class="modal-content"> <div class="modal-content">

File diff suppressed because it is too large Load Diff

View File

@ -4,9 +4,26 @@ $filename = $_POST['filename'] ?? '';
$type = $_POST['type'] ?? ''; $type = $_POST['type'] ?? '';
$pingFile = $_SERVER['DOCUMENT_ROOT'] . '/nekobox/ping.php'; $pingFile = $_SERVER['DOCUMENT_ROOT'] . '/nekobox/ping.php';
$currentBgFile = $_SERVER['DOCUMENT_ROOT'] . '/nekobox/current_background.txt';
$backgroundHistoryFile = $_SERVER['DOCUMENT_ROOT'] . '/nekobox/background_history.txt';
$pingContent = file_get_contents($pingFile); $pingContent = file_get_contents($pingFile);
$audioElement = "";
$backgroundStyle = "";
if (!file_exists($backgroundHistoryFile)) {
file_put_contents($backgroundHistoryFile, "");
}
$backgroundFiles = file($backgroundHistoryFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) ?: [];
$filename = htmlspecialchars($filename, ENT_QUOTES, 'UTF-8');
if ($action === 'set' && !empty($filename)) { if ($action === 'set' && !empty($filename)) {
if ($type !== 'audio') {
$pingContent = preg_replace('/<!-- BG_START -->.*<!-- BG_END -->/s', '', $pingContent);
}
if ($type === 'image') { if ($type === 'image') {
$backgroundStyle = "\n<style> $backgroundStyle = "\n<style>
body { body {
@ -37,91 +54,47 @@ if ($action === 'set' && !empty($filename)) {
z-index: -1; z-index: -1;
} }
.control-toggle {
position: absolute;
top: 20px;
right: 20px;
padding: 10px 20px;
background-color: #6f42c1;
color: white;
border: none;
cursor: pointer;
font-size: 16px;
border-radius: 8px;
transition: background 0.3s, transform 0.2s;
}
.control-toggle:hover {
background: rgba(255, 255, 255, 0.3);
}
.popup {
display: none;
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: rgba(255, 255, 255, 0.8);
backdrop-filter: blur(10px);
color: #333;
padding: 20px;
border-radius: 12px;
z-index: 1000;
text-align: center;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2);
width: 280px;
}
.popup button {
display: block;
margin: 10px auto;
padding: 12px 20px;
font-size: 16px;
cursor: pointer;
border: none;
border-radius: 8px;
background-color: rgba(0, 0, 0, 0.1);
color: #333;
width: 100%;
transition: background 0.3s, transform 0.2s;
}
.popup button:hover {
background: rgba(0, 0, 0, 0.2);
transform: scale(1.05);
}
.popup button:active {
transform: scale(0.95);
}
</style> </style>
<video class=\"video-background\" autoplay loop id=\"background-video\"> <video class=\"video-background\" autoplay loop id=\"background-video\">
<source src='/nekobox/assets/Pictures/$filename' type='video/mp4'> <source src='/nekobox/assets/Pictures/$filename' type='video/mp4'>
您的浏览器不支持视频标签。 您的浏览器不支持视频标签。
</video> </video>";
} elseif ($type === 'audio') {
<button class=\"control-toggle\" onclick=\"togglePopup()\">🎛 设置</button> $audioElement = "
<div class=\"popup\" id=\"popup\"> <audio id=\"background-video\" autoplay loop>
<h3>🔧 控制面板</h3> <source src='/nekobox/assets/Pictures/$filename' type='audio/mp3'>
<button onclick=\"toggleAudio()\" id=\"audio-btn\">🔊 切换音频</button> 您的浏览器不支持音频播放。
<button onclick=\"toggleObjectFit()\" id=\"object-fit-btn\">切换视频显示模式</button> </audio>";
<button onclick=\"toggleFullScreen()\" id=\"fullscreen-btn\">⛶ 切换全屏</button>
<button onclick=\"togglePopup()\">❌ 关闭</button>
</div>\n";
} }
if (strpos($pingContent, '<!-- BG_START -->') !== false && strpos($pingContent, '<!-- BG_END -->') !== false) { if (strpos($pingContent, '<!-- BG_START -->') !== false && strpos($pingContent, '<!-- BG_END -->') !== false) {
$pingContent = preg_replace('/<!-- BG_START -->.*<!-- BG_END -->/s', "<!-- BG_START -->$backgroundStyle<!-- BG_END -->", $pingContent); $pingContent = preg_replace('/<!-- BG_START -->.*<!-- BG_END -->/s', "<!-- BG_START -->$backgroundStyle$audioElement<!-- BG_END -->", $pingContent);
} else { } else {
$pingContent .= "\n<!-- BG_START -->$backgroundStyle<!-- BG_END -->\n"; $pingContent .= "\n<!-- BG_START -->$backgroundStyle$audioElement<!-- BG_END -->\n";
} }
file_put_contents($pingFile, $pingContent); file_put_contents($pingFile, $pingContent);
file_put_contents($currentBgFile, $filename);
$backgroundFiles = array_filter(array_map('trim', file($backgroundHistoryFile)));
if (($key = array_search($filename, $backgroundFiles)) !== false) {
unset($backgroundFiles[$key]);
}
array_unshift($backgroundFiles, $filename);
$backgroundFiles = array_slice($backgroundFiles, 0, 20);
file_put_contents($backgroundHistoryFile, implode("\n", $backgroundFiles));
echo "背景已成功设置!"; echo "背景已成功设置!";
} elseif ($action === 'remove') { } elseif ($action === 'remove') {
$pingContent = preg_replace('/<!-- BG_START -->.*<!-- BG_END -->/s', '', $pingContent); $pingContent = preg_replace('/<!-- BG_START -->.*<!-- BG_END -->/s', '', $pingContent);
file_put_contents($pingFile, $pingContent); file_put_contents($pingFile, $pingContent);
file_put_contents($currentBgFile, '');
echo "背景已成功删除!"; echo "背景已成功删除!";
} }
?> ?>

View File

@ -569,887 +569,7 @@ $razordVersion = getRazordVersion();
</div> </div>
</div> </div>
<div class="modal fade" id="colorModal" tabindex="-1" aria-labelledby="colorModalLabel" aria-hidden="true" data-bs-backdrop="static" data-bs-keyboard="false">
<div class="modal-dialog modal-xl">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="colorModalLabel">选择主题颜色</h5>
<button type="button" class="close" data-bs-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
</div>
<div class="modal-body">
<form method="POST" action="theme.php" id="themeForm" enctype="multipart/form-data">
<div class="row">
<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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-4 mb-3">
<label for="ipColor" class="form-label">IP 文本色</label>
<input type="color" class="form-control" name="ipColor" id="ipColor" value="#09B63F">
</div>
<div class="col-md-4 mb-3">
<label for="ipipColor" class="form-label">运营商文本色</label>
<input type="color" class="form-control" name="ipipColor" id="ipipColor" value="#ff69b4">
</div>
<div class="col-md-4 mb-3">
<label for="detailColor" class="form-label">IP详情文本色</label>
<input type="color" class="form-control" name="detailColor" id="detailColor" value="#FFFFFF">
</div>
<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-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-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-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-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-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-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-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-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-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-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-4 mb-3">
<label for="heading6Color" class="form-label">标题色 6</label>
<input type="color" class="form-control" name="heading6Color" id="heading6Color" value="#00ffff">
</div>
</div>
<div class="col-12 mb-3">
<label for="containerWidth" class="form-label">容器宽度</label>
<input type="range" class="form-range" name="containerWidth" id="containerWidth" min="800" max="2400" step="50" value="1400" style="width: 100%;">
<div id="widthValue" class="mt-2" style="color: #FF00FF;">当前宽度: 1400px</div>
</div>
<div class="col-12 mb-3">
<label for="themeName" class="form-label">自定义主题名称</label>
<input type="text" class="form-control" name="themeName" id="themeName" value="transparent">
</div>
<div class="d-flex flex-wrap justify-content-center align-items-center mb-3 gap-2">
<button type="submit" class="btn btn-primary">保存主题</button>
<button type="button" class="btn btn-success" id="resetButton" onclick="clearCache()">恢复默认值</button>
<button type="button" class="btn btn-info" id="exportButton">立即备份</button>
<button type="button" class="btn btn-warning" id="restoreButton">恢复备份</button>
<input type="file" id="importButton" class="form-control" accept="application/json" style="display: none;">
<button type="button" class="btn btn-pink" data-bs-dismiss="modal">取消</button>
</div>
</form>
</div>
</div>
</div>
</div>
<style>
input[type="range"] {
-webkit-appearance: none;
appearance: none;
width: 100%;
height: 10px;
border-radius: 5px;
background: linear-gradient(to right, #ff00ff, #00ffff);
outline: none;
}
input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 20px;
height: 20px;
border-radius: 50%;
background: #ff00ff;
border: none;
cursor: pointer;
}
input[type="range"]:focus {
outline: none;
}
input[type="range"]::-moz-range-thumb {
width: 20px;
height: 20px;
border-radius: 50%;
background: #ff00ff;
border: none;
cursor: pointer;
}
#widthValue {
color: #ff00ff;
}
</style>
<script>
const slider = document.getElementById("containerWidth");
const widthValue = document.getElementById("widthValue");
function updateSliderColor(value) {
let red = Math.min(Math.max((value - 800) / (2400 - 800) * 255, 0), 255);
let green = 255 - red;
slider.style.background = `linear-gradient(to right, rgb(${red}, ${green}, 255), rgb(${255 - red}, ${green}, ${255 - red}))`;
slider.style.setProperty('--thumb-color', `rgb(${red}, ${green}, 255)`);
widthValue.textContent = `当前宽度: ${value}px`;
widthValue.style.color = `rgb(${red}, ${green}, 255)`;
}
let savedWidth = localStorage.getItem('containerWidth');
if (savedWidth) {
slider.value = savedWidth;
}
updateSliderColor(slider.value);
slider.oninput = function() {
updateSliderColor(slider.value);
localStorage.setItem('containerWidth', slider.value);
};
</script>
<script>
document.getElementById('useBackgroundImage').addEventListener('change', function() {
const container = document.getElementById('backgroundImageContainer');
container.style.display = this.checked ? 'block' : 'none';
});
</script>
<script>
document.getElementById('restoreButton').addEventListener('click', () => {
document.getElementById('importButton').click();
});
document.getElementById('importButton').addEventListener('change', (event) => {
const file = event.target.files[0];
if (file) {
const reader = new FileReader();
reader.onload = (e) => {
const content = e.target.result;
try {
const jsonData = JSON.parse(content);
console.log('恢复的备份数据:', jsonData);
alert('备份已成功上传并解析!');
} catch (error) {
alert('文件格式错误,请上传正确的 JSON 文件!');
}
};
reader.readAsText(file);
}
});
</script>
<script>
function clearCache() {
location.reload(true);
localStorage.clear();
sessionStorage.clear();
sessionStorage.setItem('cacheCleared', 'true');
}
window.addEventListener('load', function() {
if (sessionStorage.getItem('cacheCleared') === 'true') {
sessionStorage.removeItem('cacheCleared');
}
});
</script>
<script>
const tooltip = document.createElement('div');
tooltip.style.position = 'fixed';
tooltip.style.top = '10px';
tooltip.style.left = '10px';
tooltip.style.backgroundColor = 'rgba(0, 128, 0, 0.7)';
tooltip.style.color = 'white';
tooltip.style.padding = '10px';
tooltip.style.borderRadius = '5px';
tooltip.style.zIndex = '9999';
tooltip.style.display = 'none';
document.body.appendChild(tooltip);
function showTooltip(message) {
tooltip.textContent = message;
tooltip.style.display = 'block';
setTimeout(() => {
tooltip.style.display = 'none';
}, 5000);
}
window.onload = function() {
const lastShownTime = localStorage.getItem('lastTooltipShownTime');
const currentTime = new Date().getTime();
if (!lastShownTime || (currentTime - lastShownTime) > 4 * 60 * 60 * 1000) {
showTooltip('双击左键打开播放器F8键开启网站连通性检测');
localStorage.setItem('lastTooltipShownTime', currentTime);
}
};
</script>
<div class="modal fade" id="filesModal" tabindex="-1" aria-labelledby="filesModalLabel" aria-hidden="true" data-bs-backdrop="static" data-bs-keyboard="false">
<div class="modal-dialog modal-xl">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="filesModalLabel">上传并管理背景图片/视频</h5>
<button type="button" class="close" data-bs-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
</div>
<div class="modal-body">
<div class="mb-4">
<h2 class="mb-3">上传背景图片/视频</h2>
<form method="POST" action="download.php" enctype="multipart/form-data">
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#uploadModal"><i class="fas fa-cloud-upload-alt"></i> 上传图片/视频</button>
</form>
</div>
<h2 class="mb-3">上传的图片/视频文件</h2>
<table class="table table-bordered text-center">
<thead>
<tr>
<th style="width: 25%;">文件名</th>
<th style="width: 10%;">文件大小</th>
<th style="width: 10%;">文件类型</th>
<th style="width: 30%;">预览</th>
<th style="width: 25%;">操作</th>
</tr>
</thead>
<tbody>
<?php
function isImage($file) {
$imageExtensions = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp'];
$fileExtension = strtolower(pathinfo($file, PATHINFO_EXTENSION));
return in_array($fileExtension, $imageExtensions);
}
function isVideo($file) {
$videoExtensions = ['mp4', 'avi', 'mkv', 'mov', 'wmv'];
$fileExtension = strtolower(pathinfo($file, PATHINFO_EXTENSION));
return in_array($fileExtension, $videoExtensions);
}
function getFileNameWithoutPrefix($file) {
$fileBaseName = pathinfo($file, PATHINFO_FILENAME);
$hyphenPos = strpos($fileBaseName, '-');
if ($hyphenPos !== false) {
return substr($fileBaseName, $hyphenPos + 1) . '.' . pathinfo($file, PATHINFO_EXTENSION);
} else {
return $file;
}
}
$picturesDir = $_SERVER['DOCUMENT_ROOT'] . '/nekobox/assets/Pictures/';
if (is_dir($picturesDir)) {
$files = array_diff(scandir($picturesDir), array('..', '.'));
foreach ($files as $file) {
$filePath = $picturesDir . $file;
if (is_file($filePath)) {
$fileSize = filesize($filePath);
$fileUrl = '/nekobox/assets/Pictures/' . $file;
$fileNameWithoutPrefix = getFileNameWithoutPrefix($file);
if (isImage($file)) {
$fileType = "图片";
} elseif (isVideo($file)) {
$fileType = "视频";
} else {
$fileType = "未知类型";
}
echo "<tr>
<td class='align-middle' data-label='文件名'>$fileNameWithoutPrefix</td>
<td class='align-middle' data-label='文件大小'>" . formatFileSize($fileSize) . "</td>
<td class='align-middle' data-label='文件类型'>$fileType</td>
<td class='align-middle' data-label='预览'>";
if (isVideo($file)) {
echo "<video width='200' controls><source src='$fileUrl' type='video/mp4'>Your browser does not support the video tag.</video>";
} elseif (isImage($file)) {
echo "<img src='$fileUrl' alt='$file' style='width: 200px; height: auto;'>";
} else {
echo "未知文件类型";
}
echo "</td>
<td class='align-middle' data-label='操作'>
<div class='btn-container'>
<a href='?delete=" . htmlspecialchars($file, ENT_QUOTES) . "' class='btn btn-danger' onclick='return confirm(\"确定要删除吗?\")'>删除</a>";
if (isImage($file)) {
echo "<button type=\"button\" onclick=\"setBackground('" . htmlspecialchars($file, ENT_QUOTES) . "', 'image')\" style=\"padding: 10px 14px; font-size: 14px; margin-left: 10px; background-color: #007bff; color: white; border-radius: 5px; border: none;\">设置图片背景</button>";
} elseif (isVideo($file)) {
echo "<button type=\"button\" onclick=\"setBackground('" . htmlspecialchars($file, ENT_QUOTES) . "', 'video')\" style=\"padding: 10px 14px; font-size: 14px; margin-left: 10px; background-color: #007bff; color: white; border-radius: 5px; border: none;\">设置视频背景</button>";
}
echo "</td>
</tr>";
}
}
}
?>
</tbody>
</table>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
<button type="button" class="btn btn-danger" onclick="setBackground('', '', 'remove')">删除背景</button>
</div>
</div>
</div>
</div>
<div class="modal fade" id="uploadModal" tabindex="-1" aria-labelledby="uploadModalLabel" aria-hidden="true" data-bs-backdrop="static" data-bs-keyboard="false">
<div class="modal-dialog modal-xl">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="uploadModalLabel"><i class="fas fa-cloud-upload-alt"></i> 上传文件</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body text-center">
<h2 class="mb-3">上传图片/视频</h2>
<form method="POST" action="download.php" enctype="multipart/form-data">
<div id="dropArea" class="mb-3">
<i id="uploadIcon" class="fas fa-cloud-upload-alt"></i>
<p>拖拽文件到此区域,或点击图标选择文件。</p>
<p>PHP上传文件会有大小限制如遇上传失败可以手动上传文件到 /nekobox/assets/Pictures 目录</p>
</div>
<input type="file" class="form-control mb-3" name="imageFile[]" id="imageFile" multiple style="display: none;">
<button type="submit" class="btn btn-success mt-3" id="submitBtnModal">
上传图片/视频
</button>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
<button type="button" class="btn btn-warning" id="updatePhpConfig">更新 PHP 上传限制</button>
</div>
</div>
</div>
</div>
<script>
document.getElementById("updatePhpConfig").addEventListener("click", function() {
if (confirm("确定要修改 PHP 上传限制吗?")) {
fetch("update_php_config.php", {
method: "POST",
headers: { "Content-Type": "application/json" }
})
.then(response => response.json())
.then(data => alert(data.message))
.catch(error => alert("请求失败:" + error.message));
}
});
</script>
<script>
document.getElementById('uploadIcon').addEventListener('click', function() {
document.getElementById('imageFile').click();
});
document.getElementById('imageFile').addEventListener('change', function() {
if (this.files.length > 0) {
document.getElementById('submitBtnModal').style.display = 'inline-block';
} else {
document.getElementById('submitBtnModal').style.display = 'none';
}
});
const dropArea = document.getElementById('dropArea');
dropArea.addEventListener('dragover', function(event) {
event.preventDefault();
dropArea.classList.add('dragging');
});
dropArea.addEventListener('dragleave', function() {
dropArea.classList.remove('dragging');
});
dropArea.addEventListener('drop', function(event) {
event.preventDefault();
dropArea.classList.remove('dragging');
const files = event.dataTransfer.files;
document.getElementById('imageFile').files = files;
if (files.length > 0) {
document.getElementById('submitBtnModal').style.display = 'inline-block';
}
});
</script>
<script>
const fileInput = document.getElementById('imageFile');
const dragDropArea = document.getElementById('dragDropArea');
const submitBtn = document.getElementById('submitBtn');
dragDropArea.addEventListener('dragover', function(e) {
e.preventDefault();
dragDropArea.classList.add('drag-over');
});
dragDropArea.addEventListener('dragleave', function(e) {
e.preventDefault();
dragDropArea.classList.remove('drag-over');
});
dragDropArea.addEventListener('drop', function(e) {
e.preventDefault();
dragDropArea.classList.remove('drag-over');
const files = e.dataTransfer.files;
if (files.length > 0) {
fileInput.files = files;
}
});
fileInput.addEventListener('change', function(e) {
const files = e.target.files;
if (files.length > 0) {
submitBtn.disabled = false;
} else {
submitBtn.disabled = true;
}
});
function updateDragDropText() {
if (fileInput.files.length > 0) {
dragDropArea.querySelector('p').textContent = `${fileInput.files.length} 个文件已选择`;
} else {
dragDropArea.querySelector('p').textContent = '拖动文件到此区域,或点击选择文件';
}
}
</script>
<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$uploadedFilePath = '';
$allowedTypes = [
'image/jpeg', 'image/png', 'image/gif', 'image/bmp', 'image/webp',
'video/mp4', 'video/avi', 'video/mkv', 'video/mov', 'video/wmv', 'video/3gp'
];
if (isset($_FILES['imageFile']) && $_FILES['imageFile']['error'] === UPLOAD_ERR_OK) {
$targetDir = $_SERVER['DOCUMENT_ROOT'] . '/nekobox/assets/Pictures/';
if (!file_exists($targetDir)) {
mkdir($targetDir, 0777, true);
}
$fileExtension = strtolower(pathinfo($_FILES['imageFile']['name'], PATHINFO_EXTENSION));
if (in_array($fileExtension, $allowedTypes)) {
$targetFile = $targetDir . basename($_FILES['imageFile']['name']);
if (move_uploaded_file($_FILES['imageFile']['tmp_name'], $targetFile)) {
$uploadedFilePath = '/nekobox/assets/Pictures/' . basename($_FILES['imageFile']['name']);
}
} else {
echo "<script>alert('不支持的文件类型!');</script>";
}
}
}
if (isset($_GET['delete'])) {
$fileToDelete = $_GET['delete'];
$picturesDir = $_SERVER['DOCUMENT_ROOT'] . '/nekobox/assets/Pictures/';
$filePath = $picturesDir . $fileToDelete;
if (file_exists($filePath)) {
unlink($filePath);
echo "<script>alert('文件已删除!'); window.location.href = 'settings.php';</script>";
exit;
}
}
function formatFileSize($size) {
if ($size >= 1073741824) {
return number_format($size / 1073741824, 2) . ' GB';
} elseif ($size >= 1048576) {
return number_format($size / 1048576, 2) . ' MB';
} elseif ($size >= 1024) {
return number_format($size / 1024, 2) . ' KB';
} else {
return $size . ' bytes';
}
}
?>
<script>
function setBackground(filename, type, action = 'set') {
const bodyData = 'filename=' + encodeURIComponent(filename) + '&type=' + type;
if (action === 'set') {
fetch('/nekobox/set_background.php', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: 'action=set&' + bodyData
})
.then(response => response.text())
.then(data => {
sessionStorage.setItem('notificationMessage', data);
sessionStorage.setItem('notificationType', 'success');
location.reload();
})
.catch(error => {
console.error('Error:', error);
sessionStorage.setItem('notificationMessage', "操作失败,请稍后再试");
sessionStorage.setItem('notificationType', 'error');
location.reload();
});
}
else if (action === 'remove') {
fetch('/nekobox/set_background.php', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: 'action=remove'
})
.then(response => response.text())
.then(data => {
sessionStorage.setItem('notificationMessage', data);
sessionStorage.setItem('notificationType', 'success');
location.reload();
})
.catch(error => {
console.error('Error:', error);
sessionStorage.setItem('notificationMessage', "删除失败,请稍后再试");
sessionStorage.setItem('notificationType', 'error');
location.reload();
});
}
}
function showNotification(message, type = 'success') {
var notification = document.createElement('div');
notification.style.position = 'fixed';
notification.style.top = '10px';
notification.style.left = '30px';
notification.style.padding = '10px';
notification.style.borderRadius = '5px';
notification.style.zIndex = '9999';
notification.style.color = '#fff';
notification.innerText = message;
if (type === 'success') {
notification.style.backgroundColor = '#4CAF50';
} else if (type === 'error') {
notification.style.backgroundColor = '#F44336';
}
document.body.appendChild(notification);
setTimeout(function() {
notification.style.display = 'none';
}, 5000);
}
window.addEventListener('load', function() {
var message = sessionStorage.getItem('notificationMessage');
var type = sessionStorage.getItem('notificationType');
if (message) {
showNotification(message, type);
sessionStorage.removeItem('notificationMessage');
sessionStorage.removeItem('notificationType');
}
});
</script>
<script>
document.addEventListener("DOMContentLoaded", function() {
const colorInputs = document.querySelectorAll('input[type="color"]');
colorInputs.forEach(input => {
if (localStorage.getItem(input.name)) {
input.value = localStorage.getItem(input.name);
}
input.addEventListener('input', function() {
localStorage.setItem(input.name, input.value);
});
});
const useBackgroundImageCheckbox = document.getElementById('useBackgroundImage');
const backgroundImageContainer = document.getElementById('backgroundImageContainer');
const savedBackgroundImageState = localStorage.getItem('useBackgroundImage');
if (savedBackgroundImageState === 'true') {
useBackgroundImageCheckbox.checked = true;
backgroundImageContainer.style.display = 'block';
} else {
useBackgroundImageCheckbox.checked = false;
backgroundImageContainer.style.display = 'none';
}
useBackgroundImageCheckbox.addEventListener('change', function() {
if (useBackgroundImageCheckbox.checked) {
backgroundImageContainer.style.display = 'block';
} else {
backgroundImageContainer.style.display = 'none';
}
localStorage.setItem('useBackgroundImage', useBackgroundImageCheckbox.checked);
});
document.getElementById('resetButton').addEventListener('click', function() {
document.getElementById('primaryColor').value = '#0ceda2';
document.getElementById('secondaryColor').value = '#00ffff';
document.getElementById('bodyBgColor').value = '#23407e';
document.getElementById('infoBgSubtle').value = '#23407e';
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('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('ipColor').value = '#09b63f';
document.getElementById('ipipColor').value = '#ff69b4';
document.getElementById('detailColor').value = '#FFFFFF';
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();
});
document.getElementById('exportButton').addEventListener('click', function() {
const settings = {
primaryColor: document.getElementById('primaryColor').value,
secondaryColor: document.getElementById('secondaryColor').value,
bodyBgColor: document.getElementById('bodyBgColor').value,
infoBgSubtle: document.getElementById('infoBgSubtle').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,
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,
ipColor: document.getElementById('ipColor').value,
ipipColor: document.getElementById('ipipColor').value,
detailColor: document.getElementById('detailColor').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,
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
};
const blob = new Blob([JSON.stringify(settings)], { type: 'application/json' });
const link = document.createElement('a');
link.href = URL.createObjectURL(blob);
link.download = 'theme-settings.json';
link.click();
});
document.getElementById('importButton').addEventListener('change', function(event) {
const file = event.target.files[0];
if (file && file.type === 'application/json') {
const reader = new FileReader();
reader.onload = function(e) {
const settings = JSON.parse(e.target.result);
document.getElementById('primaryColor').value = settings.primaryColor;
document.getElementById('secondaryColor').value = settings.secondaryColor;
document.getElementById('bodyBgColor').value = settings.bodyBgColor;
document.getElementById('infoBgSubtle').value = settings.infoBgSubtle;
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('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('ipColor').value = settings.ipColor;
document.getElementById('ipipColor').value = settings.ipipColor;
document.getElementById('detailColor').value = settings.detailColor;
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('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');
backgroundImageContainer.style.display = settings.useBackgroundImage ? 'block' : 'none';
document.getElementById('backgroundImage').value = settings.backgroundImage || '';
localStorage.setItem('primaryColor', settings.primaryColor);
localStorage.setItem('secondaryColor', settings.secondaryColor);
localStorage.setItem('bodyBgColor', settings.bodyBgColor);
localStorage.setItem('infoBgSubtle', settings.infoBgSubtle);
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('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('ipColor', settings.ipColor);
localStorage.setItem('ipipColor', settings.ipipColor);
localStorage.setItem('detailColor', settings.detailColor);
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('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);
};
reader.readAsText(file);
}
});
});
</script>
<style> <style>
@media (max-width: 767px) { @media (max-width: 767px) {
.table td { .table td {

View File

@ -0,0 +1,79 @@
<?php
$data = json_decode(file_get_contents('php://input'), true);
$width = isset($data['width']) ? $data['width'] : null;
$modalWidth = isset($data['modalWidth']) ? $data['modalWidth'] : null;
$applyGroup1 = isset($data['group1']) && $data['group1'] == 1;
$applyBodyBackground = isset($data['bodyBackground']) && $data['bodyBackground'] == 1;
if ($width !== null && $modalWidth !== null) {
$cssFilePath = 'assets/theme/transparent.css';
if (file_exists($cssFilePath)) {
$cssContent = file_get_contents($cssFilePath);
$cssContent = preg_replace('/\/\* START .container-sm \*\/.*?\/\* END .container-sm \*\//s', '', $cssContent);
$cssContent = preg_replace('/\/\* START .modal-xl \*\/.*?\/\* END .modal-xl \*\//s', '', $cssContent);
$containerCss = "
/* START .container-sm */
.container-sm {
width: ${width}px !important;
max-width: 100%;
margin: 0 auto;
}
/* END .container-sm */
/* START .modal-xl */
.modal-xl {
max-width: ${modalWidth}px !important;
}
@media (max-width: 768px) {
.modal-xl {
max-width: 100%;
}
}
/* END .modal-xl */
";
$position = strpos($cssContent, '.scrollable-container:hover {');
if ($position !== false) {
$scrollableCssEnd = strpos($cssContent, '}', $position);
$newCssContent = substr($cssContent, 0, $scrollableCssEnd + 1) . "\n" . $containerCss . substr($cssContent, $scrollableCssEnd + 1);
file_put_contents($cssFilePath, $newCssContent);
echo json_encode(['status' => 'success', 'message' => 'CSS 更新成功']);
} else {
echo json_encode(['status' => 'error', 'message' => '未找到 .scrollable-container:hover 样式']);
}
} else {
echo json_encode(['status' => 'error', 'message' => 'CSS 文件未找到']);
}
}
if ($applyGroup1 || $applyBodyBackground) {
$cssFilePath = 'assets/theme/transparent.css';
if (file_exists($cssFilePath)) {
$cssContent = file_get_contents($cssFilePath);
if ($applyGroup1) {
$cssContent = preg_replace('/(--bs-disabled-bg:)[^;]+;/', '$1 transparent;', $cssContent);
$cssContent = preg_replace('/(--bs-form-select:)[^;]+;/', '$1 transparent;', $cssContent);
$cssContent = preg_replace('/(--bs-info-bg-subtle:)[^;]+;/', '$1 transparent;', $cssContent);
}
if ($applyBodyBackground) {
$cssContent = preg_replace('/(--bs-body-bg:)[^;]+;/', '$1 transparent;', $cssContent);
}
file_put_contents($cssFilePath, $cssContent);
echo json_encode(['status' => 'success', 'message' => '透明背景已应用']);
} else {
echo json_encode(['status' => 'error', 'message' => 'CSS 文件未找到']);
}
} else {
echo json_encode(['status' => 'error', 'message' => '未启用透明背景']);
}
?>

View File

@ -1 +1 @@
V1.7.5-cn V1.7.6-cn