<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>OSS多文件上传</title>
    <link rel="stylesheet" href="/lib/layui-v2.6.3/css/layui.css" media="all">
    <!-- 引入 font-aswsome 相关资源 -->
    <link rel="stylesheet" href="/lib/font-awesome-4.7.0/css/font-awesome.min.css" media="all">
    <style>
        .upload-container {
            padding: 30px;
            max-width: 800px;
            margin: 50px auto;
            background: #fff;
            border-radius: 8px;
            box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
        }
        .drag-area {
            height: 300px;
            border: 2px dashed #c0c4cc;
            border-radius: 6px;
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            text-align: center;
            cursor: pointer;
            transition: all 0.3s ease;
            background: #fafafa;
            margin-bottom: 20px;
        }
        .drag-area:hover {
            border-color: #409eff;
            background: #ecf5ff;
        }
        .drag-area.active {
            border-color: #409eff;
            background: #ecf5ff;
            transform: scale(0.98);
        }
        .drag-area i {
            font-size: 60px;
            color: #409eff;
            margin-bottom: 20px;
        }
        .drag-area p {
            margin: 5px 0;
            color: #666;
            font-size: 14px;
        }
        .drag-area .tip {
            color: #999;
            font-size: 12px;
            margin-top: 10px;
        }
        .upload-list {
            margin-top: 20px;
        }
        .upload-item {
            display: flex;
            align-items: center;
            padding: 12px;
            background: #f8f9fa;
            border-radius: 6px;
            margin-bottom: 10px;
            border: 1px solid #e9ecef;
        }
        .upload-item.success {
            background: #f0f9eb;
            border-color: #e1f3d8;
        }
        .upload-item.error {
            background: #fef0f0;
            border-color: #fde2e2;
        }
        .upload-item .file-icon {
            font-size: 24px;
            color: #409eff;
            margin-right: 12px;
        }
        .upload-item .file-info {
            flex: 1;
        }
        .upload-item .file-name {
            font-size: 14px;
            font-weight: 500;
            margin-bottom: 4px;
            word-break: break-all;
        }
        .upload-item .file-size {
            font-size: 12px;
            color: #909399;
        }
        .upload-item .progress {
            width: 150px;
            margin-right: 15px;
        }
        .upload-item .status {
            min-width: 70px;
            text-align: center;
            font-size: 12px;
            padding: 4px 10px;
            border-radius: 12px;
        }
        .upload-item .status.waiting {
            background: #e6e6e6;
            color: #666;
        }
        .upload-item .status.uploading {
            background: #e8f4fe;
            color: #409eff;
        }
        .upload-item .status.success {
            background: #f0f9eb;
            color: #67c23a;
        }
        .upload-item .status.error {
            background: #fef0f0;
            color: #f56c6c;
        }
        .upload-stats {
            margin-top: 20px;
            padding: 10px;
            background: #f8f9fa;
            border-radius: 6px;
            font-size: 14px;
        }
        .empty-state {
            text-align: center;
            padding: 40px 0;
            color: #909399;
        }
        .empty-state i {
            font-size: 50px;
            margin-bottom: 15px;
            color: #c0c4cc;
        }
        h2 {
            text-align: center;
            margin-bottom: 30px;
            color: #333;
        }
    </style>
</head>
<body>
<div class="upload-container">
    <h2>拖拽文件上传到OSS</h2>

    <!-- 拖拽区域 -->
    <div class="drag-area" id="dragArea">
        <i class="layui-icon"></i>
        <p>将文件拖拽到此处上传</p>
        <p>支持多个文件，最大1GB</p>
        <p class="tip">支持图片、文档、压缩包等格式</p>
    </div>

    <!-- 上传列表 -->
    <div class="upload-list" id="uploadList">
        <div class="empty-state" id="emptyState">
            <i class="layui-icon"></i>
            <p>暂无文件，请拖拽文件到上方区域</p>
        </div>
    </div>

    <!-- 统计信息 -->
    <div class="upload-stats" id="uploadStats" style="display: none;">
        <span id="statsText"></span>
    </div>
</div>

<script src="/lib/layui-v2.6.3/layui.js" charset="utf-8"></script>
<script src="/js/lay-config.js?v=1.0.4" charset="utf-8"></script>
<script src="/js/jquery-1.10.2.min.js" charset="utf-8"></script>
<script>
    // 使用模块加载器方式
    layui.use(['table','upload', 'element', 'layer'], function () {
        let $ = layui.jquery,
            form = layui.form,
            dropdown = layui.dropdown,
            upload = layui.upload,
            element = layui.element,
            table = layui.table;

        // 存储所有上传任务
        var uploadTasks = [];
        var activeUploads = 0;
        var maxConcurrent = 3; // 最大同时上传数

        // 初始化拖拽区域
        initDragArea();

        // 更新统计信息
        function updateStats() {
            var total = uploadTasks.length;
            var success = uploadTasks.filter(t => t.status === 'success').length;
            var error = uploadTasks.filter(t => t.status === 'error').length;
            var uploading = uploadTasks.filter(t => t.status === 'uploading').length;
            var waiting = uploadTasks.filter(t => t.status === 'waiting').length;

            var statsText = '总计: ' + total + ' 个文件 | ';
            statsText += '成功: ' + success + ' | ';
            statsText += '失败: ' + error + ' | ';
            if (uploading > 0) statsText += '上传中: ' + uploading + ' | ';
            if (waiting > 0) statsText += '等待中: ' + waiting;

            $('#statsText').text(statsText);

            if (total > 0) {
                $('#uploadStats').show();
            } else {
                $('#uploadStats').hide();
            }
        }

        // 渲染文件列表
        function renderFileList() {
            var html = '';

            if (uploadTasks.length === 0) {
                $('#emptyState').show();
                updateStats();
                return;
            }

            $('#emptyState').hide();

            uploadTasks.forEach(function(task, index) {
                var statusClass = task.status || 'waiting';
                var statusText = '';

                switch(statusClass) {
                    case 'waiting':
                        statusText = '等待上传';
                        break;
                    case 'uploading':
                        statusText = '上传中';
                        break;
                    case 'success':
                        statusText = '上传成功';
                        break;
                    case 'error':
                        statusText = '上传失败';
                        break;
                }

                var progressBar = '';
                if (statusClass === 'uploading') {
                    progressBar = '<div class="layui-progress progress" lay-filter="progress-' + task.id + '" style="margin: 5px 0;">' +
                        '<div class="layui-progress-bar" lay-percent="' + task.percent + '%"></div>' +
                        '</div>';
                }

                html += '<div class="upload-item ' + statusClass + '" data-id="' + task.id + '">' +
                    '<div class="file-icon layui-icon">&#xe655;</div>' +
                    '<div class="file-info">' +
                    '<div class="file-name">' + task.name + '</div>' +
                    '<div class="file-size">' + formatFileSize(task.size) + '</div>' +
                    progressBar +
                    '</div>' +
                    '<div class="status ' + statusClass + '">' + statusText + '</div>' +
                    '</div>';
            });

            $('#uploadList').html(html + '<div class="empty-state" id="emptyState" style="display:none;">' +
                '<i class="layui-icon"></i><p>暂无文件，请拖拽文件到上方区域</p></div>');

            // 渲染进度条
            uploadTasks.forEach(function(task) {
                if (task.status === 'uploading') {
                    element.progress('progress-' + task.id, task.percent + '%');
                }
            });

            updateStats();
        }

        // 初始化拖拽区域
        function initDragArea() {
            var dragArea = $('#dragArea')[0];

            // 拖拽进入
            dragArea.addEventListener('dragover', function(e) {
                e.preventDefault();
                e.stopPropagation();
                $(this).addClass('active');
            });

            // 拖拽离开
            dragArea.addEventListener('dragleave', function(e) {
                e.preventDefault();
                e.stopPropagation();
                $(this).removeClass('active');
            });

            // 拖拽释放
            dragArea.addEventListener('drop', function(e) {
                e.preventDefault();
                e.stopPropagation();
                $(this).removeClass('active');

                var files = e.dataTransfer.files;
                if (!files || files.length === 0) {
                    return;
                }

                handleFiles(files);
            });

            // 点击选择文件（可选）
            dragArea.addEventListener('click', function() {
                var input = document.createElement('input');
                input.type = 'file';
                input.multiple = true;
                input.style.display = 'none';

                input.addEventListener('change', function(e) {
                    if (this.files && this.files.length > 0) {
                        handleFiles(this.files);
                    }
                });

                document.body.appendChild(input);
                input.click();
                document.body.removeChild(input);
            });
        }

        // 处理文件
        function handleFiles(files) {
            var validFiles = [];

            for (var i = 0; i < files.length; i++) {
                var file = files[i];

                // 检查文件大小
                if (file.size > 1024 * 1024 * 1024) {
                    layer.msg('文件 "' + file.name + '" 超过1GB限制', {icon: 2});
                    continue;
                }

                // 检查是否重复
                var isDuplicate = uploadTasks.some(function(task) {
                    return task.name === file.name && task.size === file.size;
                });

                if (isDuplicate) {
                    layer.msg('文件 "' + file.name + '" 已存在', {icon: 3});
                    continue;
                }

                let extension = file.name.split('.').pop(); //

                let arr = ["jpeg","jpg","ppt","png","mp4","mp3","pdf","xlsx","docx","zip","7z","emmx"];

                if ($.inArray(extension, arr) == -1) {
                    layer.msg('文件 "' + file.name + '" 格式不支持', {icon: 3});
                    continue;
                }

                validFiles.push(file);
            }

            if (validFiles.length === 0) {
                return;
            }

            // 添加到上传队列
            validFiles.forEach(function(file) {
                var task = {
                    id: 'file_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9),
                    file: file,
                    name: file.name,
                    size: file.size,
                    percent: 0,
                    status: 'waiting',
                    url: ''
                };

                uploadTasks.push(task);
            });

            renderFileList();

            // 开始上传
            startUpload();
        }

        // 开始上传
        function startUpload() {
            // 检查是否有等待上传的文件且未达到并发上限
            var waitingTasks = uploadTasks.filter(function(task) {
                return task.status === 'waiting' || task.status === 'error';
            });

            if (waitingTasks.length === 0 || activeUploads >= maxConcurrent) {
                return;
            }

            // 获取上传凭证
            $.ajax({
                url: '/cloud/oss/policy',
                type: 'GET',
                data: {
                    dir: 'uploads/' + new Date().getFullYear() + '-' +
                        ('0' + (new Date().getMonth() + 1)).slice(-2)
                },
                beforeSend: function() {
                    layer.msg('获取上传凭证...', {icon: 16, time: 2000});
                },
                success: function(res) {
                    layer.closeAll();

                    if (res.code === 200) {
                        var policy = res.data;

                        // 上传等待中的文件
                        for (var i = 0; i < Math.min(maxConcurrent - activeUploads, waitingTasks.length); i++) {
                            uploadFile(waitingTasks[i], policy);
                        }
                    } else {
                        layer.msg('获取上传凭证失败: ' + res.msg, {icon: 2});
                    }
                },
                error: function() {
                    layer.closeAll();
                    layer.msg('网络错误，请检查服务', {icon: 2});
                }
            });
        }

        // 上传单个文件
        function uploadFile(task, policy) {
            if (activeUploads >= maxConcurrent) {
                return;
            }

            task.status = 'uploading';
            task.percent = 0;
            activeUploads++;

            renderFileList();

            // 创建FormData
            var formData = new FormData();

            // 处理key
            var key = policy.key;
            if (key.indexOf('${filename}') !== -1) {
                // 对文件名进行URL编码
                var encodedFilename = encodeURIComponent(task.name);
                key = key.replace('${filename}', encodedFilename);
            }

            formData.append('key', key);
            formData.append('policy', policy.policy);
            formData.append('OSSAccessKeyId', policy.OSSAccessKeyId);
            formData.append('signature', policy.signature);
            formData.append('success_action_status', '200');
            formData.append('file', task.file);

            // XMLHttpRequest上传
            var xhr = new XMLHttpRequest();

            xhr.upload.onprogress = function(e) {
                if (e.lengthComputable) {
                    var percent = Math.round((e.loaded / e.total) * 100);
                    task.percent = percent;
                    renderFileList();
                }
            };

            xhr.onload = function() {
                activeUploads--;

                if (xhr.status === 200) {
                    task.status = 'success';
                    task.url = policy.host + '/' + key;

                    window.parent.parentOpen(task.name,task.url,'[[${id}]]',task.size);
                    // 继续上传其他文件
                    setTimeout(startUpload, 500);
                } else {
                    task.status = 'error';
                    console.error('上传失败:', xhr.status, xhr.responseText);

                    // 尝试解析错误信息
                    try {
                        var parser = new DOMParser();
                        var xmlDoc = parser.parseFromString(xhr.responseText, "text/xml");
                        var errorCode = xmlDoc.getElementsByTagName('Code')[0].textContent;
                        var errorMsg = xmlDoc.getElementsByTagName('Message')[0].textContent;
                        console.error('OSS错误:', errorCode, errorMsg);

                        if (errorCode === 'AccessDenied') {
                            layer.msg('上传被拒绝，请刷新页面重试', {icon: 2});
                        }
                    } catch (e) {
                        // 忽略解析错误
                    }

                    // 继续上传其他文件
                    setTimeout(startUpload, 1000);
                }

                renderFileList();
            };

            xhr.onerror = function() {
                activeUploads--;
                task.status = 'error';
                console.error('网络错误:', task.name);
                renderFileList();

                // 继续上传其他文件
                setTimeout(startUpload, 1000);
            };

            xhr.open('POST', policy.host);
            xhr.send(formData);
        }

        // 格式化文件大小
        function formatFileSize(bytes) {
            if (bytes === 0) return '0 B';
            var k = 1024;
            var sizes = ['B', 'KB', 'MB', 'GB'];
            var i = Math.floor(Math.log(bytes) / Math.log(k));
            return (bytes / Math.pow(k, i)).toFixed(2) + ' ' + sizes[i];
        }

        // 全局的$函数（简写）
        window.$ = function(selector) {
            if (selector.startsWith('#')) {
                return document.getElementById(selector.substring(1));
            }
            return document.querySelectorAll(selector);
        };
    });
</script>
</body>
</html>
