update 2025-02-04 14:16:01
This commit is contained in:
parent
1aa62b3f85
commit
6dbf0c5a5e
|
@ -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.5
|
||||
PKG_VERSION:=1.7.6
|
||||
PKG_RELEASE:=cn
|
||||
|
||||
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
|
||||
|
|
|
@ -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">
|
||||
<title>Latest Version: v1.7.5</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.6">
|
||||
<title>Latest Version: v1.7.6</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.5</text>
|
||||
<text x="1405" y="140" transform="scale(.1)" fill="#fff" 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.6</text>
|
||||
</g>
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
@ -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">
|
||||
<title>Current Version: v1.7.5</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.6">
|
||||
<title>Current Version: v1.7.6</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.5</text>
|
||||
<text x="1405" y="140" transform="scale(.1)" fill="#fff" 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.6</text>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
@ -119,12 +119,6 @@
|
|||
color: var(--bs-heading-5) !important;
|
||||
}
|
||||
|
||||
.container-sm {
|
||||
width: var(--container-width);
|
||||
max-width: 100%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.form-label {
|
||||
color: var(--bs-check-bg)
|
||||
}
|
||||
|
|
|
@ -824,6 +824,15 @@ $(document).ready(function() {
|
|||
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) {
|
||||
.section-container {
|
||||
padding-left: 15px;
|
||||
|
@ -926,7 +935,7 @@ $(document).ready(function() {
|
|||
</td>
|
||||
</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">
|
||||
<form action="index.php" method="post" style="display: inline-block; width: 100%; margin-bottom: 10px;">
|
||||
<div class="form-group">
|
||||
|
@ -976,7 +985,7 @@ $(document).ready(function() {
|
|||
</td>
|
||||
</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">
|
||||
<?php
|
||||
$mode_placeholder = '';
|
||||
|
@ -994,36 +1003,6 @@ $(document).ready(function() {
|
|||
</tbody>
|
||||
</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>
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
const savedConfig = localStorage.getItem("configSelection");
|
||||
|
@ -1235,46 +1214,12 @@ window.onload = function() {
|
|||
</div>
|
||||
<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 id="showHelpButton" class="btn btn-info" data-bs-toggle="modal" data-bs-target="#helpModal" type="button"><i class="bi bi-keyboard"></i> 键盘说明</button>
|
||||
</form>
|
||||
</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-dialog modal-dialog-centered modal-lg" role="document">
|
||||
<div class="modal-content">
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -4,9 +4,26 @@ $filename = $_POST['filename'] ?? '';
|
|||
$type = $_POST['type'] ?? '';
|
||||
|
||||
$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);
|
||||
$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 ($type !== 'audio') {
|
||||
$pingContent = preg_replace('/<!-- BG_START -->.*<!-- BG_END -->/s', '', $pingContent);
|
||||
}
|
||||
|
||||
if ($type === 'image') {
|
||||
$backgroundStyle = "\n<style>
|
||||
body {
|
||||
|
@ -37,91 +54,47 @@ if ($action === 'set' && !empty($filename)) {
|
|||
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>
|
||||
|
||||
<video class=\"video-background\" autoplay loop id=\"background-video\">
|
||||
<source src='/nekobox/assets/Pictures/$filename' type='video/mp4'>
|
||||
您的浏览器不支持视频标签。
|
||||
</video>
|
||||
|
||||
<button class=\"control-toggle\" onclick=\"togglePopup()\">🎛 设置</button>
|
||||
<div class=\"popup\" id=\"popup\">
|
||||
<h3>🔧 控制面板</h3>
|
||||
<button onclick=\"toggleAudio()\" id=\"audio-btn\">🔊 切换音频</button>
|
||||
<button onclick=\"toggleObjectFit()\" id=\"object-fit-btn\">切换视频显示模式</button>
|
||||
<button onclick=\"toggleFullScreen()\" id=\"fullscreen-btn\">⛶ 切换全屏</button>
|
||||
<button onclick=\"togglePopup()\">❌ 关闭</button>
|
||||
</div>\n";
|
||||
</video>";
|
||||
} elseif ($type === 'audio') {
|
||||
$audioElement = "
|
||||
<audio id=\"background-video\" autoplay loop>
|
||||
<source src='/nekobox/assets/Pictures/$filename' type='audio/mp3'>
|
||||
您的浏览器不支持音频播放。
|
||||
</audio>";
|
||||
}
|
||||
|
||||
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 {
|
||||
$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($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 "背景已成功设置!";
|
||||
} elseif ($action === 'remove') {
|
||||
$pingContent = preg_replace('/<!-- BG_START -->.*<!-- BG_END -->/s', '', $pingContent);
|
||||
file_put_contents($pingFile, $pingContent);
|
||||
file_put_contents($currentBgFile, '');
|
||||
|
||||
echo "背景已成功删除!";
|
||||
}
|
||||
?>
|
||||
|
|
|
@ -569,887 +569,7 @@ $razordVersion = getRazordVersion();
|
|||
</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">×</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">×</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>
|
||||
@media (max-width: 767px) {
|
||||
.table td {
|
||||
|
|
|
@ -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' => '未启用透明背景']);
|
||||
}
|
||||
?>
|
|
@ -1 +1 @@
|
|||
V1.7.5-cn
|
||||
V1.7.6-cn
|
||||
|
|
Loading…
Reference in New Issue