MissAV-Download/docker/html/home.html
2025-11-07 13:16:09 +08:00

480 lines
14 KiB
HTML

<!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="https://cdn.jsdelivr.net/npm/layui@2.9.6/dist/css/layui.min.css">
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
background-color: #f0f2f5;
color: #333;
line-height: 1.6;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 20px;
}
.task-manager {
background: #fff;
border-radius: 10px;
box-shadow: 0 2px 12px rgba(0, 0, 150, 0.1);
overflow: hidden;
}
.task-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 20px;
background: linear-gradient(135deg, #1e6fde 0%, #0d5bc2 100%);
color: white;
}
.task-title {
font-size: 20px;
font-weight: bold;
}
.add-btn {
background: rgba(255, 255, 255, 0.2);
color: white;
border-radius: 50%;
width: 40px;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: all 0.3s;
border: none;
}
.add-btn:hover {
background: rgba(255, 255, 255, 0.3);
transform: scale(1.05);
}
.task-list {
padding: 10px 0;
}
.task-item {
display: flex;
align-items: center;
padding: 15px 20px;
border-bottom: 1px solid #f0f2ff;
transition: background 0.3s;
}
.task-item:hover {
background: #fafbff;
}
.task-item:last-child {
border-bottom: none;
}
.file-info {
flex: 2;
display: flex;
align-items: center;
}
.file-icon {
width: 36px;
height: 36px;
border-radius: 6px;
background: #e6f7ff;
display: flex;
align-items: center;
justify-content: center;
margin-right: 12px;
color: #1e6fde;
}
.file-name {
color: #333;
font-weight: 500;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.progress-container {
flex: 3;
padding: 0 15px;
}
.progress-info {
flex: 1;
text-align: center;
color: #1e6fde;
font-weight: 500;
min-width: 60px;
}
.task-status {
flex: 1;
text-align: center;
padding: 6px 12px;
border-radius: 12px;
font-size: 12px;
font-weight: bold;
min-width: 70px;
}
.status-completed {
background: #e6f7ff;
color: #1890ff;
}
.status-processing {
background: #f0f6ff;
color: #1e6fde;
}
.empty-state {
text-align: center;
padding: 40px 20px;
color: #999;
}
.empty-state i {
font-size: 50px;
margin-bottom: 15px;
color: #d9d9d9;
}
.loading-state {
text-align: center;
padding: 30px 20px;
color: #1e6fde;
}
.error-state {
text-align: center;
padding: 40px 20px;
color: #ff4d4f;
}
.error-state i {
font-size: 50px;
margin-bottom: 15px;
color: #ff4d4f;
}
.last-update {
text-align: right;
padding: 10px 20px;
font-size: 12px;
color: #999;
border-top: 1px solid #f0f2ff;
}
/* 响应式设计 */
@media (max-width: 768px) {
.task-item {
flex-direction: column;
align-items: flex-start;
padding: 15px;
}
.file-info {
width: 100%;
margin-bottom: 10px;
}
.progress-container {
width: 100%;
padding: 0;
margin-bottom: 10px;
}
.progress-info {
text-align: left;
margin-bottom: 10px;
}
.task-status {
align-self: flex-end;
margin-top: 5px;
}
.task-header {
padding: 15px;
}
.task-title {
font-size: 18px;
}
.last-update {
text-align: center;
}
}
/* 进度条自定义样式 */
.layui-progress {
margin: 5px 0;
}
.layui-progress-bar {
background: linear-gradient(90deg, #1e6fde, #4a90e2);
border-radius: 1px;
transition: width 0.5s ease-in-out;
}
/* 更新动画 */
.progress-updating {
animation: pulse 1s infinite;
}
@keyframes pulse {
0% {
opacity: 1;
}
50% {
opacity: 0.7;
}
100% {
opacity: 1;
}
}
</style>
</head>
<body>
<div class="container">
<div class="task-manager">
<div class="task-header">
<div class="task-title">任务列表</div>
<button class="add-btn" id="addTask">
<i class="layui-icon">&#xe654;</i>
</button>
</div>
<div class="task-list" id="taskList">
<div class="loading-state">
<i class="layui-icon layui-icon-loading layui-anim layui-anim-rotate"></i>
<div>正在加载任务数据...</div>
</div>
</div>
<div class="last-update" id="lastUpdate">
最后更新: --
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/layui@2.9.6/dist/layui.min.js"></script>
<script>
layui.use(['element', 'jquery'], function () {
var element = layui.element;
var $ = layui.$;
var updateInterval;
var currentTasks = [];
// 从API获取任务数据
function fetchTasks() {
return new Promise((resolve, reject) => {
// 检查token是否存在
if (!localStorage.getItem('Authorization')) {
reject(new Error('Token不存在'));
return;
}
// 发起带token的请求
fetch('/api/all-task', {
method: 'GET',
headers: {
'Authorization': localStorage.getItem('Authorization'),
'Content-Type': 'application/json'
}
})
.then(response => {
if (response.status === 401) {
throw new Error('认证失败');
}
if (!response.ok) {
throw new Error('网络响应不正常');
}
return response.json();
})
.then(data => {
resolve(data);
})
.catch(error => {
console.error('获取任务数据失败:', error);
// 如果是认证错误,已经处理过了,这里处理其他错误
if (error.message !== '认证失败') {
$('#taskList').html(`
<div class="error-state">
<i class="layui-icon">&#xe69c;</i>
<div>获取数据失败: ${error.message}</div>
<button class="layui-btn layui-btn-primary layui-btn-sm" style="margin-top: 10px;" onclick="initTaskList()">重试</button>
</div>
`);
}
resolve([]);
});
});
}
// 渲染任务列表
function renderTaskList(tasks) {
tasks = tasks.data;
var taskHtml = '';
if (tasks.length === 0) {
taskHtml = `
<div class="empty-state">
<i class="layui-icon">&#xe6a5;</i>
<div>暂无任务</div>
</div>
`;
} else {
tasks.forEach(function (task) {
var statusText = task.status === 'completed' ? '已完成' : '进行中';
var statusClass = task.status === 'completed' ? 'status-completed' : 'status-processing';
var progressPercent = Math.round(task.progress * 100) + '%';
taskHtml += `
<div class="task-item" data-id="${task.id}">
<div class="file-info">
<div class="file-name">${task.fileName}</div>
</div>
<div class="progress-container">
<div class="layui-progress">
<div class="layui-progress-bar" lay-percent="${progressPercent}"></div>
</div>
</div>
<div class="progress-info">${progressPercent}</div>
<div class="task-status ${statusClass}">${statusText}</div>
</div>
`;
});
}
$('#taskList').html(taskHtml);
element.render('progress');
}
// 更新任务进度(不重新渲染整个列表)
function updateTaskProgress(tasks) {
tasks = tasks.data;
tasks.forEach(function () {
var taskItem = $(`.task-item[data-id="${task.id}"]`);
if (taskItem.length > 0) {
var progressPercent = Math.round(task.progress * 100) + '%';
var statusText = task.status === 'completed' ? '已完成' : '进行中';
var statusClass = task.status === 'completed' ? 'status-completed' : 'status-processing';
// 更新进度条
var progressBar = taskItem.find('.layui-progress-bar');
progressBar.attr('lay-percent', progressPercent);
// 添加更新动画
progressBar.addClass('progress-updating');
// 使用动画更新进度
setTimeout(function () {
progressBar.css('width', progressPercent);
progressBar.removeClass('progress-updating');
}, 100);
// 更新进度文本
taskItem.find('.progress-info').text(progressPercent);
// 更新状态
var statusElement = taskItem.find('.task-status');
statusElement.text(statusText);
statusElement.removeClass('status-completed status-processing').addClass(statusClass);
}
});
}
// 初始化任务列表
function initTaskList() {
fetchTasks().then(tasks => {
currentTasks = tasks;
renderTaskList(tasks);
// 启动定时更新
startAutoUpdate();
}).catch(error => {
console.error('初始化任务列表失败:', error);
});
}
// 启动自动更新
function startAutoUpdate() {
// 清除现有定时器
if (updateInterval) {
clearInterval(updateInterval);
}
// 每5秒更新一次
updateInterval = setInterval(function () {
fetchTasks().then(tasks => {
currentTasks = tasks;
updateTaskProgress(tasks);
});
}, 5000);
}
// 添加新任务
$('#addTask').on('click', function () {
layer.prompt({
title: '请输入URL',
formType: 0,
}, function (url, index) {
layer.close(index);
// 获取token
const token = localStorage.getItem('Authorization');
// 调用检查接口
fetch(`/api/check/${encodeURIComponent(url)}`, {
method: 'GET',
headers: {
'Authorization': token,
'Content-Type': 'application/json'
}
})
.then(response => {
console.log('响应状态:', response.status);
console.log('响应头:', response.headers);
if (!response.ok) {
throw new Error('检查URL失败');
}
return response.json();
})
.then(data => {
console.log('接口返回数据:', data);
// 重新加载任务列表
// initTaskList();
})
.catch(error => {
console.log('错误信息:', error);
layer.msg('添加任务失败: ' + error.message);
});
});
});
initTaskList();
});
</script>
</body>
</html>