初始化版本
This commit is contained in:
131
upload.php
Normal file
131
upload.php
Normal file
@@ -0,0 +1,131 @@
|
||||
<?php
|
||||
// 投稿页面:允许用户上传视频,上传内容进入待审核目录 videos_pending
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>投稿视频</title>
|
||||
<link rel="stylesheet" href="assets/style.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="page">
|
||||
<header class="menu">
|
||||
<div class="menu__logo">投稿</div>
|
||||
<nav aria-label="主菜单">
|
||||
<ul class="menu__nav">
|
||||
<li><a class="menu__link" href="index.php">返回首页</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
</header>
|
||||
<main class="upload-container" aria-label="投稿表单">
|
||||
<h1>上传你想分享的视频</h1>
|
||||
<form class="upload-grid video" action="api/upload_video.php" method="post" enctype="multipart/form-data">
|
||||
<div class="field">
|
||||
<label>选择视频文件(支持 mp4 / webm / mov)</label>
|
||||
<div id="dropzone" class="dropzone" role="button" aria-label="拖拽或点击选择文件">
|
||||
拖拽文件到此处,或点击选择文件
|
||||
</div>
|
||||
<input id="videoFile" class="hidden-input" type="file" name="video" accept="video/mp4,video/webm,video/quicktime" required />
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>标题(可选)</label>
|
||||
<input id="titleInput" type="text" name="title" placeholder="给你的投稿起个标题" />
|
||||
<div class="actions">
|
||||
<button class="btn" type="submit">提交投稿</button>
|
||||
<a href="review.php" style="font-size:12px;color:#666;">管理员审核入口</a>
|
||||
</div>
|
||||
</div>
|
||||
<aside class="card">
|
||||
<video id="preview" class="video-preview" controls style="display:none"></video>
|
||||
<div id="meta" class="meta"></div>
|
||||
<div id="errors" class="errors"></div>
|
||||
</aside>
|
||||
<p class="tips">说明:投稿后文件会进入“待审核”队列,管理员审核通过后才会出现在播放列表中。单个视频大小限制:50MB。</p>
|
||||
</form>
|
||||
</main>
|
||||
</div>
|
||||
<script>
|
||||
const dropzone = document.getElementById('dropzone');
|
||||
const fileInput = document.getElementById('videoFile');
|
||||
const preview = document.getElementById('preview');
|
||||
const meta = document.getElementById('meta');
|
||||
const errors = document.getElementById('errors');
|
||||
const titleInput = document.getElementById('titleInput');
|
||||
|
||||
const allowedExt = ['mp4','webm','mov'];
|
||||
const SIZE_LIMIT = 50 * 1024 * 1024; // 50MB
|
||||
|
||||
function formatSize(bytes){
|
||||
if (bytes >= 1024*1024*1024) return (bytes/1024/1024/1024).toFixed(2) + ' GB';
|
||||
if (bytes >= 1024*1024) return (bytes/1024/1024).toFixed(2) + ' MB';
|
||||
if (bytes >= 1024) return (bytes/1024).toFixed(2) + ' KB';
|
||||
return bytes + ' B';
|
||||
}
|
||||
|
||||
function setFile(file){
|
||||
if (!file) return;
|
||||
// 填充到 input
|
||||
const dt = new DataTransfer();
|
||||
dt.items.add(file);
|
||||
fileInput.files = dt.files;
|
||||
|
||||
// 校验扩展名
|
||||
const name = file.name || '';
|
||||
const ext = name.split('.').pop().toLowerCase();
|
||||
errors.textContent = '';
|
||||
if (!allowedExt.includes(ext)) {
|
||||
errors.textContent = '仅支持 mp4 / webm / mov 格式文件';
|
||||
fileInput.value = '';
|
||||
preview.style.display = 'none';
|
||||
preview.removeAttribute('src');
|
||||
meta.textContent = '';
|
||||
return;
|
||||
}
|
||||
|
||||
// 校验大小
|
||||
if (file.size > SIZE_LIMIT) {
|
||||
errors.textContent = '文件过大:超过 50MB 限制';
|
||||
fileInput.value = '';
|
||||
preview.style.display = 'none';
|
||||
preview.removeAttribute('src');
|
||||
meta.textContent = '';
|
||||
return;
|
||||
}
|
||||
|
||||
// 自动填充标题
|
||||
if (!titleInput.value) {
|
||||
const base = name.replace(/\.[^.]+$/, '');
|
||||
titleInput.value = base;
|
||||
}
|
||||
|
||||
// 预览视频
|
||||
const url = URL.createObjectURL(file);
|
||||
preview.src = url;
|
||||
preview.style.display = 'block';
|
||||
preview.load();
|
||||
meta.textContent = '文件:' + name + ',大小:' + formatSize(file.size) + (file.type ? ',类型:' + file.type : '');
|
||||
preview.onloadedmetadata = () => {
|
||||
const d = preview.duration;
|
||||
if (isFinite(d) && d > 0) {
|
||||
meta.textContent += ',时长:' + Math.round(d) + ' 秒';
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
dropzone.addEventListener('click', () => fileInput.click());
|
||||
dropzone.addEventListener('dragover', (e) => { e.preventDefault(); dropzone.classList.add('dragging'); });
|
||||
dropzone.addEventListener('dragleave', () => dropzone.classList.remove('dragging'));
|
||||
dropzone.addEventListener('drop', (e) => {
|
||||
e.preventDefault(); dropzone.classList.remove('dragging');
|
||||
const file = e.dataTransfer.files?.[0];
|
||||
setFile(file);
|
||||
});
|
||||
fileInput.addEventListener('change', () => {
|
||||
const file = fileInput.files?.[0];
|
||||
setFile(file);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user