Files

264 lines
11 KiB
HTML

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="/css/font.css">
<link rel="stylesheet" href="/css/xadmin.css">
<link rel="stylesheet" href="/css/win10ui.css">
<link rel="stylesheet" href="/lib/layui/css/layui.css">
<script type="text/javascript" src="/lib/layui/layui.js" charset="utf-8"></script>
<script type="text/javascript" src="/js/xadmin.js"></script>
<script src="/assets/js/socket/Socket.IO.js"></script>
<script>window.breadcrumbs = [{name: "首页", url: ""},{name: "Termination4", url: ""},{name: "大文件传输"}];</script>
<script src="/js/address.bar.js"></script>
<style>
.task-card {
width: 100px;
height: 100px;
margin: 10px;
display: inline-flex;
flex-direction: column;
justify-content: center;
align-items: center;
border-radius: 4px;
background-color: #f2f2f2;
transition: all 0.3s;
cursor: pointer;
}
.task-card.success {
background-color: #d2e4c4;
border: 1px solid #5fb92f;
}
.task-card.error {
background-color: #f8d7da;
border: 1px solid #dc3545;
}
.task-card .card-index {
font-size: 18px;
font-weight: bold;
}
.task-card .card-status {
font-size: 12px;
margin-top: 5px;
}
.task-container {
margin-top: 20px;
display: flex;
flex-wrap: wrap;
}
.form-row {
display: flex;
align-items: center;
margin-bottom: 15px;
}
.form-row .layui-form-item {
margin-right: 15px;
margin-bottom: 0;
}
.stats-panel {
margin-top: 20px;
padding: 15px;
background-color: #f8f8f8;
border-radius: 4px;
}
</style>
</head>
<body>
<div class="layui-fluid">
<div class="layui-card">
<div class="layui-card-header">大文件分段传输配置</div>
<div class="layui-card-body">
<form class="layui-form" id="DonwLoadForm">
<div class="form-row">
<div class="layui-form-item">
<label class="layui-form-label">工作线程数</label>
<div class="layui-input-inline">
<input type="number" name="thread_count" lay-verify="required" value="4" min="1" max="8" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">单线程工作量(KB)</label>
<div class="layui-input-inline">
<input type="number" name="chunk_size" lay-verify="required" value="1024" min="1" max="10240" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">超时时间(秒)</label>
<div class="layui-input-inline">
<input type="number" name="timeout" lay-verify="required" value="30" min="0.5" max="100" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">重试次数</label>
<div class="layui-input-inline">
<input type="number" name="retry_count" lay-verify="required" value="5" min="0" max="20" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-inline">
<button class="layui-btn" lay-submit lay-filter="formSubmit">开始传输</button>
</div>
</div>
</div>
</form>
<div class="stats-panel" id="statsPanel" style="display: none;">
<div class="layui-row">
<div class="layui-col-md3">
<span>总任务数: </span><span id="totalTasks">0</span>
</div>
<div class="layui-col-md3">
<span>已完成: </span><span id="completedTasks">0</span>
</div>
<div class="layui-col-md3">
<span>失败数: </span><span id="failedTasks">0</span>
</div>
<div class="layui-col-md3">
<span>进度: </span><span id="progress">0%</span>
</div>
</div>
</div>
<div class="task-container" id="taskContainer"></div>
</div>
</div>
</div>
<script>
socket = io("/Termination4SocketIOSpace");
var fileuuid = crypto.randomUUID().replace(/-/g, '');
layui.use(['form', 'layer'], function(){
var form = layui.form;
var layer = layui.layer;
form.on('submit(formSubmit)', function(data){
$("#DonwLoadForm").remove();
var threadCount = parseInt(data.field.thread_count);
var chunkSize = parseInt(data.field.chunk_size);
var timeout = parseInt(data.field.timeout);
var retryCount = parseInt(data.field.retry_count);
console.log(Path);
socket.emit('T4CMDCommand', {
PCMachineGUID: PCMachineGUID,
'work': 'updatefile',
'Command': {
"FileUUID": fileuuid,
"ThreadCount": threadCount,
"ChunkSize": chunkSize,
"Timeout": timeout,
"RetryCount": retryCount,
"Path": Path
}
});
// 这里应该是实际的文件大小获取逻辑
// 模拟一个1GB的文件
Toast.success("文件传输", "文件传输信息已发送,注意不要重复提交");
// 模拟任务更新
// simulateTaskUpdates(totalChunks);
return false;
});
function simulateTaskUpdates(totalChunks) {
var completed = 0;
var failed = 0;
var interval = setInterval(function() {
if(completed + failed >= totalChunks) {
clearInterval(interval);
layer.msg('所有任务已完成!', {icon: 1});
return;
}
var randomIndex = Math.floor(Math.random() * totalChunks);
var card = $(`.task-card[data-index="${randomIndex}"]`);
if(card.attr('data-status') !== 'pending') return;
var isSuccess = Math.random() > 0.1;
if(isSuccess) {
card.addClass('success');
card.attr('data-status', 'success');
card.find('.card-status').text('已完成');
completed++;
} else {
card.addClass('error');
card.attr('data-status', 'error');
card.find('.card-status').text('失败');
failed++;
}
// 更新统计信息
$('#completedTasks').text(completed);
$('#failedTasks').text(failed);
$('#progress').text(Math.round((completed + failed) / totalChunks * 100) + '%');
// 实际应用中应该是通过WebSocket接收更新
if(socket.taskUpdateCallback) {
socket.taskUpdateCallback({
index: randomIndex,
status: isSuccess ? 'success' : 'error',
message: isSuccess ? '下载完成' : '下载失败'
});
}
}, 500);
}
window.completed=0;
window.failed=0;
socket.on(PCMachineGUID+"CMDRUpdateFileReturnBack"+fileuuid, function(data) {
$('#statsPanel').show();
$('#totalTasks').text(data.ChunkCount);
$('#completedTasks').text(0);
$('#failedTasks').text(0);
$('#progress').text('0%');
var taskContainer = $('#taskContainer').empty();
for(var i = 0; i < data.ChunkCount; i++) {
taskContainer.append(`
<div class="task-card" data-index="${i}" data-status="pending">
<div class="card-index">${i+1}</div>
<div class="card-status">等待中</div>
</div>
`);
}
});
socket.on(PCMachineGUID+"CMDRUpdateFileTaskReturnBack"+fileuuid, function(data) {
console.log(data);
var card = $(`.task-card[data-index="${data.Partid}"]`);
$('#completedTasks').text(window.completed);
$('#failedTasks').text(window.failed);
$('#progress').text(Math.round((window.completed+1) / data.ChunkCount * 100) + '%');
if(card.length) {
if(data.status) {
card.addClass('success');
card.attr('data-status', 'success');
card.find('.card-status').text(data.status || '完成');
window.completed++
} else {
card.addClass('error');
card.attr('data-status', 'error');
card.find('.card-status').text(data.status || '失败');
window.failed++
}
}
if(data.Last){
layer.msg('所有任务已完成!', {icon: 1});
Toast.success("文件传输", "所有任务已完成");
}
});
function DownloadDirectly(url, fileName) {
const link = document.createElement('a');
link.href = url;
link.download = fileName || url.split('/').pop();
link.click();
}
socket.on(PCMachineGUID+"CMDRDownloadFile"+fileuuid, (message) => {
console.log("CMDRDownloadFile", message);
DownloadDirectly(message.url, message.filename.substring(message.filename.lastIndexOf("/") + 1));
});
});
</script>
</body>
</html>