Files
file-upload/file-upload.php
2026-06-05 10:23:33 +08:00

444 lines
16 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php if(!defined('__TYPECHO_ADMIN__')) exit; ?>
<?php
if (isset($post) || isset($page)) {
$cid = isset($post) ? $post->cid : $page->cid;
if ($cid) {
\Widget\Contents\Attachment\Related::alloc(['parentId' => $cid])->to($attachment);
} else {
\Widget\Contents\Attachment\Unattached::alloc()->to($attachment);
}
}
?>
<div id="upload-panel" class="p">
<div class="upload-area" data-url="<?php $security->index('/action/upload'); ?>">
<?php _e('拖放文件到这里<br>或者 %s选择文件上传%s', '<a href="###" class="upload-file">', '</a>'); ?>
</div>
<ul id="file-list">
<?php while ($attachment->next()): ?>
<li data-cid="<?php $attachment->cid(); ?>" data-url="<?php echo $attachment->attachment->url; ?>" data-image="<?php echo $attachment->attachment->isImage ? 1 : 0; ?>"><input type="hidden" name="attachment[]" value="<?php $attachment->cid(); ?>" />
<a class="insert" title="<?php _e('点击插入文件'); ?>" href="###"><?php $attachment->title(); ?></a>
<div class="info">
<?php echo number_format(ceil($attachment->attachment->size / 1024)); ?> Kb
<a class="file" target="_blank" href="<?php $options->adminUrl('media.php?cid=' . $attachment->cid); ?>" title="<?php _e('编辑'); ?>"><i class="i-edit"></i></a>
<a href="###" class="delete" title="<?php _e('删除'); ?>"><i class="i-delete"></i></a>
</div>
</li>
<?php endwhile; ?>
</ul>
</div>
<style>
#upload-notice {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 99999;
background: rgba(0, 0, 0, 0.8);
color: #fff;
padding: 60px 150px;
border-radius: 4px;
font-size: 16px;
text-align: center;
white-space: nowrap;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
animation: fadeInOut 3s ease-in-out forwards;
pointer-events: none;
}
@keyframes fadeInOut {
0% { opacity: 0; }
10% { opacity: 1; }
90% { opacity: 1; }
100% { opacity: 0; visibility: hidden; }
}
</style>
<script>
(function() {
// 防止重复初始化
if (window._uploadFinalFixed) return;
window._uploadFinalFixed = true;
var uploadUrl = document.querySelector('.upload-area').getAttribute('data-url');
var fileList = document.getElementById('file-list');
var isUploading = false;
var isSelecting = false;
// 显示居中提示
function showNotice(message) {
var oldNotice = document.getElementById('upload-notice');
if (oldNotice) {
oldNotice.remove();
}
var notice = document.createElement('div');
notice.id = 'upload-notice';
notice.textContent = message;
document.body.appendChild(notice);
setTimeout(function() {
var n = document.getElementById('upload-notice');
if (n) n.remove();
}, 3000);
}
// 获取当前文章cid
function getCurrentCid() {
var cidInput = document.querySelector('input[name="cid"]');
return cidInput && cidInput.value ? cidInput.value : '';
}
// 激活附件菜单(切换到附件选项卡)
function activateAttachmentsMenu() {
// 根据实际HTML结构附件选项卡的ID是 tab-files-btn
var attachmentsTab = document.getElementById('tab-files-btn');
if (!attachmentsTab) {
// 备用选择器
attachmentsTab = document.querySelector('a[href="#tab-files"]');
}
if (!attachmentsTab) {
// 再尝试查找包含"附件"文字的选项卡
var allTabs = document.querySelectorAll('.typecho-option-tabs li a');
for (var i = 0; i < allTabs.length; i++) {
var text = allTabs[i].innerText || allTabs[i].textContent;
if (text && text.indexOf('附件') !== -1) {
attachmentsTab = allTabs[i];
break;
}
}
}
if (attachmentsTab) {
// 检查是否已经是激活状态
var parentLi = attachmentsTab.parentNode;
if (parentLi && parentLi.className.indexOf('active') !== -1) {
return; // 已经是激活状态,不需要切换
}
// 模拟点击附件选项卡
if (typeof attachmentsTab.click === 'function') {
attachmentsTab.click();
} else if (typeof jQuery !== 'undefined') {
jQuery(attachmentsTab).trigger('click');
}
// 手动切换选项卡内容
var tabFiles = document.getElementById('tab-files');
var tabAdvance = document.getElementById('tab-advance');
if (tabFiles && tabAdvance) {
tabFiles.classList.remove('hidden');
tabAdvance.classList.add('hidden');
}
// 更新选项卡样式
if (parentLi) {
var allTabsLis = document.querySelectorAll('.typecho-option-tabs li');
for (var i = 0; i < allTabsLis.length; i++) {
allTabsLis[i].classList.remove('active');
}
parentLi.classList.add('active');
}
}
}
// 刷新附件列表(不刷新整个页面)
function refreshAttachmentList() {
var cid = getCurrentCid();
var url = window.location.origin + '/admin/ajax/attachment-list?cid=' + cid;
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.onload = function() {
if (xhr.status === 200) {
try {
var data = JSON.parse(xhr.responseText);
if (data && data.html) {
// 保存当前滚动位置
var scrollTop = window.pageYOffset || document.documentElement.scrollTop;
// 更新附件列表
fileList.innerHTML = data.html;
// 重新绑定事件
document.querySelectorAll('#file-list li').forEach(bindFileEvents);
// 恢复滚动位置
window.scrollTo(0, scrollTop);
// 更新附件数量显示
updateAttachmentCount();
// 上传成功后激活附件菜单
activateAttachmentsMenu();
} else {
// 降级方案:刷新整个页面
window.location.reload();
}
} catch(e) {
window.location.reload();
}
} else {
window.location.reload();
}
};
xhr.onerror = function() {
window.location.reload();
};
xhr.send();
}
// 更新附件数量显示
function updateAttachmentCount() {
var attachmentCount = fileList.children.length;
var tabBtn = document.getElementById('tab-files-btn');
if (tabBtn) {
var balloon = tabBtn.querySelector('.balloon');
if (!balloon && attachmentCount > 0) {
balloon = document.createElement('span');
balloon.className = 'balloon';
tabBtn.appendChild(balloon);
}
if (balloon) {
balloon.textContent = attachmentCount;
if (attachmentCount === 0) {
balloon.style.display = 'none';
} else {
balloon.style.display = '';
}
}
}
}
// 上传文件
function uploadFiles(files) {
if (!files || files.length === 0 || isUploading) return;
isUploading = true;
var total = files.length;
var completed = 0;
var successCount = 0;
var failCount = 0;
function checkComplete() {
if (completed === total) {
isUploading = false;
if (successCount > 0 || failCount > 0) {
var message = '';
if (successCount > 0 && failCount > 0) {
message = '已成功上传 ' + successCount + ' 个附件,失败 ' + failCount + ' 个附件。';
} else if (successCount > 0) {
message = '已成功上传 ' + successCount + ' 个附件。';
} else if (failCount > 0) {
message = '上传失败 ' + failCount + ' 个附件。';
}
showNotice(message);
}
if (successCount > 0) {
// 上传成功后刷新附件列表(会自动激活附件菜单)
refreshAttachmentList();
}
}
}
for (var i = 0; i < files.length; i++) {
(function(file) {
var formData = new FormData();
formData.append('file', file);
var url = uploadUrl;
var cid = getCurrentCid();
if (cid) {
url = uploadUrl + '?cid=' + cid;
}
var xhr = new XMLHttpRequest();
xhr.open('POST', url, true);
xhr.onload = function() {
completed++;
if (xhr.status === 200) {
try {
var response = JSON.parse(xhr.responseText);
if (response && response[1] && response[1].cid) {
successCount++;
} else {
failCount++;
}
} catch(e) {
failCount++;
}
} else {
failCount++;
}
checkComplete();
};
xhr.onerror = function() {
completed++;
failCount++;
checkComplete();
};
xhr.send(formData);
})(files[i]);
}
}
function bindFileEvents(li) {
// 插入按钮
var insertBtn = li.querySelector('.insert');
if (insertBtn) {
insertBtn.onclick = function(e) {
e.preventDefault();
var url = li.getAttribute('data-url');
var isImage = li.getAttribute('data-image') === '1';
var title = insertBtn.innerText;
var textarea = document.querySelector('#text, .wmd-input');
if (textarea) {
var insertText = isImage ? '![](' + url + ')' : '<a href="' + url + '">' + title + '</a>';
insertAtCursor(textarea, insertText);
}
return false;
};
}
// 删除按钮
var deleteBtn = li.querySelector('.delete');
if (deleteBtn) {
deleteBtn.onclick = function(e) {
e.preventDefault();
var cid = li.getAttribute('data-cid');
if (confirm('确定要删除这个附件吗?')) {
var xhr = new XMLHttpRequest();
xhr.open('POST', window.location.origin + '/action/upload?do=delete&cid=' + cid, true);
xhr.onload = function() {
if (xhr.status === 200) {
li.remove();
// 更新附件数量
updateAttachmentCount();
// 删除后如果列表为空,保持在附件菜单
if (fileList.children.length === 0) {
activateAttachmentsMenu();
}
}
};
xhr.send();
}
return false;
};
}
}
function insertAtCursor(textarea, text) {
if (textarea.selectionStart !== undefined) {
var start = textarea.selectionStart;
var end = textarea.selectionEnd;
textarea.value = textarea.value.substring(0, start) + text + textarea.value.substring(end);
textarea.selectionStart = textarea.selectionEnd = start + text.length;
} else if (textarea.createTextRange) {
var range = textarea.createTextRange();
range.collapse(true);
range.pasteHTML(text);
}
textarea.focus();
}
// 绑定现有列表项
document.querySelectorAll('#file-list li').forEach(bindFileEvents);
// 更新初始附件数量
updateAttachmentCount();
// 获取上传链接
var uploadLink = document.querySelector('.upload-file');
if (uploadLink) {
// 移除原有的 onclick 属性
uploadLink.removeAttribute('onclick');
// 解绑 jQuery 事件
if (typeof jQuery !== 'undefined') {
jQuery(uploadLink).off('click');
}
// 添加新的事件监听
uploadLink.addEventListener('click', function(e) {
e.preventDefault();
e.stopPropagation();
e.stopImmediatePropagation();
if (isUploading) {
return false;
}
if (isSelecting) {
return false;
}
isSelecting = true;
var input = document.createElement('input');
input.type = 'file';
input.multiple = true;
input.setAttribute('multiple', 'multiple');
input.style.position = 'fixed';
input.style.left = '-9999px';
input.style.top = '-9999px';
input.style.opacity = '0';
document.body.appendChild(input);
var cleanup = function() {
setTimeout(function() {
if (input && input.parentNode) {
input.parentNode.removeChild(input);
}
isSelecting = false;
}, 100);
};
input.onchange = function(e) {
var files = input.files;
cleanup();
if (files && files.length > 0) {
uploadFiles(files);
}
};
input.click();
return false;
}, true);
}
// 拖放上传
var uploadArea = document.querySelector('.upload-area');
if (uploadArea) {
if (typeof jQuery !== 'undefined') {
jQuery(uploadArea).off('drop dragover');
}
uploadArea.ondrop = function(e) {
e.preventDefault();
e.stopPropagation();
if (isUploading) {
return false;
}
var files = e.dataTransfer.files;
if (files && files.length > 0) {
uploadFiles(files);
}
return false;
};
uploadArea.ondragover = function(e) {
e.preventDefault();
e.stopPropagation();
return false;
};
}
// 确保初始时如果 URL 包含 #tab-files激活附件菜单
if (window.location.hash === '#tab-files') {
activateAttachmentsMenu();
}
})();
</script>