|
<?php |
|
|
|
require_once 'settings.php'; |
|
|
|
class PasteBoard { |
|
private $db; |
|
private $settings; |
|
|
|
public function __construct() { |
|
$this->settings = new Settings(); |
|
$this->db = new SQLite3($this->settings->getSetting('db_path')); |
|
} |
|
|
|
private function getChineseTime($timestamp) { |
|
date_default_timezone_set('Asia/Shanghai'); |
|
return $timestamp; |
|
} |
|
|
|
public function getPaste($uuid) { |
|
$stmt = $this->db->prepare('SELECT * FROM notes WHERE uuid = :uuid'); |
|
$stmt->bindValue(':uuid', $uuid, SQLITE3_TEXT); |
|
$result = $stmt->execute(); |
|
|
|
if ($row = $result->fetchArray(SQLITE3_ASSOC)) { |
|
|
|
date_default_timezone_set('Asia/Shanghai'); |
|
if (time() > $row['expires_at']) { |
|
$this->deletePaste($uuid); |
|
return null; |
|
} |
|
|
|
|
|
if ($row['max_views'] > 0 && $row['current_views'] >= $row['max_views']) { |
|
$this->deletePaste($uuid); |
|
return null; |
|
} |
|
|
|
|
|
$stmt = $this->db->prepare('UPDATE notes SET current_views = current_views + 1 WHERE uuid = :uuid'); |
|
$stmt->bindValue(':uuid', $uuid, SQLITE3_TEXT); |
|
$stmt->execute(); |
|
|
|
return $row; |
|
} |
|
return null; |
|
} |
|
|
|
private function deletePaste($uuid) { |
|
$stmt = $this->db->prepare('DELETE FROM notes WHERE uuid = :uuid'); |
|
$stmt->bindValue(':uuid', $uuid, SQLITE3_TEXT); |
|
$stmt->execute(); |
|
} |
|
} |
|
|
|
$pasteboard = new PasteBoard(); |
|
$settings = new Settings(); |
|
$paste = null; |
|
$uuid = isset($_GET['id']) ? $_GET['id'] : null; |
|
|
|
if ($uuid) { |
|
$paste = $pasteboard->getPaste($uuid); |
|
if (!$paste) { |
|
header("HTTP/1.0 404 Not Found"); |
|
echo "Paste not found or expired"; |
|
exit; |
|
} |
|
} |
|
?> |
|
|
|
<!DOCTYPE html> |
|
<html lang="zh-CN"> |
|
<head> |
|
<meta charset="UTF-8"> |
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
<title><?php echo htmlspecialchars($settings->getSetting('site_name')); ?></title> |
|
<link rel="icon" href="<?php echo htmlspecialchars($settings->getSetting('favicon_path')); ?>"> |
|
<link rel="stylesheet" href="/css/marked.css"> |
|
<link rel="stylesheet" href="/css/style.css"> |
|
</head> |
|
<body> |
|
<div class="container"> |
|
<h1><?php echo htmlspecialchars($settings->getSetting('site_name')); ?></h1> |
|
<p><?php echo htmlspecialchars($settings->getSetting('site_description')); ?></p> |
|
|
|
<?php if ($paste): ?> |
|
<div class="info"> |
|
浏览次数: <?php echo $paste['current_views']; ?>/<?php echo $paste['max_views'] ? $paste['max_views'] : '∞'; ?> |
|
| 过期时间: <?php |
|
date_default_timezone_set('Asia/Shanghai'); |
|
echo date('Y-m-d H:i:s', $paste['expires_at']); |
|
?> |
|
</div> |
|
<div id="content" <?php echo $paste['is_encrypted'] ? 'style="display:none;"' : ''; ?>> |
|
<?php if ($paste['is_markdown']): ?> |
|
<div id="markdown-content"></div> |
|
<?php else: ?> |
|
<pre><?php echo htmlspecialchars($paste['content']); ?></pre> |
|
<?php endif; ?> |
|
</div> |
|
<?php if ($paste['is_encrypted']): ?> |
|
<div id="decrypt-section"> |
|
<p>此内容已加密。解密密钥应该在URL的#后面。</p> |
|
<div id="decryption-error" style="color: red; display: none;"> |
|
解密失败。请检查解密密钥。 |
|
</div> |
|
</div> |
|
<?php endif; ?> |
|
<?php else: ?> |
|
<div class="tab-buttons"> |
|
<button class="tab-button active" data-tab="paste">URL分享</button> |
|
<button class="tab-button" data-tab="code">提取码分享</button> |
|
<button class="tab-button" data-tab="file">文件分享</button> |
|
</div> |
|
|
|
<!-- 原有的文本分享表单 --> |
|
<form id="pasteForm" style="display: block;"> |
|
<div class="editor-container"> |
|
<textarea name="content" placeholder="在此粘贴您要分享的内容"></textarea> |
|
<div class="markdown-preview" style="display: none;"></div> |
|
</div> |
|
|
|
<div class="options"> |
|
<div class="option"> |
|
<label>过期时间:</label> |
|
<select name="expire_time"> |
|
<option value="3600">1小时</option> |
|
<option value="86400">1天</option> |
|
<option value="604800">1周</option> |
|
<option value="2592000" selected>1个月</option> |
|
<option value="31536000">1年</option> |
|
</select> |
|
</div> |
|
<div class="option"> |
|
<label>最大浏览次数 (0表示无限制):</label> |
|
<input type="number" name="max_views" value="0" min="0" max="25565"> |
|
</div> |
|
<div class="option"> |
|
<label> |
|
<input type="checkbox" name="is_markdown"> 启用Markdown |
|
</label> |
|
</div> |
|
<div class="option"> |
|
<label> |
|
<input type="checkbox" name="is_encrypted"> 启用加密 |
|
</label> |
|
</div> |
|
</div> |
|
|
|
<div class="form-actions"> |
|
<button type="submit">创建笔记</button> |
|
</div> |
|
</form> |
|
|
|
<!-- 提取码分享表单 --> |
|
<form id="textShareForm" style="display: none;"> |
|
<div class="editor-container"> |
|
<textarea name="content" placeholder="在此输入您要分享的文本内容..."></textarea> |
|
</div> |
|
|
|
<div class="options"> |
|
<div class="option"> |
|
<label>过期时间:</label> |
|
<select name="expire_time"> |
|
<option value="3600">1小时</option> |
|
<option value="86400">1天</option> |
|
<option value="604800">1周</option> |
|
<option value="2592000" selected>1个月</option> |
|
<option value="31536000">1年</option> |
|
</select> |
|
</div> |
|
<div class="option"> |
|
<label>最大查看次数 (0表示无限制):</label> |
|
<input type="number" name="max_downloads" value="0" min="0"> |
|
</div> |
|
</div> |
|
|
|
<div class="form-actions"> |
|
<button type="submit">生成提取码</button> |
|
</div> |
|
</form> |
|
|
|
<!-- 文件上传表单 --> |
|
<form id="fileForm" style="display: none;"> |
|
<div class="file-upload-container"> |
|
<input type="file" name="file" id="fileInput"> |
|
<div class="file-info"></div> |
|
<div class="upload-progress" style="display: none;"> |
|
<div class="progress-bar"> |
|
<div class="progress-bar-fill"></div> |
|
</div> |
|
<div class="progress-text">0%</div> |
|
</div> |
|
</div> |
|
|
|
<div class="options"> |
|
<div class="option"> |
|
<label>过期时间:</label> |
|
<select name="expire_time"> |
|
<option value="3600">1小时</option> |
|
<option value="86400">1天</option> |
|
<option value="604800">1周</option> |
|
<option value="2592000" selected>1个月</option> |
|
<option value="31536000">1年</option> |
|
</select> |
|
</div> |
|
<div class="option"> |
|
<label>最大下载次数 (0表示无限制):</label> |
|
<input type="number" name="max_downloads" value="0" min="0"> |
|
</div> |
|
</div> |
|
|
|
<div class="form-actions"> |
|
<button type="submit">上传文件</button> |
|
</div> |
|
</form> |
|
|
|
<!-- 提取码输入区域 --> |
|
<div class="code-input-container"> |
|
<input type="text" id="codeInput" placeholder="输入提取码"> |
|
<button onclick="getFile()">获取内容</button> |
|
</div> |
|
|
|
<!-- 文件信息显示区域 --> |
|
<div id="fileInfo" style="display: none;"> |
|
<div class="info"> |
|
<span class="downloads"></span> |
|
<span class="expires"></span> |
|
</div> |
|
<div class="content"></div> |
|
</div> |
|
<?php endif; ?> |
|
</div> |
|
|
|
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script> |
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script> |
|
<script> |
|
// 修改获取网站域名的方法 |
|
const siteUrl = (() => { |
|
|
|
const forwardedHost = '<?php echo isset($_SERVER["HTTP_X_FORWARDED_HOST"]) ? $_SERVER["HTTP_X_FORWARDED_HOST"] : ""; ?>'; |
|
const forwardedProto = '<?php echo isset($_SERVER["HTTP_X_FORWARDED_PROTO"]) ? $_SERVER["HTTP_X_FORWARDED_PROTO"] : ""; ?>'; |
|
|
|
if (forwardedHost && forwardedProto) { |
|
return `${forwardedProto}: |
|
} |
|
|
|
|
|
const protocol = window.location.protocol; |
|
const host = window.location.host; |
|
return `${protocol} |
|
})(); |
|
|
|
<?php if ($paste && $paste['is_markdown']): ?> |
|
document.getElementById('markdown-content').innerHTML = marked.parse(<?php echo json_encode($paste['content']); ?>); |
|
<?php endif; ?> |
|
|
|
<?php if ($paste && $paste['is_encrypted']): ?> |
|
const encryptedContent = <?php echo json_encode($paste['content']); ?>; |
|
const decryptionKey = window.location.hash.substring(1); |
|
|
|
if (decryptionKey) { |
|
try { |
|
const decryptedBytes = CryptoJS.AES.decrypt(encryptedContent, decryptionKey); |
|
const decryptedContent = decryptedBytes.toString(CryptoJS.enc.Utf8); |
|
|
|
if (decryptedContent) { |
|
const content = document.getElementById('content'); |
|
content.style.display = 'block'; |
|
if (<?php echo $paste['is_markdown'] ? 'true' : 'false'; ?>) { |
|
|
|
const markdownContent = document.getElementById('markdown-content'); |
|
markdownContent.innerHTML = marked.parse(decryptedContent); |
|
|
|
|
|
markdownContent.querySelectorAll('img').forEach(img => { |
|
img.style.maxWidth = '100%'; // 改为100% |
|
img.style.height = 'auto'; |
|
img.style.maxHeight = '600px'; // 增加最大高度 |
|
img.style.margin = '0.5rem auto'; |
|
img.style.display = 'block'; |
|
|
|
// 添加点击放大功能 |
|
img.addEventListener('click', function(e) { |
|
e.preventDefault(); |
|
const modal = document.createElement('div'); |
|
modal.style.cssText = ` |
|
position: fixed; |
|
top: 0; |
|
left: 0; |
|
width: 100%; |
|
height: 100%; |
|
background: rgba(0, 0, 0, 0.9); |
|
display: flex; |
|
justify-content: center; |
|
align-items: center; |
|
z-index: 1000; |
|
cursor: zoom-out; |
|
`; |
|
|
|
const modalImg = document.createElement('img'); |
|
modalImg.src = this.src; |
|
modalImg.style.cssText = ` |
|
max-width: 90%; |
|
max-height: 90vh; |
|
object-fit: contain; |
|
border-radius: 4px; |
|
`; |
|
|
|
modal.appendChild(modalImg); |
|
document.body.appendChild(modal); |
|
|
|
modal.addEventListener('click', function() { |
|
document.body.removeChild(modal); |
|
}); |
|
}); |
|
}); |
|
} else { |
|
content.innerHTML = `<pre>${decryptedContent}</pre>`; |
|
} |
|
document.getElementById('decrypt-section').style.display = 'none'; |
|
} else { |
|
document.getElementById('decryption-error').style.display = 'block'; |
|
} |
|
} catch (e) { |
|
document.getElementById('decryption-error').style.display = 'block'; |
|
} |
|
} |
|
<?php endif; ?> |
|
|
|
if (document.getElementById('pasteForm')) { |
|
document.getElementById('pasteForm').onsubmit = async (e) => { |
|
e.preventDefault(); |
|
const formData = new FormData(e.target); |
|
const data = Object.fromEntries(formData.entries()); |
|
|
|
if (data.is_encrypted) { |
|
const key = CryptoJS.lib.WordArray.random(32).toString(); |
|
data.content = CryptoJS.AES.encrypt(data.content, key).toString(); |
|
data.encryption_key = key; |
|
} |
|
|
|
try { |
|
const response = await fetch('api.php', { |
|
method: 'POST', |
|
headers: { |
|
'Content-Type': 'application/json', |
|
}, |
|
body: JSON.stringify(data) |
|
}); |
|
|
|
const result = await response.json(); |
|
if (result.status === 'success') { |
|
let url = `${window.location.origin}/${result.uuid}`; |
|
if (data.is_encrypted) { |
|
url += '#' + result.encryption_key; |
|
} |
|
window.location.href = url; |
|
} else { |
|
alert('Error creating paste: ' + result.message); |
|
} |
|
} catch (error) { |
|
alert('Error creating paste: ' + error.message); |
|
} |
|
}; |
|
} |
|
document.addEventListener('DOMContentLoaded', function() { |
|
const markdownCheckbox = document.querySelector('input[name="is_markdown"]'); |
|
const editorContainer = document.querySelector('.editor-container'); |
|
const textarea = document.querySelector('textarea[name="content"]'); |
|
const markdownPreview = document.querySelector('.markdown-preview'); |
|
|
|
let isPreviewScrolling = false; |
|
let isEditorScrolling = false; |
|
let lastEditorScrollTop = 0; |
|
let lastPreviewScrollTop = 0; |
|
|
|
|
|
textarea.addEventListener('scroll', function() { |
|
if (!isPreviewScrolling && markdownPreview.style.display !== 'none') { |
|
isEditorScrolling = true; |
|
|
|
|
|
const editorScrollPercentage = this.scrollTop / (this.scrollHeight - this.clientHeight); |
|
const previewMaxScroll = markdownPreview.scrollHeight - markdownPreview.clientHeight; |
|
|
|
|
|
markdownPreview.scrollTop = previewMaxScroll * editorScrollPercentage; |
|
|
|
setTimeout(() => isEditorScrolling = false, 50); |
|
} |
|
}); |
|
|
|
|
|
|
|
|
|
|
|
markdownCheckbox.addEventListener('change', function() { |
|
if (this.checked) { |
|
editorContainer.classList.add('split-view'); |
|
markdownPreview.style.display = 'block'; |
|
|
|
markdownPreview.style.height = `${textarea.offsetHeight}px`; |
|
updatePreview(markdownPreview, textarea); |
|
} else { |
|
editorContainer.classList.remove('split-view'); |
|
markdownPreview.style.display = 'none'; |
|
} |
|
}); |
|
|
|
|
|
textarea.addEventListener('input', function() { |
|
updatePreview(markdownPreview, textarea); |
|
}); |
|
|
|
|
|
textarea.addEventListener('paste', async function(e) { |
|
const items = (e.clipboardData || e.originalEvent.clipboardData).items; |
|
|
|
for (let item of items) { |
|
if (item.type.indexOf('image') === 0) { |
|
e.preventDefault(); |
|
|
|
const blob = item.getAsFile(); |
|
const formData = new FormData(); |
|
formData.append('image', blob); |
|
|
|
try { |
|
|
|
const uploadingText = `![Uploading...]()\n`; |
|
const startPos = this.selectionStart; |
|
this.value = this.value.substring(0, startPos) + |
|
uploadingText + |
|
this.value.substring(this.selectionEnd); |
|
|
|
|
|
const response = await fetch('upload.php', { |
|
method: 'POST', |
|
body: formData |
|
}); |
|
|
|
const result = await response.json(); |
|
|
|
if (result.success) { |
|
|
|
const imageMarkdown = `\n`; |
|
const currentContent = this.value; |
|
const uploadingIndex = currentContent.indexOf(uploadingText); |
|
|
|
if (uploadingIndex !== -1) { |
|
this.value = currentContent.substring(0, uploadingIndex) + |
|
imageMarkdown + |
|
currentContent.substring(uploadingIndex + uploadingText.length); |
|
|
|
|
|
updatePreview(markdownPreview, textarea); |
|
} |
|
} else { |
|
|
|
alert('图片上传失败: ' + result.message); |
|
} |
|
} catch (error) { |
|
alert('图片上传出错: ' + error.message); |
|
} |
|
} |
|
} |
|
}); |
|
}); |
|
|
|
function updatePreview(markdownPreview, textarea) { |
|
if (markdownPreview && markdownPreview.style.display !== 'none') { |
|
try { |
|
const content = textarea.value || ''; |
|
const parsedContent = marked.parse(content); |
|
markdownPreview.innerHTML = parsedContent; |
|
|
|
|
|
markdownPreview.querySelectorAll('img').forEach(img => { |
|
img.addEventListener('click', function(e) { |
|
e.preventDefault(); |
|
// 创建模态框显示大图 |
|
const modal = document.createElement('div'); |
|
modal.style.cssText = ` |
|
position: fixed; |
|
top: 0; |
|
left: 0; |
|
width: 100%; |
|
height: 100%; |
|
background: rgba(0, 0, 0, 0.9); |
|
display: flex; |
|
justify-content: center; |
|
align-items: center; |
|
z-index: 1000; |
|
cursor: zoom-out; |
|
`; |
|
|
|
const modalImg = document.createElement('img'); |
|
modalImg.src = this.src; |
|
modalImg.style.cssText = ` |
|
max-width: 90%; |
|
max-height: 90vh; |
|
object-fit: contain; |
|
border-radius: 4px; |
|
`; |
|
|
|
modal.appendChild(modalImg); |
|
document.body.appendChild(modal); |
|
|
|
// 点击模态框关闭 |
|
modal.addEventListener('click', function() { |
|
document.body.removeChild(modal); |
|
}); |
|
}); |
|
}); |
|
} catch (error) { |
|
console.error('Markdown parsing error:', error); |
|
markdownPreview.innerHTML = '<p style="color: red;">Error parsing markdown content</p>'; |
|
} |
|
} |
|
} |
|
|
|
|
|
document.addEventListener('DOMContentLoaded', function() { |
|
|
|
const tabButtons = document.querySelectorAll('.tab-button'); |
|
const pasteForm = document.getElementById('pasteForm'); |
|
const textShareForm = document.getElementById('textShareForm'); |
|
const fileForm = document.getElementById('fileForm'); |
|
|
|
tabButtons.forEach(button => { |
|
button.addEventListener('click', function() { |
|
const tab = this.dataset.tab; |
|
|
|
// 更新按钮状态 |
|
tabButtons.forEach(btn => btn.classList.remove('active')); |
|
this.classList.add('active'); |
|
|
|
// 显示/隐藏表单 |
|
pasteForm.style.display = tab === 'paste' ? 'block' : 'none'; |
|
textShareForm.style.display = tab === 'code' ? 'block' : 'none'; |
|
fileForm.style.display = tab === 'file' ? 'block' : 'none'; |
|
}); |
|
}); |
|
|
|
|
|
if (textShareForm) { |
|
textShareForm.onsubmit = async (e) => { |
|
e.preventDefault(); |
|
const formData = new FormData(e.target); |
|
|
|
try { |
|
const response = await fetch('file_api.php', { |
|
method: 'POST', |
|
body: formData |
|
}); |
|
|
|
const result = await response.json(); |
|
if (result.status === 'success') { |
|
|
|
const shareUrl = `${window.location.origin}?code=${result.code}`; |
|
const modal = document.createElement('div'); |
|
modal.className = 'modal'; |
|
modal.innerHTML = ` |
|
<div class="modal-content"> |
|
<h3>分享成功!</h3> |
|
<div class="share-info"> |
|
<div class="copy-group"> |
|
<label>提取码:</label> |
|
<span class="copy-text" data-clipboard="${result.code}">${result.code}</span> |
|
<button class="copy-btn" onclick="copyText(this.previousElementSibling)">复制</button> |
|
</div> |
|
<div class="copy-group"> |
|
<label>分享链接:</label> |
|
<span class="copy-text" data-clipboard="${shareUrl}">${shareUrl}</span> |
|
<button class="copy-btn" onclick="copyText(this.previousElementSibling)">复制</button> |
|
</div> |
|
</div> |
|
<button class="close-btn" onclick="this.parentElement.parentElement.remove()">关闭</button> |
|
</div> |
|
`; |
|
document.body.appendChild(modal); |
|
} else { |
|
alert('分享失败:' + result.message); |
|
} |
|
} catch (error) { |
|
alert('分享出错:' + error.message); |
|
} |
|
}; |
|
} |
|
|
|
// 文件上传表单处理 |
|
if (fileForm) { |
|
const fileInput = document.getElementById('fileInput'); |
|
const fileInfo = document.querySelector('.file-info'); |
|
const progressBar = document.querySelector('.progress-bar-fill'); |
|
const progressText = document.querySelector('.progress-text'); |
|
const uploadProgress = document.querySelector('.upload-progress'); |
|
|
|
fileInput.addEventListener('change', function() { |
|
if (this.files[0]) { |
|
const file = this.files[0]; |
|
const size = (file.size / 1024 / 1024).toFixed(2); |
|
fileInfo.textContent = `文件名: ${file.name}, 大小: ${size}MB`; |
|
} |
|
}); |
|
|
|
fileForm.onsubmit = async (e) => { |
|
e.preventDefault(); |
|
const formData = new FormData(e.target); |
|
|
|
try { |
|
uploadProgress.style.display = 'block'; |
|
|
|
const xhr = new XMLHttpRequest(); |
|
xhr.upload.onprogress = (e) => { |
|
if (e.lengthComputable) { |
|
const percentComplete = Math.round((e.loaded / e.total) * 100); |
|
progressBar.style.width = percentComplete + '%'; |
|
progressText.textContent = percentComplete + '%'; |
|
} |
|
}; |
|
|
|
// 使用 Promise 包装 XHR 请求 |
|
const response = await new Promise((resolve, reject) => { |
|
xhr.onload = () => { |
|
if (xhr.status === 200) { |
|
try { |
|
resolve(JSON.parse(xhr.responseText)); |
|
} catch (e) { |
|
reject(new Error('解析响应失败')); |
|
} |
|
} else { |
|
reject(new Error('上传失败')); |
|
} |
|
}; |
|
xhr.onerror = () => reject(new Error('网络错误')); |
|
|
|
xhr.open('POST', 'file_api.php', true); |
|
xhr.send(formData); |
|
}); |
|
|
|
if (response.status === 'success') { |
|
const shareUrl = `${window.location.origin}?code=${response.code}`; |
|
const modal = document.createElement('div'); |
|
modal.className = 'modal'; |
|
modal.innerHTML = ` |
|
<div class="modal-content"> |
|
<h3>上传成功!</h3> |
|
<div class="share-info"> |
|
<div class="copy-group"> |
|
<label>提取码:</label> |
|
<span class="copy-text" data-clipboard="${response.code}">${response.code}</span> |
|
<button class="copy-btn" onclick="copyText(this.previousElementSibling)">复制</button> |
|
</div> |
|
<div class="copy-group"> |
|
<label>分享链接:</label> |
|
<span class="copy-text" data-clipboard="${shareUrl}">${shareUrl}</span> |
|
<button class="copy-btn" onclick="copyText(this.previousElementSibling)">复制</button> |
|
</div> |
|
</div> |
|
<button class="close-btn" onclick="this.parentElement.parentElement.remove()">关闭</button> |
|
</div> |
|
`; |
|
document.body.appendChild(modal); |
|
|
|
// 重置进度条 |
|
setTimeout(() => { |
|
uploadProgress.style.display = 'none'; |
|
progressBar.style.width = '0%'; |
|
progressText.textContent = '0%'; |
|
}, 1000); |
|
} else { |
|
alert('上传失败:' + response.message); |
|
} |
|
} catch (error) { |
|
alert('上传出错:' + error.message); |
|
} |
|
}; |
|
} |
|
}); |
|
|
|
// 修改获取文件函数 |
|
async function getFile() { |
|
const code = document.getElementById('codeInput').value.trim(); |
|
if (!code) { |
|
alert('请输入提取码'); |
|
return; |
|
} |
|
|
|
// 显示加载动画 |
|
const loadingModal = document.createElement('div'); |
|
loadingModal.className = 'modal'; |
|
loadingModal.innerHTML = ` |
|
<div class="modal-content"> |
|
<h3>正在获取内容...</h3> |
|
<div class="loading-spinner"></div> |
|
</div> |
|
`; |
|
document.body.appendChild(loadingModal); |
|
|
|
try { |
|
const response = await fetch(`file_api.php?code=${code}`); |
|
const result = await response.json(); |
|
|
|
if (result.status === 'success') { |
|
if (result.content) { |
|
// 文本内容 |
|
const fileInfo = document.getElementById('fileInfo'); |
|
fileInfo.style.display = 'block'; |
|
fileInfo.querySelector('.content').innerHTML = `<pre>${result.content}</pre>`; |
|
|
|
// 添加过期时间显示 |
|
const info = fileInfo.querySelector('.info'); |
|
if (info) { |
|
info.innerHTML = ` |
|
下载次数: ${result.current_downloads}/${result.max_downloads ? result.max_downloads : '∞'} |
|
| 过期时间: ${result.expires_at_formatted} |
|
`; |
|
} |
|
} else { |
|
// 文件下载 - 创建下载链接 |
|
const downloadUrl = `${siteUrl}/file_api.php?download=${code}&filename=${encodeURIComponent(result.filename)}`; |
|
window.location.href = downloadUrl; |
|
} |
|
} else { |
|
alert(result.message || '获取内容失败'); |
|
} |
|
} catch (error) { |
|
alert('获取文件失败:' + error.message); |
|
} finally { |
|
// 移除加载动画 |
|
loadingModal.remove(); |
|
} |
|
} |
|
|
|
// 添加复制功能 |
|
function copyText(element) { |
|
const text = element.getAttribute('data-clipboard'); |
|
navigator.clipboard.writeText(text).then(() => { |
|
// 显示复制成功提示 |
|
const originalText = element.nextElementSibling.textContent; |
|
element.nextElementSibling.textContent = '已复制!'; |
|
setTimeout(() => { |
|
element.nextElementSibling.textContent = originalText; |
|
}, 1000); |
|
}).catch(err => { |
|
console.error('复制失败:', err); |
|
}); |
|
} |
|
|
|
// 在 DOMContentLoaded 事件中添加自动填充提取码的功能 |
|
document.addEventListener('DOMContentLoaded', function() { |
|
// 检查 URL 中是否有提取码 |
|
const urlParams = new URLSearchParams(window.location.search); |
|
const code = urlParams.get('code'); |
|
if (code) { |
|
// 自动填充提取码并触发获取 |
|
const codeInput = document.getElementById('codeInput'); |
|
if (codeInput) { |
|
codeInput.value = code; |
|
getFile(); // 自动获取文件 |
|
} |
|
} |
|
// ... 其他现有的 DOMContentLoaded 代码 ... |
|
}); |
|
</script> |
|
|
|
<!-- 添加模态框样式 --> |
|
<style> |
|
.modal { |
|
position: fixed; |
|
top: 0; |
|
left: 0; |
|
width: 100%; |
|
height: 100%; |
|
background: rgba(0, 0, 0, 0.5); |
|
display: flex; |
|
justify-content: center; |
|
align-items: center; |
|
z-index: 1000; |
|
} |
|
|
|
.modal-content { |
|
background: var(--container-bg); |
|
padding: 2rem; |
|
border-radius: 8px; |
|
box-shadow: var(--shadow); |
|
text-align: center; |
|
} |
|
|
|
.modal-content h3 { |
|
margin-bottom: 1rem; |
|
} |
|
|
|
.modal-content strong { |
|
font-size: 1.2rem; |
|
color: var(--primary-color); |
|
} |
|
|
|
.modal-content button { |
|
margin-top: 1rem; |
|
padding: 0.5rem 1rem; |
|
background: var(--primary-color); |
|
color: white; |
|
border: none; |
|
border-radius: 4px; |
|
cursor: pointer; |
|
} |
|
|
|
.modal-content button:hover { |
|
background: var(--primary-hover); |
|
} |
|
</style> |
|
</body> |
|
</html> |
|
|