1101 lines
47 KiB
HTML
1101 lines
47 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>中国烟草AI合同及卷宗审核系统 - 上传文档</title>
|
|
<link href="https://cdnjs.cloudflare.com/ajax/libs/remixicon/2.5.0/remixicon.css" rel="stylesheet">
|
|
<link href="https://cdnjs.cloudflare.com/ajax/libs/tailwindcss/2.2.19/tailwind.min.css" rel="stylesheet">
|
|
<!-- <link href="https://cdn.jsdelivr.net/npm/remixicon@2.5.0/fonts/remixicon.css" rel="stylesheet">
|
|
<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet"> -->
|
|
<!-- 引入外部CSS文件 -->
|
|
<link href="main.css" rel="stylesheet">
|
|
<style>
|
|
.upload-area {
|
|
border: 2px dashed #e0e0e0;
|
|
border-radius: 8px;
|
|
padding: 40px;
|
|
text-align: center;
|
|
background-color: #fafafa;
|
|
transition: all 0.3s;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.upload-area:hover, .upload-area.drag-over {
|
|
border-color: var(--primary-color);
|
|
background-color: rgba(0, 104, 74, 0.05);
|
|
}
|
|
|
|
.upload-icon {
|
|
font-size: 48px;
|
|
color: #bdbdbd;
|
|
margin-bottom: 16px;
|
|
}
|
|
|
|
.upload-area:hover .upload-icon, .upload-area.drag-over .upload-icon {
|
|
color: var(--primary-color);
|
|
}
|
|
|
|
.file-list {
|
|
margin-top: 24px;
|
|
}
|
|
|
|
.file-item {
|
|
display: flex;
|
|
align-items: center;
|
|
padding: 12px;
|
|
border: 1px solid #f0f0f0;
|
|
border-radius: 4px;
|
|
margin-bottom: 12px;
|
|
background-color: white;
|
|
}
|
|
|
|
.file-item:hover {
|
|
background-color: #f9f9f9;
|
|
}
|
|
|
|
.file-icon {
|
|
font-size: 24px;
|
|
margin-right: 12px;
|
|
}
|
|
|
|
.file-info {
|
|
flex: 1;
|
|
}
|
|
|
|
.file-name {
|
|
font-weight: 500;
|
|
margin-bottom: 4px;
|
|
}
|
|
|
|
.file-meta {
|
|
font-size: 12px;
|
|
color: #666;
|
|
}
|
|
|
|
.file-size {
|
|
margin-right: 16px;
|
|
}
|
|
|
|
.progress-bar {
|
|
height: 4px;
|
|
background-color: #f0f0f0;
|
|
border-radius: 2px;
|
|
margin-top: 8px;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.progress-bar-inner {
|
|
height: 100%;
|
|
background-color: var(--primary-color);
|
|
border-radius: 2px;
|
|
transition: width 0.3s;
|
|
}
|
|
|
|
.file-actions {
|
|
display: flex;
|
|
align-items: center;
|
|
}
|
|
|
|
.file-actions button {
|
|
margin-left: 8px;
|
|
}
|
|
|
|
.test-document-switch {
|
|
display: flex;
|
|
align-items: center;
|
|
margin-top: 10px;
|
|
}
|
|
|
|
.switch {
|
|
position: relative;
|
|
display: inline-block;
|
|
width: 40px;
|
|
height: 20px;
|
|
margin-right: 8px;
|
|
}
|
|
|
|
.switch input {
|
|
opacity: 0;
|
|
width: 0;
|
|
height: 0;
|
|
}
|
|
|
|
.slider {
|
|
position: absolute;
|
|
cursor: pointer;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
background-color: #ccc;
|
|
border-radius: 20px;
|
|
transition: .3s;
|
|
}
|
|
|
|
.slider:before {
|
|
position: absolute;
|
|
content: "";
|
|
height: 16px;
|
|
width: 16px;
|
|
left: 2px;
|
|
bottom: 2px;
|
|
background-color: white;
|
|
border-radius: 50%;
|
|
transition: .3s;
|
|
}
|
|
|
|
input:checked + .slider {
|
|
background-color: var(--primary-color);
|
|
}
|
|
|
|
input:checked + .slider:before {
|
|
transform: translateX(20px);
|
|
}
|
|
|
|
/* 文件预览功能样式 */
|
|
.preview-modal {
|
|
display: none;
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
background-color: rgba(0, 0, 0, 0.7);
|
|
z-index: 1000;
|
|
justify-content: center;
|
|
align-items: center;
|
|
}
|
|
|
|
.preview-content {
|
|
background-color: white;
|
|
border-radius: 8px;
|
|
width: 90%;
|
|
max-width: 1000px;
|
|
height: 85%;
|
|
overflow: hidden;
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.preview-header {
|
|
padding: 16px;
|
|
border-bottom: 1px solid #f0f0f0;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
}
|
|
|
|
.preview-body {
|
|
flex: 1;
|
|
overflow: auto;
|
|
padding: 0;
|
|
}
|
|
|
|
.preview-iframe {
|
|
width: 100%;
|
|
height: 100%;
|
|
border: none;
|
|
}
|
|
|
|
.preview-footer {
|
|
padding: 12px 16px;
|
|
border-top: 1px solid #f0f0f0;
|
|
text-align: right;
|
|
}
|
|
|
|
/* 文件编辑按钮样式 */
|
|
.edit-filename {
|
|
cursor: pointer;
|
|
color: var(--primary-color);
|
|
margin-left: 8px;
|
|
font-size: 14px;
|
|
}
|
|
|
|
.edit-filename:hover {
|
|
text-decoration: underline;
|
|
}
|
|
|
|
/* 批量操作样式 */
|
|
.batch-actions {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
margin-bottom: 16px;
|
|
padding: 8px 12px;
|
|
background-color: #f8f9fa;
|
|
border-radius: 4px;
|
|
border: 1px solid #f0f0f0;
|
|
}
|
|
|
|
/* 更多上传设置 */
|
|
.advanced-options {
|
|
margin-top: 16px;
|
|
}
|
|
|
|
.advanced-options-toggle {
|
|
cursor: pointer;
|
|
color: var(--primary-color);
|
|
font-size: 14px;
|
|
display: inline-flex;
|
|
align-items: center;
|
|
}
|
|
|
|
.advanced-options-toggle i {
|
|
transition: transform 0.3s;
|
|
}
|
|
|
|
.advanced-options-toggle.open i {
|
|
transform: rotate(180deg);
|
|
}
|
|
|
|
.advanced-options-content {
|
|
display: none;
|
|
margin-top: 12px;
|
|
padding: 12px;
|
|
border: 1px solid #f0f0f0;
|
|
border-radius: 4px;
|
|
background-color: #f9f9f9;
|
|
}
|
|
|
|
/* 上传失败状态样式 */
|
|
.file-status.error {
|
|
color: #f5222d;
|
|
}
|
|
|
|
.retry-btn {
|
|
color: var(--primary-color);
|
|
cursor: pointer;
|
|
}
|
|
|
|
.retry-btn:hover {
|
|
text-decoration: underline;
|
|
}
|
|
|
|
/* 上传完成操作按钮组 */
|
|
.upload-complete-actions {
|
|
display: none;
|
|
margin-top: 20px;
|
|
text-align: center;
|
|
}
|
|
|
|
/* 提示框样式 */
|
|
.alert {
|
|
padding: 12px 16px;
|
|
border-radius: 4px;
|
|
margin-bottom: 16px;
|
|
display: flex;
|
|
align-items: center;
|
|
}
|
|
|
|
.alert-success {
|
|
background-color: #f6ffed;
|
|
border: 1px solid #b7eb8f;
|
|
color: #52c41a;
|
|
}
|
|
|
|
.alert-info {
|
|
background-color: #e6f7ff;
|
|
border: 1px solid #91d5ff;
|
|
color: #1890ff;
|
|
}
|
|
|
|
.alert-warning {
|
|
background-color: #fffbe6;
|
|
border: 1px solid #ffe58f;
|
|
color: #faad14;
|
|
}
|
|
|
|
.alert-error {
|
|
background-color: #fff2f0;
|
|
border: 1px solid #ffccc7;
|
|
color: #ff4d4f;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="layout-container">
|
|
<!-- 侧边栏 -->
|
|
<div class="sidebar">
|
|
<div class="py-6 px-4 border-b border-gray-100">
|
|
<div class="flex items-center">
|
|
<i class="ri-file-search-line text-primary text-xl mr-2"></i>
|
|
<h2 class="text-lg font-medium">AI审核系统</h2>
|
|
</div>
|
|
</div>
|
|
<div class="py-4">
|
|
<div class="sidebar-menu-item">
|
|
<a href="#" class="flex items-center text-sm font-medium">
|
|
<i class="ri-dashboard-line mr-3"></i>
|
|
<span>首页</span>
|
|
</a>
|
|
</div>
|
|
<div class="sidebar-menu-item active">
|
|
<a href="#" class="flex items-center text-sm font-medium">
|
|
<i class="ri-file-upload-line mr-3"></i>
|
|
<span>文件管理</span>
|
|
</a>
|
|
</div>
|
|
<div class="sidebar-menu-item">
|
|
<a href="#" class="flex items-center text-sm font-medium">
|
|
<i class="ri-list-check-2 mr-3"></i>
|
|
<span>评查规则库</span>
|
|
</a>
|
|
</div>
|
|
<div class="sidebar-menu-item">
|
|
<a href="#" class="flex items-center text-sm font-medium">
|
|
<i class="ri-history-line mr-3"></i>
|
|
<span>审核历史</span>
|
|
</a>
|
|
</div>
|
|
<div class="sidebar-menu-item">
|
|
<a href="#" class="flex items-center text-sm font-medium">
|
|
<i class="ri-settings-3-line mr-3"></i>
|
|
<span>系统设置</span>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 主内容区 -->
|
|
<div class="main-content">
|
|
<!-- 面包屑导航 -->
|
|
<div class="breadcrumb">
|
|
<span class="breadcrumb-item">首页</span>
|
|
<span class="breadcrumb-item">文件管理</span>
|
|
<span class="breadcrumb-item">上传文档</span>
|
|
</div>
|
|
|
|
<!-- 页面头部 -->
|
|
<div class="flex justify-between items-center mb-4">
|
|
<h2 class="text-xl font-medium">上传文档</h2>
|
|
<div>
|
|
<button class="ant-btn ant-btn-default mr-2" onclick="window.location.href='文档-列表.html'">
|
|
<i class="ri-arrow-left-line"></i> 返回
|
|
</button>
|
|
<button class="ant-btn ant-btn-primary" id="start-upload-btn" disabled>
|
|
<i class="ri-upload-2-line"></i> 开始上传
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 上传表单 -->
|
|
<div class="ant-card">
|
|
<div class="ant-card-body">
|
|
<form id="upload-form">
|
|
<div class="grid grid-cols-2 gap-6 mb-6">
|
|
<div class="form-group">
|
|
<label class="form-label">文档类型 <span class="text-red-500">*</span></label>
|
|
<select class="form-select" id="doc-type" required>
|
|
<option value="">请选择文档类型</option>
|
|
<option value="1">销售合同</option>
|
|
<option value="2">采购合同</option>
|
|
<option value="3">专卖许可证</option>
|
|
<option value="4">行政处罚决定书</option>
|
|
<option value="5">承包协议</option>
|
|
</select>
|
|
<div class="text-sm text-secondary mt-1">不同文档类型应用不同的评查规则</div>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label class="form-label">文档编号</label>
|
|
<input type="text" class="form-input" id="doc-number" placeholder="请输入合同编号、许可证号等">
|
|
<div class="text-sm text-secondary mt-1">如无编号可留空,系统将自动识别</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group mb-4">
|
|
<label class="form-label">备注信息</label>
|
|
<textarea class="form-textarea" id="doc-remark" placeholder="可输入文档的相关描述或备注信息" rows="2"></textarea>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label class="form-label">上传文档 <span class="text-red-500">*</span></label>
|
|
<div class="upload-area" id="upload-area">
|
|
<input type="file" id="file-input" style="display: none;" multiple>
|
|
<i class="ri-upload-cloud-line upload-icon"></i>
|
|
<div class="upload-text">
|
|
<p class="text-lg mb-2">拖拽文件到此处或点击上传</p>
|
|
<p class="text-sm text-secondary">支持 PDF、DOC、DOCX、TXT 格式文档,单个文件大小不超过50MB</p>
|
|
</div>
|
|
<div class="test-document-switch">
|
|
<label class="switch">
|
|
<input type="checkbox" id="test-document-toggle">
|
|
<span class="slider"></span>
|
|
</label>
|
|
<span>标记为测试文档(不计入正式统计)</span>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 批量操作栏 -->
|
|
<div class="batch-actions" id="batch-actions" style="display: none;">
|
|
<div>
|
|
<span class="text-sm">已选择 <span id="selected-count">0</span> 个文件</span>
|
|
</div>
|
|
<div>
|
|
<button type="button" class="ant-btn ant-btn-default ant-btn-sm mr-2" id="batch-delete-btn">
|
|
<i class="ri-delete-bin-line"></i> 删除选中
|
|
</button>
|
|
<button type="button" class="ant-btn ant-btn-default ant-btn-sm" id="clear-all-btn">
|
|
<i class="ri-close-circle-line"></i> 清空列表
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="file-list" id="file-list"></div>
|
|
|
|
<!-- 高级选项区域 -->
|
|
<div class="advanced-options">
|
|
<div class="advanced-options-toggle" id="advanced-toggle">
|
|
<span>高级上传设置</span>
|
|
<i class="ri-arrow-down-s-line ml-1"></i>
|
|
</div>
|
|
<div class="advanced-options-content" id="advanced-content">
|
|
<div class="grid grid-cols-2 gap-4">
|
|
<div class="form-group">
|
|
<label class="form-label">存储方式</label>
|
|
<select class="form-select" id="storage-type">
|
|
<option value="minio">MinIO对象存储</option>
|
|
<option value="local">本地文件系统</option>
|
|
<option value="s3">Amazon S3</option>
|
|
</select>
|
|
<div class="text-sm text-secondary mt-1">选择文档的存储位置</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label class="form-label">上传后操作</label>
|
|
<select class="form-select" id="after-upload">
|
|
<option value="list">返回文档列表</option>
|
|
<option value="stay">留在当前页面</option>
|
|
<option value="audit">立即开始审核</option>
|
|
</select>
|
|
<div class="text-sm text-secondary mt-1">上传完成后自动执行的操作</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
|
|
<!-- 上传完成后的操作区域 -->
|
|
<div class="upload-complete-actions" id="upload-complete-actions">
|
|
<div class="alert alert-success mb-4">
|
|
<i class="ri-checkbox-circle-line mr-2"></i> 所有文件上传成功!
|
|
</div>
|
|
<div>
|
|
<button class="ant-btn ant-btn-default mr-2" id="upload-more-btn">
|
|
<i class="ri-add-line"></i> 继续上传
|
|
</button>
|
|
<button class="ant-btn ant-btn-default mr-2" id="view-list-btn">
|
|
<i class="ri-list-check-line"></i> 查看文档列表
|
|
</button>
|
|
<button class="ant-btn ant-btn-primary" id="start-audit-btn">
|
|
<i class="ri-play-circle-line"></i> 开始审核
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 文件预览模态框 -->
|
|
<div class="preview-modal" id="preview-modal">
|
|
<div class="preview-content">
|
|
<div class="preview-header">
|
|
<h3 class="text-lg font-medium" id="preview-title">文件预览</h3>
|
|
<button class="ant-btn ant-btn-text" id="close-preview">
|
|
<i class="ri-close-line"></i>
|
|
</button>
|
|
</div>
|
|
<div class="preview-body">
|
|
<iframe id="preview-iframe" class="preview-iframe"></iframe>
|
|
</div>
|
|
<div class="preview-footer">
|
|
<button class="ant-btn ant-btn-default" id="close-preview-btn">关闭</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
const uploadArea = document.getElementById('upload-area');
|
|
const fileInput = document.getElementById('file-input');
|
|
const fileList = document.getElementById('file-list');
|
|
const startUploadBtn = document.getElementById('start-upload-btn');
|
|
const testDocumentToggle = document.getElementById('test-document-toggle');
|
|
const previewModal = document.getElementById('preview-modal');
|
|
const previewTitle = document.getElementById('preview-title');
|
|
const previewIframe = document.getElementById('preview-iframe');
|
|
const closePreviewBtn = document.getElementById('close-preview');
|
|
const closePreviewFooterBtn = document.getElementById('close-preview-btn');
|
|
|
|
let files = [];
|
|
|
|
// 更新上传按钮状态
|
|
function updateUploadButtonState() {
|
|
startUploadBtn.disabled = files.length === 0 || !document.getElementById('doc-type').value;
|
|
}
|
|
|
|
// 点击上传区域触发文件选择
|
|
uploadArea.addEventListener('click', function() {
|
|
fileInput.click();
|
|
});
|
|
|
|
// 拖拽文件
|
|
uploadArea.addEventListener('dragover', function(e) {
|
|
e.preventDefault();
|
|
this.classList.add('drag-over');
|
|
});
|
|
|
|
uploadArea.addEventListener('dragleave', function() {
|
|
this.classList.remove('drag-over');
|
|
});
|
|
|
|
uploadArea.addEventListener('drop', function(e) {
|
|
e.preventDefault();
|
|
this.classList.remove('drag-over');
|
|
|
|
const droppedFiles = e.dataTransfer.files;
|
|
handleFiles(droppedFiles);
|
|
});
|
|
|
|
// 文件选择
|
|
fileInput.addEventListener('change', function() {
|
|
handleFiles(this.files);
|
|
this.value = ''; // 清空文件选择器,允许重复选择同一文件
|
|
});
|
|
|
|
// 文档类型选择
|
|
document.getElementById('doc-type').addEventListener('change', updateUploadButtonState);
|
|
|
|
// 处理选择的文件
|
|
function handleFiles(selectedFiles) {
|
|
if (!selectedFiles || selectedFiles.length === 0) return;
|
|
|
|
for (let i = 0; i < selectedFiles.length; i++) {
|
|
const file = selectedFiles[i];
|
|
|
|
// 检查文件类型
|
|
const fileType = file.type;
|
|
const validTypes = ['application/pdf', 'application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'text/plain'];
|
|
|
|
if (!validTypes.includes(fileType) &&
|
|
!file.name.toLowerCase().endsWith('.pdf') &&
|
|
!file.name.toLowerCase().endsWith('.doc') &&
|
|
!file.name.toLowerCase().endsWith('.docx') &&
|
|
!file.name.toLowerCase().endsWith('.txt')) {
|
|
alert(`不支持的文件类型: ${file.name}\n请上传PDF、DOC、DOCX或TXT格式文件`);
|
|
continue;
|
|
}
|
|
|
|
// 检查文件大小
|
|
if (file.size > 50 * 1024 * 1024) { // 50MB
|
|
alert(`文件过大: ${file.name}\n文件大小不能超过50MB`);
|
|
continue;
|
|
}
|
|
|
|
// 检查是否已添加
|
|
const isDuplicate = files.some(f => f.name === file.name && f.size === file.size);
|
|
if (isDuplicate) {
|
|
alert(`文件已添加: ${file.name}`);
|
|
continue;
|
|
}
|
|
|
|
files.push(file);
|
|
createFileListItem(file);
|
|
}
|
|
|
|
updateUploadButtonState();
|
|
updateBatchActionsVisibility();
|
|
}
|
|
|
|
// 创建文件列表项
|
|
function createFileListItem(file) {
|
|
const fileItem = document.createElement('div');
|
|
fileItem.className = 'file-item';
|
|
|
|
// 生成唯一ID供后续操作
|
|
const fileId = 'file-' + Math.random().toString(36).substr(2, 9);
|
|
fileItem.setAttribute('data-file-id', fileId);
|
|
|
|
// 根据文件类型选择图标
|
|
let fileIconClass = 'ri-file-text-line';
|
|
let fileIconColor = 'text-primary';
|
|
let canPreview = false;
|
|
|
|
if (file.name.toLowerCase().endsWith('.pdf')) {
|
|
fileIconClass = 'ri-file-pdf-line';
|
|
fileIconColor = 'text-red-500';
|
|
canPreview = true;
|
|
} else if (file.name.toLowerCase().endsWith('.doc') || file.name.toLowerCase().endsWith('.docx')) {
|
|
fileIconClass = 'ri-file-word-line';
|
|
fileIconColor = 'text-blue-500';
|
|
} else if (file.name.toLowerCase().endsWith('.txt')) {
|
|
fileIconClass = 'ri-file-text-line';
|
|
fileIconColor = 'text-gray-500';
|
|
canPreview = true;
|
|
}
|
|
|
|
// 格式化文件大小
|
|
const fileSize = formatFileSize(file.size);
|
|
|
|
// 允许编辑文件名
|
|
const fileName = file.name;
|
|
const fileNameWithoutExt = fileName.substring(0, fileName.lastIndexOf('.'));
|
|
const fileExt = fileName.substring(fileName.lastIndexOf('.'));
|
|
|
|
fileItem.innerHTML = `
|
|
<div class="flex items-center mr-3">
|
|
<input type="checkbox" class="file-checkbox" data-file-id="${fileId}">
|
|
</div>
|
|
<i class="${fileIconClass} file-icon ${fileIconColor}"></i>
|
|
<div class="file-info">
|
|
<div class="file-name">
|
|
<span class="filename-text">${fileName}</span>
|
|
<span class="edit-filename" title="编辑文件名"><i class="ri-edit-line"></i></span>
|
|
</div>
|
|
<div class="file-meta">
|
|
<span class="file-size">${fileSize}</span>
|
|
<span class="file-status">待上传</span>
|
|
</div>
|
|
<div class="progress-bar">
|
|
<div class="progress-bar-inner" style="width: 0%"></div>
|
|
</div>
|
|
</div>
|
|
<div class="file-actions">
|
|
${canPreview ? `
|
|
<button type="button" class="ant-btn ant-btn-text ant-btn-sm text-primary preview-file-btn" title="预览文件">
|
|
<i class="ri-eye-line"></i>
|
|
</button>
|
|
` : ''}
|
|
<button type="button" class="ant-btn ant-btn-text ant-btn-sm text-error delete-file-btn" title="删除文件">
|
|
<i class="ri-delete-bin-line"></i>
|
|
</button>
|
|
</div>
|
|
`;
|
|
|
|
// 预览按钮
|
|
if (canPreview) {
|
|
const previewBtn = fileItem.querySelector('.preview-file-btn');
|
|
previewBtn.addEventListener('click', function() {
|
|
previewFile(file);
|
|
});
|
|
}
|
|
|
|
// 删除按钮
|
|
const deleteBtn = fileItem.querySelector('.delete-file-btn');
|
|
deleteBtn.addEventListener('click', function() {
|
|
removeFile(fileId);
|
|
});
|
|
|
|
// 编辑文件名
|
|
const editNameBtn = fileItem.querySelector('.edit-filename');
|
|
const filenameText = fileItem.querySelector('.filename-text');
|
|
|
|
editNameBtn.addEventListener('click', function() {
|
|
const currentName = filenameText.textContent;
|
|
const nameWithoutExt = currentName.substring(0, currentName.lastIndexOf('.'));
|
|
const ext = currentName.substring(currentName.lastIndexOf('.'));
|
|
|
|
// 创建输入框
|
|
const input = document.createElement('input');
|
|
input.type = 'text';
|
|
input.value = nameWithoutExt;
|
|
input.className = 'form-input py-0 px-1';
|
|
input.style.width = '70%';
|
|
|
|
// 替换文本为输入框
|
|
filenameText.innerHTML = '';
|
|
filenameText.appendChild(input);
|
|
input.focus();
|
|
|
|
// 处理完成编辑
|
|
const finishEditing = () => {
|
|
let newName = input.value.trim();
|
|
if (newName) {
|
|
// 只更新文件名,保留扩展名
|
|
filenameText.textContent = newName + ext;
|
|
|
|
// 更新文件对象的名称
|
|
const fileIndex = files.findIndex(f =>
|
|
fileItem.getAttribute('data-file-id') === fileId
|
|
);
|
|
|
|
if (fileIndex !== -1) {
|
|
// 在这里,我们只是更新UI显示,实际上传时再处理文件名
|
|
// 因为File对象的name属性不能直接修改,我们将使用FormData时设置新名称
|
|
fileItem.setAttribute('data-new-name', newName + ext);
|
|
}
|
|
} else {
|
|
// 如果用户删除了所有内容,还原原始文件名
|
|
filenameText.textContent = currentName;
|
|
}
|
|
};
|
|
|
|
// 失去焦点或按回车时完成编辑
|
|
input.addEventListener('blur', finishEditing);
|
|
input.addEventListener('keydown', function(e) {
|
|
if (e.key === 'Enter') {
|
|
finishEditing();
|
|
}
|
|
});
|
|
});
|
|
|
|
// 复选框事件
|
|
const checkbox = fileItem.querySelector('.file-checkbox');
|
|
checkbox.addEventListener('change', updateBatchActionsVisibility);
|
|
|
|
fileList.appendChild(fileItem);
|
|
return fileItem;
|
|
}
|
|
|
|
// 格式化文件大小
|
|
function formatFileSize(bytes) {
|
|
if (bytes === 0) return '0 Bytes';
|
|
|
|
const k = 1024;
|
|
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
|
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
|
|
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
|
}
|
|
|
|
// 预览文件
|
|
function previewFile(file) {
|
|
if (file.type === 'application/pdf' || file.name.toLowerCase().endsWith('.pdf')) {
|
|
// 对于PDF文件,使用对象URL直接在iframe中显示
|
|
const objectUrl = URL.createObjectURL(file);
|
|
previewTitle.textContent = file.name;
|
|
previewIframe.src = objectUrl;
|
|
previewModal.style.display = 'flex';
|
|
} else if (file.type === 'text/plain' || file.name.toLowerCase().endsWith('.txt')) {
|
|
// 对于文本文件,读取内容并在iframe中显示
|
|
const reader = new FileReader();
|
|
reader.onload = function(e) {
|
|
const content = e.target.result;
|
|
previewTitle.textContent = file.name;
|
|
|
|
// 创建一个HTML文档来显示文本内容
|
|
const html = `
|
|
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<style>
|
|
body {
|
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
|
line-height: 1.6;
|
|
padding: 20px;
|
|
white-space: pre-wrap;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>${content}</body>
|
|
</html>
|
|
`;
|
|
|
|
previewIframe.src = 'data:text/html;charset=utf-8,' + encodeURIComponent(html);
|
|
previewModal.style.display = 'flex';
|
|
};
|
|
reader.readAsText(file);
|
|
}
|
|
}
|
|
|
|
// 关闭预览
|
|
function closePreview() {
|
|
previewModal.style.display = 'none';
|
|
previewIframe.src = '';
|
|
}
|
|
|
|
closePreviewBtn.addEventListener('click', closePreview);
|
|
closePreviewFooterBtn.addEventListener('click', closePreview);
|
|
|
|
// 点击模态框背景时关闭预览
|
|
previewModal.addEventListener('click', function(e) {
|
|
if (e.target === previewModal) {
|
|
closePreview();
|
|
}
|
|
});
|
|
|
|
// 移除文件
|
|
function removeFile(fileId) {
|
|
const fileItem = document.querySelector(`.file-item[data-file-id="${fileId}"]`);
|
|
if (!fileItem) return;
|
|
|
|
// 从文件列表中移除
|
|
const fileIndex = files.findIndex((_, index) =>
|
|
document.querySelectorAll('.file-item')[index].getAttribute('data-file-id') === fileId
|
|
);
|
|
|
|
if (fileIndex !== -1) {
|
|
files.splice(fileIndex, 1);
|
|
}
|
|
|
|
fileItem.remove();
|
|
updateUploadButtonState();
|
|
updateBatchActionsVisibility();
|
|
}
|
|
|
|
// 更新批量操作按钮可见性
|
|
function updateBatchActionsVisibility() {
|
|
const checkboxes = document.querySelectorAll('.file-checkbox:checked');
|
|
const batchActions = document.getElementById('batch-actions');
|
|
const selectedCount = document.getElementById('selected-count');
|
|
|
|
if (files.length > 0) {
|
|
batchActions.style.display = 'flex';
|
|
selectedCount.textContent = checkboxes.length;
|
|
} else {
|
|
batchActions.style.display = 'none';
|
|
}
|
|
}
|
|
|
|
// 批量删除按钮
|
|
document.getElementById('batch-delete-btn').addEventListener('click', function() {
|
|
const checkedBoxes = document.querySelectorAll('.file-checkbox:checked');
|
|
const fileIds = Array.from(checkedBoxes).map(checkbox => checkbox.getAttribute('data-file-id'));
|
|
|
|
if (fileIds.length === 0) return;
|
|
|
|
if (confirm(`确定要删除选中的 ${fileIds.length} 个文件吗?`)) {
|
|
fileIds.forEach(id => removeFile(id));
|
|
}
|
|
});
|
|
|
|
// 清空列表按钮
|
|
document.getElementById('clear-all-btn').addEventListener('click', function() {
|
|
if (files.length === 0) return;
|
|
|
|
if (confirm('确定要清空文件列表吗?')) {
|
|
files = [];
|
|
fileList.innerHTML = '';
|
|
updateUploadButtonState();
|
|
updateBatchActionsVisibility();
|
|
}
|
|
});
|
|
|
|
// 高级选项切换
|
|
const advancedToggle = document.getElementById('advanced-toggle');
|
|
const advancedContent = document.getElementById('advanced-content');
|
|
|
|
advancedToggle.addEventListener('click', function() {
|
|
const isOpen = advancedContent.style.display === 'block';
|
|
|
|
if (isOpen) {
|
|
advancedContent.style.display = 'none';
|
|
this.classList.remove('open');
|
|
} else {
|
|
advancedContent.style.display = 'block';
|
|
this.classList.add('open');
|
|
}
|
|
});
|
|
|
|
// 开始上传按钮
|
|
startUploadBtn.addEventListener('click', function() {
|
|
const docType = document.getElementById('doc-type').value;
|
|
const docNumber = document.getElementById('doc-number').value;
|
|
const docRemark = document.getElementById('doc-remark').value;
|
|
const isTestDocument = testDocumentToggle.checked;
|
|
const storageType = document.getElementById('storage-type').value;
|
|
const afterUpload = document.getElementById('after-upload').value;
|
|
|
|
if (!docType) {
|
|
alert('请选择文档类型');
|
|
return;
|
|
}
|
|
|
|
if (files.length === 0) {
|
|
alert('请至少上传一个文档');
|
|
return;
|
|
}
|
|
|
|
// 模拟上传过程
|
|
const fileItems = document.querySelectorAll('.file-item');
|
|
|
|
files.forEach((file, index) => {
|
|
uploadFile(file, fileItems[index], {
|
|
type_id: docType,
|
|
document_number: docNumber,
|
|
remark: docRemark,
|
|
is_test_document: isTestDocument,
|
|
storage_type: storageType
|
|
});
|
|
});
|
|
});
|
|
|
|
// 上传文件
|
|
function uploadFile(file, fileItem, metadata) {
|
|
const progressBar = fileItem.querySelector('.progress-bar-inner');
|
|
const statusText = fileItem.querySelector('.file-status');
|
|
|
|
// 获取可能被修改的文件名
|
|
const newName = fileItem.getAttribute('data-new-name');
|
|
const fileName = newName || file.name;
|
|
|
|
statusText.textContent = '上传中...';
|
|
|
|
// 假设文件ID,实际应由服务器返回
|
|
const uploadId = 'upload-' + Math.random().toString(36).substr(2, 9);
|
|
fileItem.setAttribute('data-upload-id', uploadId);
|
|
|
|
// 模拟上传进度
|
|
let progress = 0;
|
|
const interval = setInterval(() => {
|
|
progress += Math.random() * 10;
|
|
if (progress >= 100) {
|
|
progress = 100;
|
|
clearInterval(interval);
|
|
|
|
// 上传完成
|
|
setTimeout(() => {
|
|
// 根据概率模拟偶尔的上传失败情况
|
|
const success = Math.random() > 0.1; // 90%概率成功
|
|
|
|
if (success) {
|
|
statusText.textContent = '上传成功';
|
|
|
|
// 实际应用中应该使用AJAX请求上传文件
|
|
// console.log('文件上传成功:', fileName, metadata);
|
|
|
|
// 检查是否所有文件都已上传
|
|
const allUploaded = Array.from(document.querySelectorAll('.file-status')).every(
|
|
status => status.textContent === '上传成功'
|
|
);
|
|
|
|
if (allUploaded) {
|
|
setTimeout(() => {
|
|
handleUploadComplete();
|
|
}, 1000);
|
|
}
|
|
} else {
|
|
statusText.textContent = '上传失败';
|
|
statusText.classList.add('error');
|
|
|
|
// 添加重试按钮
|
|
const retryButton = document.createElement('span');
|
|
retryButton.className = 'retry-btn ml-2';
|
|
retryButton.innerHTML = '<i class="ri-refresh-line"></i> 重试';
|
|
statusText.parentNode.appendChild(retryButton);
|
|
|
|
retryButton.addEventListener('click', function() {
|
|
statusText.textContent = '准备重新上传...';
|
|
statusText.classList.remove('error');
|
|
retryButton.remove();
|
|
|
|
// 延迟一下再开始上传,让用户感知状态变化
|
|
setTimeout(() => {
|
|
progressBar.style.width = '0%';
|
|
uploadFile(file, fileItem, metadata);
|
|
}, 500);
|
|
});
|
|
}
|
|
}, 500);
|
|
}
|
|
|
|
progressBar.style.width = `${progress}%`;
|
|
}, 200);
|
|
|
|
// 实际应用中应该使用FormData和fetch/XMLHttpRequest上传文件
|
|
// const formData = new FormData();
|
|
// formData.append('file', file);
|
|
// formData.append('type_id', metadata.type_id);
|
|
// formData.append('document_number', metadata.document_number);
|
|
// formData.append('remark', metadata.remark);
|
|
// formData.append('is_test_document', metadata.is_test_document);
|
|
// formData.append('storage_type', metadata.storage_type);
|
|
|
|
// fetch('/api/documents', {
|
|
// method: 'POST',
|
|
// body: formData
|
|
// })
|
|
// .then(response => response.json())
|
|
// .then(data => {
|
|
// // console.log('上传成功:', data);
|
|
// statusText.textContent = '上传成功';
|
|
// progressBar.style.width = '100%';
|
|
//
|
|
// // 检查是否所有文件都已上传
|
|
// const allUploaded = Array.from(document.querySelectorAll('.file-status')).every(
|
|
// status => status.textContent === '上传成功'
|
|
// );
|
|
//
|
|
// if (allUploaded) {
|
|
// handleUploadComplete();
|
|
// }
|
|
// })
|
|
// .catch(error => {
|
|
// console.error('上传失败:', error);
|
|
// statusText.textContent = '上传失败';
|
|
// statusText.classList.add('error');
|
|
//
|
|
// // 添加重试按钮
|
|
// const retryButton = document.createElement('span');
|
|
// retryButton.className = 'retry-btn ml-2';
|
|
// retryButton.innerHTML = '<i class="ri-refresh-line"></i> 重试';
|
|
// statusText.parentNode.appendChild(retryButton);
|
|
//
|
|
// retryButton.addEventListener('click', function() {
|
|
// statusText.textContent = '准备重新上传...';
|
|
// statusText.classList.remove('error');
|
|
// retryButton.remove();
|
|
//
|
|
// // 延迟一下再开始上传,让用户感知状态变化
|
|
// setTimeout(() => {
|
|
// progressBar.style.width = '0%';
|
|
// uploadFile(file, fileItem, metadata);
|
|
// }, 500);
|
|
// });
|
|
// });
|
|
}
|
|
|
|
// 上传完成后的处理
|
|
function handleUploadComplete() {
|
|
// 隐藏上传区域和文件列表
|
|
document.getElementById('upload-form').style.display = 'none';
|
|
|
|
// 显示上传完成操作区域
|
|
const uploadCompleteActions = document.getElementById('upload-complete-actions');
|
|
uploadCompleteActions.style.display = 'block';
|
|
|
|
// 滚动到操作区域
|
|
uploadCompleteActions.scrollIntoView({ behavior: 'smooth' });
|
|
|
|
// 根据选择的上传后操作决定行为
|
|
const afterUpload = document.getElementById('after-upload').value;
|
|
|
|
if (afterUpload === 'list') {
|
|
setTimeout(() => {
|
|
window.location.href = '文档-列表.html';
|
|
}, 2000);
|
|
} else if (afterUpload === 'audit') {
|
|
setTimeout(() => {
|
|
window.location.href = '文档-详情.html?id=1&action=audit';
|
|
}, 2000);
|
|
}
|
|
}
|
|
|
|
// 上传完成后的操作按钮事件
|
|
document.getElementById('upload-more-btn').addEventListener('click', function() {
|
|
// 重置表单,允许继续上传
|
|
document.getElementById('upload-form').style.display = 'block';
|
|
document.getElementById('upload-complete-actions').style.display = 'none';
|
|
|
|
// 清空文件列表
|
|
files = [];
|
|
fileList.innerHTML = '';
|
|
updateUploadButtonState();
|
|
updateBatchActionsVisibility();
|
|
});
|
|
|
|
document.getElementById('view-list-btn').addEventListener('click', function() {
|
|
window.location.href = '文档-列表.html';
|
|
});
|
|
|
|
document.getElementById('start-audit-btn').addEventListener('click', function() {
|
|
// 假设最后一个上传的文档ID是1
|
|
window.location.href = '文档-详情.html?id=1&action=audit';
|
|
});
|
|
});
|
|
</script>
|
|
</body>
|
|
</html> |