update 2025-02-02 09:28:42

This commit is contained in:
kenzok8 2025-02-02 09:28:42 +08:00
parent 1c5aaed286
commit dcdc295470
9 changed files with 479 additions and 36 deletions

File diff suppressed because one or more lines are too long

View File

@ -1,21 +1,62 @@
<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (isset($_FILES['imageFile']) && $_FILES['imageFile']['error'] === UPLOAD_ERR_OK) {
if (isset($_FILES['imageFile']) && is_array($_FILES['imageFile']['error'])) {
$targetDir = $_SERVER['DOCUMENT_ROOT'] . '/nekobox/assets/Pictures/';
if (!file_exists($targetDir)) {
mkdir($targetDir, 0777, true);
mkdir($targetDir, 0777, true);
}
$targetFile = $targetDir . basename($_FILES['imageFile']['name']);
$uploadedImagePath = '/nekobox/assets/Pictures/' . basename($_FILES['imageFile']['name']);
$allowedFileTypes = ['image/jpeg', 'image/png', 'video/mp4'];
$maxFileSize = 1024 * 1024 * 1024;
if (move_uploaded_file($_FILES['imageFile']['tmp_name'], $targetFile)) {
$uploadedFiles = [];
$fileErrors = [];
foreach ($_FILES['imageFile']['name'] as $key => $fileName) {
$fileTmpName = $_FILES['imageFile']['tmp_name'][$key];
$fileSize = $_FILES['imageFile']['size'][$key];
$fileError = $_FILES['imageFile']['error'][$key];
$fileType = $_FILES['imageFile']['type'][$key];
if ($fileError === UPLOAD_ERR_OK) {
if (!in_array($fileType, $allowedFileTypes)) {
$fileErrors[] = "文件 '$fileName' 类型不允许上传!";
continue;
}
if ($fileSize > $maxFileSize) {
$fileErrors[] = "文件 '$fileName' 大小超出限制!";
continue;
}
$uniqueFileName = uniqid() . '-' . basename($fileName);
$targetFile = $targetDir . $uniqueFileName;
$uploadedFilePath = '/nekobox/assets/Pictures/' . $uniqueFileName;
if (move_uploaded_file($fileTmpName, $targetFile)) {
$uploadedFiles[] = $uploadedFilePath;
} else {
$fileErrors[] = "文件 '$fileName' 上传失败!";
}
} else {
$fileErrors[] = "文件 '$fileName' 上传出错,错误代码: $fileError";
}
}
if (count($uploadedFiles) > 0) {
echo "<script>
alert('图片或视频已上传成功!');
alert('文件上传成功!');
window.location.href = 'settings.php';
</script>";
} else {
echo "<script>alert('文件上传失败!');</script>";
if (count($fileErrors) > 0) {
foreach ($fileErrors as $error) {
echo "<script>alert('$error');</script>";
}
} else {
echo "<script>alert('没有文件上传或上传出错!');</script>";
}
}
} else {
echo "<script>alert('没有文件上传或上传出错!');</script>";

View File

@ -837,6 +837,70 @@ $(document).ready(function() {
display: block;
}
}
@media (max-width: 767px) {
.section-container .table {
display: block;
width: 100%;
}
.section-container .table tbody,
.section-container .table thead,
.section-container .table tr {
display: block;
}
.section-container .table td {
display: block;
width: 100%;
padding: 10px;
border: 1px solid #ddd;
margin-bottom: 10px;
}
.section-container .table td:first-child {
font-weight: bold;
background-color: #f8f9fa;
}
.section-container .btn-group {
display: flex;
flex-direction: column;
gap: 10px;
}
.section-container .form-select,
.section-container .form-control,
.section-container .input-group {
width: 100%;
}
.section-container .btn {
width: 100%;
}
}
@media (max-width: 767px) {
.section-container .table td {
background-color: #fff;
border-radius: 5px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.section-container .table td:first-child {
background-color: #f0f0f0;
font-size: 1.1em;
}
.section-container .btn {
border-radius: 5px;
}
.section-container .btn-group {
gap: 15px;
}
}
</style>
<div class="section-container">
<table class="table table-borderless mb-2">

View File

@ -480,7 +480,122 @@ $lang = $_GET['lang'] ?? 'en';
fill: none !important;
}
#dropArea {
border: 2px dashed #007bff;
padding: 20px;
border-radius: 10px;
text-align: center;
background-color: #f8f9fa;
}
#dropArea.dragging {
background-color: #e9ecef;
}
#dropArea p {
color: #ff69b4;
}
#uploadIcon {
font-size: 50px;
color: #007bff;
cursor: pointer;
margin-bottom: 20px;
transition: color 0.3s;
}
#uploadIcon:hover {
color: #0056b3;
}
#submitBtnModal {
display: none;
padding: 10px 20px;
font-size: 16px;
border: none;
background-color: #28a745;
color: white;
border-radius: 5px;
cursor: pointer;
transition: background-color 0.3s;
}
#submitBtnModal:hover {
background-color: #218838;
}
@media (max-width: 768px) {
.d-flex.justify-content-between.gap-2 {
width: 100%;
display: flex;
justify-content: space-between;
gap: 5px;
padding-left: 0.7em;
}
.d-flex.justify-content-between.gap-2 .btn {
flex: 1;
min-width: 0;
text-align: center;
}
}
@media (max-width: 768px) {
.table thead {
display: none;
}
.table tbody,
.table tr,
.table td {
display: block;
width: 100%;
}
.table tr {
margin-bottom: 10px;
border: 1px solid #dee2e6;
border-radius: 5px;
padding: 10px;
background: #f8f9fa;
}
.table td::before {
content: attr(data-label);
font-weight: bold;
display: block;
margin-bottom: 5px;
}
.table td img,
.table td video {
display: block;
margin: 0 auto;
}
.table td .btn-container {
display: flex;
justify-content: space-between;
gap: 10px;
}
.table td .btn {
flex: 1;
text-align: center;
padding: 10px;
font-size: 14px;
min-width: 0;
}
}
@media (max-width: 767px) {
.control-toggle {
display: none;
}
}
</style>
<link rel="stylesheet" href="./assets/bootstrap/all.min.css">
<link href="./assets/bootstrap/bootstrap-icons.css" rel="stylesheet">
<script src="./assets/neko/js/jquery.min.js"></script>
<link rel="stylesheet" href="./assets/bootstrap/leaflet.css" />
@ -1154,19 +1269,25 @@ setInterval(IP.getIpipnetIP, 180000);
<script>
document.addEventListener("DOMContentLoaded", function () {
var video = document.getElementById('background-video');
var savedMuteState = localStorage.getItem("videoMuted");
if (savedMuteState !== null) {
video.muted = savedMuteState === "true";
}
var savedObjectFit = localStorage.getItem("videoObjectFit");
if (savedObjectFit) {
video.style.objectFit = savedObjectFit;
} else {
video.style.objectFit = "cover";
}
updateButtonStates();
});
function togglePopup() {
var popup = document.getElementById('popup');
popup.style.display = (popup.style.display === "block") ? "none" : "block";
updateButtonStates();
}
@ -1186,13 +1307,50 @@ setInterval(IP.getIpipnetIP, 180000);
updateButtonStates();
}
function toggleObjectFit() {
var video = document.getElementById('background-video');
var objectFitBtn = document.getElementById('object-fit-btn');
switch (video.style.objectFit) {
case "contain":
video.style.objectFit = "cover";
objectFitBtn.textContent = "🔲 正常显示";
localStorage.setItem("videoObjectFit", "cover");
break;
case "cover":
video.style.objectFit = "fill";
objectFitBtn.textContent = "🖼️ 填充";
localStorage.setItem("videoObjectFit", "fill");
break;
case "fill":
video.style.objectFit = "none";
objectFitBtn.textContent = "🔲 不缩放";
localStorage.setItem("videoObjectFit", "none");
break;
case "none":
video.style.objectFit = "scale-down";
objectFitBtn.textContent = "🖼️ 缩小";
localStorage.setItem("videoObjectFit", "scale-down");
break;
case "scale-down":
video.style.objectFit = "contain";
objectFitBtn.textContent = "🖼️ 铺满全屏";
localStorage.setItem("videoObjectFit", "contain");
break;
default:
video.style.objectFit = "cover";
objectFitBtn.textContent = "🔲 正常显示";
localStorage.setItem("videoObjectFit", "cover");
break;
}
}
function updateButtonStates() {
var video = document.getElementById('background-video');
var audioBtn = document.getElementById('audio-btn');
var fullscreenBtn = document.getElementById('fullscreen-btn');
audioBtn.textContent = video.muted ? "🔇 静音" : "🔊 取消静音";
fullscreenBtn.textContent = document.fullscreenElement ? "📴 退出全屏" : "⛶ 进入全屏";
}
@ -1203,7 +1361,7 @@ setInterval(IP.getIpipnetIP, 180000);
});
document.addEventListener("fullscreenchange", updateButtonStates);
</script>
</script>
<script>
document.addEventListener('keydown', function(event) {
@ -2405,3 +2563,13 @@ function speakWeather(weather) {

View File

@ -20,7 +20,7 @@ if ($action === 'set' && !empty($filename)) {
} elseif ($type === 'video') {
$backgroundStyle = "\n<style>
body {
background: none;
background: transparent;
position: relative;
margin: 0;
padding: 0;
@ -28,7 +28,7 @@ if ($action === 'set' && !empty($filename)) {
}
.video-background {
position: absolute;
position: fixed;
top: 0;
left: 0;
width: 100%;
@ -40,7 +40,7 @@ if ($action === 'set' && !empty($filename)) {
.control-toggle {
position: absolute;
top: 20px;
left: 20px;
right: 20px;
padding: 10px 20px;
background-color: #6f42c1;
color: white;
@ -105,6 +105,7 @@ if ($action === 'set' && !empty($filename)) {
<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";

View File

@ -887,28 +887,25 @@ $razordVersion = getRazordVersion();
<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>
<div class="modal-body">
<div class="mb-4">
<h2 class="mb-3">上传背景图片/视频</h2>
<form method="POST" action="download.php" enctype="multipart/form-data">
<input type="file" class="form-control mb-3" name="imageFile" id="imageFile">
<button type="submit" class="btn btn-success" id="submitBtn" title="PHP上传文件会有大小限制如遇上传失败可以手动上传文件到 /nekobox/assets/Pictures 目录">上传图片/视频</button>
<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>文件名</th>
<th>文件大小</th>
<th>预览</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<h2 class="mb-3">上传的图片/视频文件</h2>
<table class="table table-bordered text-center">
<thead>
<tr>
<th>文件名</th>
<th>文件大小</th>
<th>预览</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<?php
function isImage($file) {
$imageExtensions = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp'];
@ -922,6 +919,16 @@ $razordVersion = getRazordVersion();
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('..', '.'));
@ -930,10 +937,11 @@ $razordVersion = getRazordVersion();
if (is_file($filePath)) {
$fileSize = filesize($filePath);
$fileUrl = '/nekobox/assets/Pictures/' . $file;
$fileNameWithoutPrefix = getFileNameWithoutPrefix($file);
echo "<tr>
<td class='align-middle'>$file</td>
<td class='align-middle'>" . formatFileSize($fileSize) . "</td>
<td class='align-middle'>";
<td class='align-middle' data-label='文件名'>$fileNameWithoutPrefix</td>
<td class='align-middle' data-label='文件大小'>" . formatFileSize($fileSize) . "</td>
<td class='align-middle' data-label='预览'>";
if (isVideo($file)) {
$fileType = strtolower(pathinfo($file, PATHINFO_EXTENSION));
echo "<video width='100' controls>
@ -947,7 +955,8 @@ $razordVersion = getRazordVersion();
}
echo "</td>
<td class='align-middle'>
<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)) {
@ -973,6 +982,128 @@ $razordVersion = getRazordVersion();
</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 = '';
@ -1020,6 +1151,7 @@ function formatFileSize($size) {
}
}
?>
<script>
function setBackground(filename, type, action = 'set') {
if (action === 'set') {

View File

@ -0,0 +1,33 @@
<?php
header("Content-Type: application/json");
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$configFile = "/etc/php.ini";
$configChanges = [
'upload_max_filesize' => '1024M',
'post_max_size' => '1024M',
'max_file_uploads' => '50',
'memory_limit' => '1024M',
'max_execution_time' => '1800',
'max_input_time' => '1800'
];
$configData = file_get_contents($configFile);
foreach ($configChanges as $key => $value) {
$configData = preg_replace("/^$key\s*=\s*.*/m", "$key = $value", $configData);
}
if (file_put_contents($configFile, $configData) !== false) {
shell_exec("/etc/init.d/uhttpd restart > /dev/null 2>&1 &");
shell_exec("/etc/init.d/nginx restart > /dev/null 2>&1 &");
echo json_encode(["status" => "success", "message" => "PHP 配置已更新并重启"]);
} else {
echo json_encode(["status" => "error", "message" => "更新失败,检查权限!"]);
}
} else {
echo json_encode(["status" => "error", "message" => "无效的请求"]);
}
?>