HTML视频审核模型

这是一段HTML代码,实现了本地视频上传和审核状态实时追踪,方便您快速测试审核流程。

```html

<!DOCTYPE html>

<html lang="zh-CN">

<head>

<meta charset="UTF-8" />

<meta name="viewport" content="width=device-width, initial-scale=1" />

<title>视频上传审核</title>

<style>

body {

font-family: -apple-system, "PingFang SC", "Microsoft YaHei", sans-serif;

max-width: 560px;

margin: 60px auto;

padding: 0 20px;

color: #333;

}

h2 { margin-bottom: 24px; }

.box {

border: 2px dashed #d0d7de;

border-radius: 10px;

padding: 28px;

text-align: center;

transition: border-color .2s;

}

.box.dragover { border-color: #1f6feb; background: #f0f6ff; }

inputtype=file { display: none; }

.pick {

display: inline-block;

padding: 9px 22px;

background: #1f6feb;

color: #fff;

border-radius: 6px;

cursor: pointer;

font-size: 14px;

}

.pick:hover { background: #1858c4; }

.filename {

margin-top: 14px;

font-size: 13px;

color: #666;

word-break: break-all;

}

progress {

width: 100%;

height: 10px;

margin-top: 20px;

border-radius: 5px;

display: none;

}

progress::-webkit-progress-bar { background: #eaeef2; border-radius: 5px; }

progress::-webkit-progress-value { background: #1f6feb; border-radius: 5px; transition: width .2s; }

#status {

margin-top: 18px;

font-size: 14px;

min-height: 22px;

line-height: 1.6;

}

.tag {

display: inline-block;

padding: 2px 10px;

border-radius: 20px;

font-size: 12px;

margin-right: 6px;

}

.s-pending { background: #fff8e5; color: #b7791f; }

.s-reviewing { background: #e7f0ff; color: #1f6feb; }

.s-approved { background: #e6f7ec; color: #1a7f37; }

.s-rejected { background: #ffeceb; color: #cf222e; }

.s-failed { background: #f0f0f0; color: #666; }

</style>

</head>

<body>

<h2>上传视频(自动送审)</h2>

<div class="box" id="dropbox">

<label class="pick" for="file">选择视频文件</label>

<input type="file" id="file" accept="video/mp4,video/quicktime,video/webm" />

<div class="filename" id="filename">支持 mp4 / mov / webm,单文件 ≤ 500MB</div>

<progress id="progress" max="100" value="0"></progress>

</div>

<div id="status"></div>

<script>

const STATUS_TEXT = {

pending: '待审核',

reviewing: '审核中',

approved: '审核通过',

rejected: '审核未通过',

failed: '处理失败'

};

const fileInput = document.getElementById('file');

const filenameEl = document.getElementById('filename');

const progressEl = document.getElementById('progress');

const statusEl = document.getElementById('status');

const dropbox = document.getElementById('dropbox');

let pollTimer = null;

/* ---------- 文件选择 ---------- */

fileInput.addEventListener('change', () => {

const file = fileInput.files0;

if (!file) return;

filenameEl.textContent = `{file.name} ({(file.size / 1024 / 1024).toFixed(1)} MB)`;

statusEl.innerHTML = '';

progressEl.style.display = 'none';

progressEl.value = 0;

});

/* ---------- 拖拽上传 ---------- */

'dragenter', 'dragover'.forEach(ev =>

dropbox.addEventListener(ev, e => {

e.preventDefault();

dropbox.classList.add('dragover');

})

);

'dragleave', 'drop'.forEach(ev =>

dropbox.addEventListener(ev, e => {

e.preventDefault();

dropbox.classList.remove('dragover');

})

);

dropbox.addEventListener('drop', e => {

const file = e.dataTransfer.files0;

if (!file) return;

fileInput.files = e.dataTransfer.files;

fileInput.dispatchEvent(new Event('change'));

startUpload();

});

/* ---------- 选择后自动开始上传 ---------- */

fileInput.addEventListener('change', () => {

if (fileInput.files0) startUpload();

});

/* ---------- 上传 ---------- */

function startUpload() {

const file = fileInput.files0;

if (!file) return;

// 前端预校验,减少无效请求

if (!file.type.startsWith('video/')) {

statusEl.innerHTML = '<span class="tag s-rejected">错误</span>请选择视频文件';

return;

}

if (file.size > 500 * 1024 * 1024) {

statusEl.innerHTML = '<span class="tag s-rejected">错误</span>文件超过 500MB';

return;

}

const formData = new FormData();

formData.append('video', file);

const xhr = new XMLHttpRequest();

xhr.open('POST', '/api/videos/upload');

progressEl.style.display = 'block';

statusEl.innerHTML = '<span class="tag s-pending">上传中</span>正在上传文件...';

// 上传进度

xhr.upload.onprogress = e => {

if (e.lengthComputable) {

const percent = Math.round((e.loaded / e.total) * 100);

progressEl.value = percent;

statusEl.innerHTML = `<span class="tag s-pending">上传中</span>${percent}%`;

}

};

xhr.onload = () => {

let res;

try { res = JSON.parse(xhr.responseText); }

catch { return (statusEl.innerHTML = '<span class="tag s-failed">失败</span>响应解析错误'); }

if (xhr.status !== 200 || res.code !== 0) {

statusEl.innerHTML = `<span class="tag s-failed">失败</span>${res.msg || '上传失败'}`;

return;

}

progressEl.value = 100;

statusEl.innerHTML = '<span class="tag s-reviewing">审核中</span>上传成功,正在审核...';

pollStatus(res.data.id);

};

xhr.onerror = () => {

statusEl.innerHTML = '<span class="tag s-failed">失败</span>网络错误,请重试';

};

xhr.ontimeout = () => {

statusEl.innerHTML = '<span class="tag s-failed">失败</span>上传超时';

};

xhr.send(formData);

}

/* ---------- 轮询审核状态 ---------- */

function pollStatus(id) {

clearInterval(pollTimer);

let retries = 0;

const MAX_RETRIES = 150; // 最多轮询 5 分钟

const check = async () => {

if (++retries > MAX_RETRIES) {

clearInterval(pollTimer);

statusEl.innerHTML = '<span class="tag s-failed">超时</span>审核结果查询超时,请稍后刷新';

return;

}

try {

const resp = await fetch(`/api/videos/${id}/status`);

const json = await resp.json();

if (json.code !== 0) return;

const { status, reason } = json.data;

const cls = `s-${status}`;

const text = STATUS_TEXTstatus || status;

let html = `<span class="tag {cls}"\>{text}</span>`;

if (reason) html += `<span style="color:#cf222e">${reason}</span>`;

if (status === 'approved') html += '视频已发布';

if (status === 'rejected') html += '请联系管理员申诉';

statusEl.innerHTML = html;

// 终态则停止轮询

if ('approved', 'rejected', 'failed'.includes(status)) {

clearInterval(pollTimer);

progressEl.style.display = 'none';

}

} catch (err) {

console.warn('轮询失败', err);

}

};

check();

pollTimer = setInterval(check, 2000);

}

</script>

</body>

</html>

```

上传、审核与反馈流程

整个页面围绕"选视频-传视频-看进度-等审核"这条线展开,操作反馈很直接。

· 选择与拖拽:点击"选择视频文件"或直接把视频拖进虚线框,都能触发上传,选中后立刻显示文件名和大小。

· 前端校验:上传前会检查文件类型和大小,只有视频文件且不超过500MB才会继续,避免无效请求。

· 上传进度:进度条实时展示上传百分比,状态标签同步提示"上传中"。

· 审核轮询:上传成功后自动开始每2秒查询一次审核状态,审核通过显示"已发布",未通过会展示原因并提示联系管理员。

· 状态可视:待审核、审核中、通过、拒绝、失败等状态用不同颜色标签区分,一目了然。


优化建议: 可将代码中的后端上传接口地址/api/videos/upload替换为实际服务端地址,并根据需要调整500MB的文件大小限制。

文章仅供参考用。

相关推荐
言乐62 小时前
Python根据无法识别搜索词找出可能输入内容模型
开发语言·python·django·virtualenv·pygame
yl45303 小时前
硫酸泄露处理生产商怎么选才够专业
大数据·人工智能·python
笨笨饿3 小时前
140_AI新手村MCP与Skills是干嘛的
开发语言·人工智能·python·stm32·单片机·嵌入式硬件·物联网
for_ever_love__4 小时前
机器学习入门——手写线性回归与梯度下降
人工智能·python·学习·机器学习·线性回归
打工仔折腾 AI4 小时前
从 Demo 到生产级 Agent:8 个关键设计机制与 Python 实现拆解
java·jvm·人工智能·后端·python·langchain·ai agent 实战
I Am a robert girl4 小时前
当传感器学会“说谎“:拆解可靠性门控的稀疏惯性动捕融合
python·姿态估计·传感器融合·惯性动捕·imu传感器·可靠性门控·可穿戴计算
李航19834 小时前
AI定制柜建模,需要详细的建模规范和标准流程
人工智能·python·计算机视觉·ai·ai编程
沙漠之主5 小时前
Python 教学设计资料:从入门到实战的完整课程方案
爬虫·python
ebiobiz6 小时前
极海 APM32 使用 Nimmake 编译指南
c++·python·单片机·嵌入式硬件·mcu