Typecho 249 3

    Typecho 批量插入附件 并实现图片预览[2025/04/25更新]

    在文章的附件选项页加入批量插入所有附件的按钮

    并自动识别图片与普通文件,实现图片预览功能

    2025-04-07T03:20:33.png
    2025-04-07T03:20:33.png

    Markdown语法格式自动修正为

    ![2025-04-07T02:49:18.png](https://img.imsun.org/2025/04/750116001.png)

    具体代码实现
    在主题的functions.php最后插入

    /**
     * Typecho后台附件增强:图片预览、批量插入、保留官方删除按钮与逻辑
     * @author jkjoy
     * @date 2025-04-25
     */
    Typecho_Plugin::factory('admin/write-post.php')->bottom = array('AttachmentHelper', 'addEnhancedFeatures');
    Typecho_Plugin::factory('admin/write-page.php')->bottom = array('AttachmentHelper', 'addEnhancedFeatures');
    
    class AttachmentHelper {
        public static function addEnhancedFeatures() {
            ?>
            <style>
            #file-list{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:15px;padding:15px;list-style:none;margin:0;}
            #file-list li{position:relative;border:1px solid #e0e0e0;border-radius:4px;padding:10px;background:#fff;transition:all 0.3s ease;list-style:none;margin:0;}
            #file-list li:hover{box-shadow:0 2px 8px rgba(0,0,0,0.1);}
            #file-list li.loading{opacity:0.7;pointer-events:none;}
            .att-enhanced-thumb{position:relative;width:100%;height:150px;margin-bottom:8px;background:#f5f5f5;overflow:hidden;border-radius:3px;display:flex;align-items:center;justify-content:center;}
            .att-enhanced-thumb img{width:100%;height:100%;object-fit:contain;display:block;}
            .att-enhanced-thumb .file-icon{display:flex;align-items:center;justify-content:center;width:100%;height:100%;font-size:40px;color:#999;}
            .att-enhanced-finfo{padding:5px 0;}
            .att-enhanced-fname{font-size:13px;margin-bottom:5px;word-break:break-all;color:#333;}
            .att-enhanced-fsize{font-size:12px;color:#999;}
            .att-enhanced-factions{display:flex;justify-content:space-between;align-items:center;margin-top:8px;gap:8px;}
            .att-enhanced-factions button{flex:1;padding:4px 8px;border:none;border-radius:3px;background:#e0e0e0;color:#333;cursor:pointer;font-size:12px;transition:all 0.2s ease;}
            .att-enhanced-factions button:hover{background:#d0d0d0;}
            .att-enhanced-factions .btn-insert{background:#467B96;color:white;}
            .att-enhanced-factions .btn-insert:hover{background:#3c6a81;}
            .att-enhanced-checkbox{position:absolute;top:5px;right:5px;z-index:2;width:18px;height:18px;cursor:pointer;}
            .batch-actions{margin:15px;display:flex;gap:10px;align-items:center;}
            .btn-batch{padding:8px 15px;border-radius:4px;border:none;cursor:pointer;transition:all 0.3s ease;font-size:10px;display:inline-flex;align-items:center;justify-content:center;}
            .btn-batch.primary{background:#467B96;color:white;}
            .btn-batch.primary:hover{background:#3c6a81;}
            .btn-batch.secondary{background:#e0e0e0;color:#333;}
            .btn-batch.secondary:hover{background:#d0d0d0;}
            .upload-progress{position:absolute;bottom:0;left:0;width:100%;height:2px;background:#467B96;transition:width 0.3s ease;}
            </style>
            <script>
            $(document).ready(function() {
                // 批量操作UI按钮
                var $batchActions = $('<div class="batch-actions"></div>')
                    .append('<button type="button" class="btn-batch primary" id="batch-insert">批量插入</button>')
                    .append('<button type="button" class="btn-batch secondary" id="select-all">全选</button>')
                    .append('<button type="button" class="btn-batch secondary" id="unselect-all">取消全选</button>');
                $('#file-list').before($batchActions);
    
                // 插入格式
                Typecho.insertFileToEditor = function(title, url, isImage) {
                    var textarea = $('#text'), 
                        sel = textarea.getSelection(),
                        insertContent = isImage ? '![' + title + '](' + url + ')' : 
                                                '[' + title + '](' + url + ')';
                    textarea.replaceSelection(insertContent + '\n');
                    textarea.focus();
                };
    
                // 批量插入
                $('#batch-insert').on('click', function(e) {
                    e.preventDefault();
                    e.stopPropagation();
                    var content = '';
                    $('#file-list li').each(function() {
                        if ($(this).find('.att-enhanced-checkbox').is(':checked')) {
                            var $li = $(this);
                            var title = $li.find('.att-enhanced-fname').text();
                            var url = $li.data('url');
                            var isImage = $li.data('image') == 1;
                            content += isImage ? '![' + title + '](' + url + ')\n' : '[' + title + '](' + url + ')\n';
                        }
                    });
                    if (content) {
                        var textarea = $('#text');
                        var pos = textarea.getSelection();
                        var newContent = textarea.val();
                        newContent = newContent.substring(0, pos.start) + content + newContent.substring(pos.end);
                        textarea.val(newContent);
                        textarea.focus();
                    }
                });
    
                $('#select-all').on('click', function(e) {
                    e.preventDefault();
                    e.stopPropagation();
                    $('#file-list .att-enhanced-checkbox').prop('checked', true);
                    return false;
                });
                $('#unselect-all').on('click', function(e) {
                    e.preventDefault();
                    e.stopPropagation();
                    $('#file-list .att-enhanced-checkbox').prop('checked', false);
                    return false;
                });
    
                // 防止复选框冒泡
                $(document).on('click', '.att-enhanced-checkbox', function(e) {e.stopPropagation();});
    
                // 增强文件列表样式,但不破坏li原结构和官方按钮
                function enhanceFileList() {
                    $('#file-list li').each(function() {
                        var $li = $(this);
                        if ($li.hasClass('att-enhanced')) return;
                        $li.addClass('att-enhanced');
                        // 只增强,不清空li
                        // 增加批量选择框
                        if ($li.find('.att-enhanced-checkbox').length === 0) {
                            $li.prepend('<input type="checkbox" class="att-enhanced-checkbox" />');
                        }
                        // 增加图片预览(如已有则不重复加)
                        if ($li.find('.att-enhanced-thumb').length === 0) {
                            var url = $li.data('url');
                            var isImage = $li.data('image') == 1;
                            var fileName = $li.find('.insert').text();
                            var $thumbContainer = $('<div class="att-enhanced-thumb"></div>');
                            if (isImage) {
                                var $img = $('<img src="' + url + '" alt="' + fileName + '" />');
                                $img.on('error', function() {
                                    $(this).replaceWith('<div class="file-icon">🖼️</div>');
                                });
                                $thumbContainer.append($img);
                            } else {
                                $thumbContainer.append('<div class="file-icon">📄</div>');
                            }
                            // 插到插入按钮之前
                            $li.find('.insert').before($thumbContainer);
                        }
    
                    });
                }
    
                // 插入按钮事件
                $(document).on('click', '.btn-insert', function(e) {
                    e.preventDefault();
                    e.stopPropagation();
                    var $li = $(this).closest('li');
                    var title = $li.find('.att-enhanced-fname').text();
                    Typecho.insertFileToEditor(title, $li.data('url'), $li.data('image') == 1);
                });
    
                // 上传完成后增强新项
                var originalUploadComplete = Typecho.uploadComplete;
                Typecho.uploadComplete = function(attachment) {
                    setTimeout(function() {
                        enhanceFileList();
                    }, 200);
                    if (typeof originalUploadComplete === 'function') {
                        originalUploadComplete(attachment);
                    }
                };
    
                // 首次增强
                enhanceFileList();
            });
            </script>
            <?php
        }
    }
    ?>
    老孙
    资深网民孙先生
    1. acevs

      2025-04-07 14:17

      mark不错。

        1. 老孙

          2025-04-08 11:59
          @acevs

          已知 有附件无法删除的问题

            1. 老孙

              2025-04-25 13:26
              @老孙

              已修复