|
|
@@ -53,6 +53,7 @@
|
|
|
border-radius: 8px;
|
|
|
overflow: hidden;
|
|
|
min-height: 80vh;
|
|
|
+ position: relative;
|
|
|
}
|
|
|
.pdf-viewer-wrapper iframe,
|
|
|
.pdf-viewer-wrapper embed {
|
|
|
@@ -81,6 +82,54 @@
|
|
|
color: #6c757d;
|
|
|
margin-right: 8px;
|
|
|
}
|
|
|
+ .loading-overlay {
|
|
|
+ position: absolute;
|
|
|
+ top: 0;
|
|
|
+ left: 0;
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ background-color: rgba(255, 255, 255, 0.95);
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ justify-content: center;
|
|
|
+ align-items: center;
|
|
|
+ z-index: 1000;
|
|
|
+ transition: opacity 0.3s ease;
|
|
|
+ }
|
|
|
+ .loading-spinner {
|
|
|
+ width: 50px;
|
|
|
+ height: 50px;
|
|
|
+ border: 5px solid #f3f3f3;
|
|
|
+ border-top: 5px solid #0d6efd;
|
|
|
+ border-radius: 50%;
|
|
|
+ animation: spin 1s linear infinite;
|
|
|
+ margin-bottom: 16px;
|
|
|
+ }
|
|
|
+ .loading-text {
|
|
|
+ font-size: 1rem;
|
|
|
+ color: #6c757d;
|
|
|
+ text-align: center;
|
|
|
+ }
|
|
|
+ @keyframes spin {
|
|
|
+ 0% { transform: rotate(0deg); }
|
|
|
+ 100% { transform: rotate(360deg); }
|
|
|
+ }
|
|
|
+ .loading-progress {
|
|
|
+ width: 80%;
|
|
|
+ max-width: 400px;
|
|
|
+ height: 8px;
|
|
|
+ background-color: #e9ecef;
|
|
|
+ border-radius: 4px;
|
|
|
+ overflow: hidden;
|
|
|
+ margin: 16px 0;
|
|
|
+ }
|
|
|
+ .loading-progress-bar {
|
|
|
+ height: 100%;
|
|
|
+ background-color: #0d6efd;
|
|
|
+ border-radius: 4px;
|
|
|
+ width: 0%;
|
|
|
+ transition: width 0.3s ease;
|
|
|
+ }
|
|
|
</style>
|
|
|
{% endblock %}
|
|
|
|
|
|
@@ -172,12 +221,6 @@
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="d-flex gap-2 mt-3 justify-content-end">
|
|
|
- <a href="{{ selected_pdf.oss_url }}" target="_blank" class="btn btn-sm btn-outline-primary">
|
|
|
- <i class="bi bi-box-arrow-up-right"></i> 新窗口打开
|
|
|
- </a>
|
|
|
- <a href="{{ selected_pdf.oss_url }}" download class="btn btn-sm btn-outline-secondary">
|
|
|
- <i class="bi bi-download"></i> 下载
|
|
|
- </a>
|
|
|
<form action="{{ url_for('delete_pdf', pdf_id=selected_pdf.id) }}" method="POST" class="d-inline"
|
|
|
onsubmit="return confirm('确定要删除此PDF文件吗?此操作无法撤销。');">
|
|
|
<button type="submit" class="btn btn-sm btn-outline-danger">
|
|
|
@@ -188,7 +231,14 @@
|
|
|
</div>
|
|
|
<div class="card-body p-0">
|
|
|
<div class="pdf-viewer-wrapper">
|
|
|
- <iframe id="pdfViewer" src="{{ selected_pdf.oss_url }}" type="application/pdf"></iframe>
|
|
|
+ <div id="loadingOverlay" class="loading-overlay">
|
|
|
+ <div class="loading-spinner"></div>
|
|
|
+ <div class="loading-text">正在加载PDF文件,请稍候...</div>
|
|
|
+ <div class="loading-progress">
|
|
|
+ <div class="loading-progress-bar" id="loadingProgressBar"></div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <iframe id="pdfViewer" src="{{ selected_pdf.oss_url }}#toolbar=0" type="application/pdf" onload="hideLoading()"></iframe>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
@@ -211,3 +261,75 @@
|
|
|
|
|
|
|
|
|
{% endblock %}
|
|
|
+
|
|
|
+{% block extra_js %}
|
|
|
+<script>
|
|
|
+ // 显示加载动画
|
|
|
+ function showLoading() {
|
|
|
+ document.getElementById('loadingOverlay').style.display = 'flex';
|
|
|
+ }
|
|
|
+
|
|
|
+ // 隐藏加载动画
|
|
|
+ function hideLoading() {
|
|
|
+ const overlay = document.getElementById('loadingOverlay');
|
|
|
+ overlay.style.opacity = '0';
|
|
|
+ setTimeout(() => {
|
|
|
+ overlay.style.display = 'none';
|
|
|
+ }, 300);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 模拟加载进度
|
|
|
+ function simulateLoadingProgress() {
|
|
|
+ const progressBar = document.getElementById('loadingProgressBar');
|
|
|
+ if (progressBar) {
|
|
|
+ let progress = 0;
|
|
|
+ const interval = setInterval(() => {
|
|
|
+ progress += 5;
|
|
|
+ if (progress > 90) {
|
|
|
+ clearInterval(interval);
|
|
|
+ } else {
|
|
|
+ progressBar.style.width = progress + '%';
|
|
|
+ }
|
|
|
+ }, 200);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 页面加载完成后开始模拟加载进度
|
|
|
+ document.addEventListener('DOMContentLoaded', function() {
|
|
|
+ // 检查是否有选中的PDF
|
|
|
+ if (document.getElementById('pdfViewer')) {
|
|
|
+ simulateLoadingProgress();
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ // 监听PDF卡片点击事件,显示加载动画
|
|
|
+ document.querySelectorAll('.pdf-card').forEach(card => {
|
|
|
+ card.addEventListener('click', function() {
|
|
|
+ // 显示加载动画
|
|
|
+ const overlay = document.createElement('div');
|
|
|
+ overlay.id = 'loadingOverlay';
|
|
|
+ overlay.className = 'loading-overlay';
|
|
|
+ overlay.innerHTML = `
|
|
|
+ <div class="loading-spinner"></div>
|
|
|
+ <div class="loading-text">正在加载PDF文件,请稍候...</div>
|
|
|
+ <div class="loading-progress">
|
|
|
+ <div class="loading-progress-bar" id="loadingProgressBar"></div>
|
|
|
+ </div>
|
|
|
+ `;
|
|
|
+ document.body.appendChild(overlay);
|
|
|
+
|
|
|
+ // 开始模拟加载进度
|
|
|
+ let progress = 0;
|
|
|
+ const progressBar = overlay.querySelector('#loadingProgressBar');
|
|
|
+ const interval = setInterval(() => {
|
|
|
+ progress += 5;
|
|
|
+ if (progress > 90) {
|
|
|
+ clearInterval(interval);
|
|
|
+ } else {
|
|
|
+ progressBar.style.width = progress + '%';
|
|
|
+ }
|
|
|
+ }, 200);
|
|
|
+ });
|
|
|
+ });
|
|
|
+</script>
|
|
|
+{% endblock %}
|