首页 / 应用软件 / WordPress高级教程,开发内部知识库与文档协作中心

WordPress高级教程,开发内部知识库与文档协作中心

WordPress高级教程:开发内部知识库与文档协作中心

引言:WordPress的无限可能性

WordPress作为全球最流行的内容管理系统,早已超越了简单的博客平台定位。根据W3Techs的数据,截至2023年,WordPress占据了全球网站市场份额的43%,其中超过三分之一的顶级网站使用WordPress。这一成功不仅源于其用户友好的界面和丰富的插件生态,更得益于其高度可扩展的架构设计。

本教程将深入探讨如何通过WordPress的二次开发,构建一个功能完善的内部知识库与文档协作中心,并集成常用互联网小工具功能。我们将从基础架构设计开始,逐步深入到高级功能实现,最终打造一个集知识管理、团队协作和工具集成为一体的企业级平台。

第一部分:知识库系统架构设计

1.1 知识库内容模型设计

一个高效的知识库系统需要精心设计的内容架构。在WordPress中,我们可以通过自定义文章类型(Custom Post Types)和分类法(Taxonomies)来构建专业的知识库结构。

// 注册知识库自定义文章类型
function register_knowledgebase_post_type() {
    $labels = array(
        'name' => '知识库文章',
        'singular_name' => '知识库文章',
        'menu_name' => '知识库',
        'add_new' => '添加新文章',
        'add_new_item' => '添加新知识库文章',
        'edit_item' => '编辑知识库文章',
        'new_item' => '新知识库文章',
        'view_item' => '查看知识库文章',
        'search_items' => '搜索知识库文章',
        'not_found' => '未找到知识库文章',
        'not_found_in_trash' => '回收站中未找到知识库文章'
    );
    
    $args = array(
        'labels' => $labels,
        'public' => true,
        'publicly_queryable' => true,
        'show_ui' => true,
        'show_in_menu' => true,
        'query_var' => true,
        'rewrite' => array('slug' => 'knowledgebase'),
        'capability_type' => 'post',
        'has_archive' => true,
        'hierarchical' => false,
        'menu_position' => 5,
        'menu_icon' => 'dashicons-book',
        'supports' => array('title', 'editor', 'author', 'thumbnail', 'excerpt', 'comments', 'revisions', 'custom-fields'),
        'show_in_rest' => true, // 启用Gutenberg编辑器支持
    );
    
    register_post_type('knowledgebase', $args);
}
add_action('init', 'register_knowledgebase_post_type');

// 注册知识库分类法
function register_knowledgebase_taxonomies() {
    // 主分类
    register_taxonomy(
        'kb_category',
        'knowledgebase',
        array(
            'label' => '知识分类',
            'rewrite' => array('slug' => 'kb-category'),
            'hierarchical' => true,
            'show_admin_column' => true,
            'show_in_rest' => true,
        )
    );
    
    // 标签
    register_taxonomy(
        'kb_tag',
        'knowledgebase',
        array(
            'label' => '知识标签',
            'rewrite' => array('slug' => 'kb-tag'),
            'hierarchical' => false,
            'show_admin_column' => true,
            'show_in_rest' => true,
        )
    );
}
add_action('init', 'register_knowledgebase_taxonomies');

1.2 高级权限管理系统

内部知识库需要精细的权限控制。我们可以扩展WordPress的角色和权限系统,实现基于团队、部门和用户级别的访问控制。

// 添加自定义用户角色和权限
function add_knowledgebase_roles() {
    // 知识库编辑者角色
    add_role('kb_editor', '知识库编辑者', array(
        'read' => true,
        'edit_knowledgebase' => true,
        'edit_published_knowledgebase' => true,
        'publish_knowledgebase' => true,
        'delete_knowledgebase' => true,
        'delete_published_knowledgebase' => true,
        'upload_files' => true,
        'read_knowledgebase' => true,
    ));
    
    // 知识库审核者角色
    add_role('kb_reviewer', '知识库审核者', array(
        'read' => true,
        'edit_knowledgebase' => true,
        'edit_others_knowledgebase' => true,
        'edit_published_knowledgebase' => true,
        'publish_knowledgebase' => true,
        'read_private_knowledgebase' => true,
        'delete_knowledgebase' => true,
        'delete_published_knowledgebase' => true,
        'delete_private_knowledgebase' => true,
        'delete_others_knowledgebase' => true,
        'manage_knowledgebase_categories' => true,
    ));
}
add_action('init', 'add_knowledgebase_roles');

// 扩展用户权限
function add_knowledgebase_capabilities() {
    $roles = array('administrator', 'editor', 'kb_editor', 'kb_reviewer');
    
    foreach ($roles as $role_name) {
        $role = get_role($role_name);
        
        if ($role) {
            $role->add_cap('read_knowledgebase');
            $role->add_cap('edit_knowledgebase');
            $role->add_cap('edit_knowledgebases');
            $role->add_cap('edit_others_knowledgebases');
            $role->add_cap('publish_knowledgebases');
            $role->add_cap('read_private_knowledgebases');
        }
    }
}
add_action('admin_init', 'add_knowledgebase_capabilities');

第二部分:文档协作功能实现

2.1 实时协作编辑器集成

现代文档协作中心需要支持多人实时编辑。我们可以集成开源协作编辑器,如CKEditor 5或Quill,实现类似Google Docs的协作体验。

// 集成协作编辑器
function enqueue_collaborative_editor() {
    global $post;
    
    // 仅在知识库文章编辑页面加载
    if (is_admin() && isset($post) && $post->post_type === 'knowledgebase') {
        // 加载CKEditor 5
        wp_enqueue_script('ckeditor5', 'https://cdn.ckeditor.com/ckeditor5/36.0.1/super-build/ckeditor.js', array(), '36.0.1', true);
        
        // 加载协作插件
        wp_enqueue_script('collab-editor', get_template_directory_uri() . '/js/collab-editor.js', array('ckeditor5', 'jquery'), '1.0.0', true);
        
        // 传递必要参数
        wp_localize_script('collab-editor', 'collabConfig', array(
            'postId' => $post->ID,
            'userId' => get_current_user_id(),
            'userName' => wp_get_current_user()->display_name,
            'nonce' => wp_create_nonce('collab_editor_nonce'),
            'apiUrl' => rest_url('collab/v1/'),
        ));
    }
}
add_action('admin_enqueue_scripts', 'enqueue_collaborative_editor');

// 创建REST API端点处理实时协作
function register_collaboration_api() {
    register_rest_route('collab/v1', '/update/(?P<id>d+)', array(
        'methods' => 'POST',
        'callback' => 'handle_collaborative_update',
        'permission_callback' => function() {
            return current_user_can('edit_knowledgebase');
        },
        'args' => array(
            'id' => array(
                'validate_callback' => function($param, $request, $key) {
                    return is_numeric($param);
                }
            ),
        ),
    ));
    
    register_rest_route('collab/v1', '/presence/(?P<id>d+)', array(
        'methods' => 'GET',
        'callback' => 'get_active_users',
        'permission_callback' => function() {
            return current_user_can('read_knowledgebase');
        },
    ));
}
add_action('rest_api_init', 'register_collaboration_api');

function handle_collaborative_update(WP_REST_Request $request) {
    $post_id = $request->get_param('id');
    $content = $request->get_param('content');
    $user_id = get_current_user_id();
    
    // 验证权限
    if (!current_user_can('edit_post', $post_id)) {
        return new WP_Error('rest_forbidden', '您没有编辑此文章的权限', array('status' => 403));
    }
    
    // 更新文章内容
    wp_update_post(array(
        'ID' => $post_id,
        'post_content' => wp_kses_post($content)
    ));
    
    // 记录协作历史
    add_post_meta($post_id, '_collab_history', array(
        'user_id' => $user_id,
        'timestamp' => current_time('mysql'),
        'action' => 'edit'
    ));
    
    return new WP_REST_Response(array(
        'success' => true,
        'message' => '内容已更新'
    ), 200);
}

2.2 版本控制与历史记录

完善的文档协作需要完整的版本控制功能。我们可以扩展WordPress的修订版本系统,提供更强大的版本管理。

// 增强版本控制功能
class Enhanced_Revision_Manager {
    
    private $max_revisions = 50;
    
    public function __construct() {
        // 设置最大修订版本数
        add_filter('wp_revisions_to_keep', array($this, 'set_max_revisions'), 10, 2);
        
        // 添加版本比较功能
        add_action('add_meta_boxes', array($this, 'add_revision_comparison_meta_box'));
        
        // 添加版本标记功能
        add_action('post_submitbox_misc_actions', array($this, 'add_version_note_field'));
        add_action('save_post', array($this, 'save_version_note'));
    }
    
    public function set_max_revisions($num, $post) {
        if ($post->post_type === 'knowledgebase') {
            return $this->max_revisions;
        }
        return $num;
    }
    
    public function add_revision_comparison_meta_box() {
        add_meta_box(
            'revision-comparison',
            '版本比较',
            array($this, 'render_revision_comparison'),
            'knowledgebase',
            'side',
            'default'
        );
    }
    
    public function render_revision_comparison($post) {
        $revisions = wp_get_post_revisions($post->ID);
        
        if (count($revisions) > 1) {
            echo '<div class="revision-comparison">';
            echo '<select id="revision-from">';
            echo '<option value="">选择旧版本</option>';
            
            foreach ($revisions as $revision) {
                $author = get_userdata($revision->post_author);
                $date = date_i18n('Y-m-d H:i', strtotime($revision->post_modified));
                echo sprintf(
                    '<option value="%d">%s - %s</option>',
                    $revision->ID,
                    $date,
                    $author->display_name
                );
            }
            
            echo '</select>';
            echo '<select id="revision-to">';
            echo '<option value="">选择新版本</option>';
            
            foreach ($revisions as $revision) {
                $author = get_userdata($revision->post_author);
                $date = date_i18n('Y-m-d H:i', strtotime($revision->post_modified));
                echo sprintf(
                    '<option value="%d">%s - %s</option>',
                    $revision->ID,
                    $date,
                    $author->display_name
                );
            }
            
            echo '</select>';
            echo '<button id="compare-revisions" class="button">比较版本</button>';
            echo '<div id="revision-diff-result" style="margin-top:10px;"></div>';
            echo '</div>';
            
            // 添加比较脚本
            wp_enqueue_script('revision-diff', get_template_directory_uri() . '/js/revision-diff.js', array('jquery'), '1.0.0', true);
        } else {
            echo '<p>暂无历史版本</p>';
        }
    }
    
    public function add_version_note_field($post) {
        if ($post->post_type !== 'knowledgebase') return;
        
        echo '<div class="misc-pub-section">';
        echo '<label for="version-note">版本说明:</label>';
        echo '<input type="text" id="version-note" name="version_note" value="" placeholder="简要说明本次修改内容" style="width:100%;margin-top:5px;">';
        echo '</div>';
    }
    
    public function save_version_note($post_id) {
        if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return;
        if (!current_user_can('edit_post', $post_id)) return;
        if (!isset($_POST['version_note'])) return;
        
        $version_note = sanitize_text_field($_POST['version_note']);
        
        if (!empty($version_note)) {
            // 获取最新修订版本
            $revisions = wp_get_post_revisions($post_id);
            $latest_revision = reset($revisions);
            
            if ($latest_revision) {
                update_metadata('post', $latest_revision->ID, '_version_note', $version_note);
            }
        }
    }
}

new Enhanced_Revision_Manager();

第三部分:常用互联网小工具集成

3.1 代码片段管理器

对于技术团队,代码片段管理是知识库的重要功能。我们可以创建一个专门的代码片段管理器。

// 代码片段管理器
class Code_Snippet_Manager {
    
    public function __construct() {
        // 注册代码片段文章类型
        add_action('init', array($this, 'register_code_snippet_post_type'));
        
        // 添加上传代码文件支持
        add_filter('upload_mimes', array($this, 'add_code_mime_types'));
        
        // 添加代码高亮
        add_action('wp_enqueue_scripts', array($this, 'enqueue_code_highlight'));
        add_action('admin_enqueue_scripts', array($this, 'enqueue_code_highlight'));
        
        // 添加快捷码
        add_shortcode('code_snippet', array($this, 'code_snippet_shortcode'));
    }
    
    public function register_code_snippet_post_type() {
        $args = array(
            'public' => true,
            'label'  => '代码片段',
            'menu_icon' => 'dashicons-editor-code',
            'supports' => array('title', 'editor', 'author', 'custom-fields'),
            'show_in_rest' => true,
            'taxonomies' => array('post_tag', 'category'),
            'has_archive' => true,
        );
        
        register_post_type('code_snippet', $args);
    }
    
    public function add_code_mime_types($mimes) {
        $mimes['js'] = 'text/javascript';
        $mimes['php'] = 'text/php';
        $mimes['py'] = 'text/x-python';
        $mimes['java'] = 'text/x-java';
        $mimes['cpp'] = 'text/x-c++';
        $mimes['c'] = 'text/x-c';
        $mimes['sql'] = 'text/x-sql';
        $mimes['json'] = 'application/json';
        $mimes['xml'] = 'application/xml';
        return $mimes;
    }
    
    public function enqueue_code_highlight() {
        // 加载Prism.js代码高亮库
        wp_enqueue_style('prism-css', 'https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/themes/prism-tomorrow.min.css');
        wp_enqueue_script('prism-js', 'https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/prism.min.js', array(), '1.29.0', true);
        
        // 加载语言支持
        $languages = array('php', 'javascript', 'python', 'java', 'cpp', 'sql', 'json', 'bash');
        foreach ($languages as $lang) {
            wp_enqueue_script("prism-$lang", "https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-$lang.min.js", array('prism-js'), '1.29.0', true);
        }
    }
    
    public function code_snippet_shortcode($atts) {
        $atts = shortcode_atts(array(
            'id' => 0,
            'language' => 'php',
            'title' => '',
            'linenumbers' => 'true',
            'download' => 'false'
        ), $atts);
        
        $snippet_id = intval($atts['id']);
        
        if ($snippet_id <= 0) {
            return '<p>错误:未指定代码片段ID</p>';
        }
        
        $snippet = get_post($snippet_id);
        
        if (!$snippet || $snippet->post_type !== 'code_snippet') {
            return '<p>错误:代码片段不存在</p>';
        }
        
        $language = sanitize_text_field($atts['language']);
        $title = sanitize_text_field($atts['title']);
        $show_line_numbers = $atts['linenumbers'] === 'true';
        $show_download = $atts['download'] === 'true';
        
        $output = '<div class="code-snippet-container">';
        
        if (!empty($title)) {
            $output .= '<div class="code-snippet-header">';

$output .= '<h4>' . esc_html($title) . '</h4>';

        
        if ($show_download) {
            $output .= '<a href="' . get_permalink($snippet_id) . '?download=1" class="download-snippet" download>下载代码</a>';
        }
        
        $output .= '</div>';
    }
    
    $output .= '<pre class="' . ($show_line_numbers ? 'line-numbers' : '') . '">';
    $output .= '<code class="language-' . esc_attr($language) . '">';
    $output .= htmlspecialchars($snippet->post_content);
    $output .= '</code></pre>';
    
    // 添加代码信息
    $output .= '<div class="code-snippet-meta">';
    $output .= '<span>语言: ' . esc_html($language) . '</span>';
    $output .= '<span>作者: ' . get_the_author_meta('display_name', $snippet->post_author) . '</span>';
    $output .= '<span>更新: ' . get_the_modified_date('', $snippet_id) . '</span>';
    $output .= '</div>';
    
    $output .= '</div>';
    
    return $output;
}

}

new Code_Snippet_Manager();

// 代码片段下载处理
function handle_code_snippet_download() {

if (isset($_GET['download']) && is_singular('code_snippet')) {
    $post_id = get_the_ID();
    $post = get_post($post_id);
    
    if ($post && $post->post_type === 'code_snippet') {
        $filename = sanitize_title($post->post_title) . '.txt';
        $content = $post->post_content;
        
        header('Content-Type: text/plain');
        header('Content-Disposition: attachment; filename="' . $filename . '"');
        header('Content-Length: ' . strlen($content));
        
        echo $content;
        exit;
    }
}

}
add_action('template_redirect', 'handle_code_snippet_download');


### 3.2 API测试工具集成

为开发团队集成API测试工具,方便在知识库中直接测试和调试API接口。

// API测试工具
class API_Test_Tool {


public function __construct() {
    // 注册API测试文章类型
    add_action('init', array($this, 'register_api_test_post_type'));
    
    // 添加快捷码
    add_shortcode('api_tester', array($this, 'api_tester_shortcode'));
    
    // 添加REST API端点处理代理请求
    add_action('rest_api_init', array($this, 'register_api_proxy_endpoint'));
    
    // 加载前端资源
    add_action('wp_enqueue_scripts', array($this, 'enqueue_api_tester_assets'));
}

public function register_api_test_post_type() {
    $args = array(
        'public' => true,
        'label'  => 'API文档',
        'menu_icon' => 'dashicons-rest-api',
        'supports' => array('title', 'editor', 'custom-fields'),
        'show_in_rest' => true,
        'has_archive' => true,
    );
    
    register_post_type('api_doc', $args);
}

public function api_tester_shortcode($atts) {
    $atts = shortcode_atts(array(
        'id' => 0,
        'title' => 'API测试工具',
        'default_url' => '',
        'default_method' => 'GET',
        'default_headers' => '{"Content-Type": "application/json"}',
        'default_body' => '{}'
    ), $atts);
    
    $api_doc_id = intval($atts['id']);
    $api_data = array();
    
    if ($api_doc_id > 0) {
        $api_doc = get_post($api_doc_id);
        if ($api_doc && $api_doc->post_type === 'api_doc') {
            $api_data = array(
                'endpoint' => get_post_meta($api_doc_id, '_api_endpoint', true),
                'method' => get_post_meta($api_doc_id, '_api_method', true) ?: 'GET',
                'headers' => get_post_meta($api_doc_id, '_api_headers', true) ?: '{"Content-Type": "application/json"}',
                'body' => get_post_meta($api_doc_id, '_api_body', true) ?: '{}',
                'description' => $api_doc->post_content
            );
        }
    }
    
    ob_start();
    ?>
    <div class="api-tester-container" data-doc-id="<?php echo esc_attr($api_doc_id); ?>">
        <div class="api-tester-header">
            <h3><?php echo esc_html($atts['title']); ?></h3>
            <div class="api-tester-actions">
                <button class="btn-run-api">发送请求</button>
                <button class="btn-save-api">保存配置</button>
                <button class="btn-clear-api">清空</button>
            </div>
        </div>
        
        <div class="api-tester-form">
            <div class="form-group">
                <label>请求方法:</label>
                <select class="api-method">
                    <option value="GET" <?php selected($api_data['method'] ?? $atts['default_method'], 'GET'); ?>>GET</option>
                    <option value="POST" <?php selected($api_data['method'] ?? $atts['default_method'], 'POST'); ?>>POST</option>
                    <option value="PUT" <?php selected($api_data['method'] ?? $atts['default_method'], 'PUT'); ?>>PUT</option>
                    <option value="DELETE" <?php selected($api_data['method'] ?? $atts['default_method'], 'DELETE'); ?>>DELETE</option>
                    <option value="PATCH" <?php selected($api_data['method'] ?? $atts['default_method'], 'PATCH'); ?>>PATCH</option>
                </select>
                
                <label class="url-label">请求URL:</label>
                <input type="text" class="api-url" 
                       value="<?php echo esc_attr($api_data['endpoint'] ?? $atts['default_url']); ?>" 
                       placeholder="https://api.example.com/endpoint">
            </div>
            
            <div class="form-group">
                <label>请求头:</label>
                <textarea class="api-headers" rows="4"><?php 
                    echo esc_textarea($api_data['headers'] ?? $atts['default_headers']); 
                ?></textarea>
            </div>
            
            <div class="form-group">
                <label>请求体:</label>
                <textarea class="api-body" rows="8"><?php 
                    echo esc_textarea($api_data['body'] ?? $atts['default_body']); 
                ?></textarea>
            </div>
            
            <?php if (!empty($api_data['description'])): ?>
            <div class="api-description">
                <h4>API说明:</h4>
                <div><?php echo wp_kses_post($api_data['description']); ?></div>
            </div>
            <?php endif; ?>
        </div>
        
        <div class="api-tester-response">
            <div class="response-header">
                <h4>响应结果</h4>
                <div class="response-status">
                    <span class="status-label">状态:</span>
                    <span class="status-code">-</span>
                    <span class="status-time">时间: <span class="time-value">-</span>ms</span>
                </div>
            </div>
            <div class="response-body">
                <pre><code class="language-json">等待请求...</code></pre>
            </div>
        </div>
    </div>
    <?php
    return ob_get_clean();
}

public function register_api_proxy_endpoint() {
    register_rest_route('api-tester/v1', '/proxy', array(
        'methods' => 'POST',
        'callback' => array($this, 'handle_api_proxy_request'),
        'permission_callback' => function() {
            // 仅限登录用户使用
            return is_user_logged_in();
        },
    ));
}

public function handle_api_proxy_request(WP_REST_Request $request) {
    $url = sanitize_url($request->get_param('url'));
    $method = sanitize_text_field($request->get_param('method'));
    $headers = $request->get_param('headers');
    $body = $request->get_param('body');
    
    // 验证URL
    if (empty($url) || !filter_var($url, FILTER_VALIDATE_URL)) {
        return new WP_Error('invalid_url', '无效的URL地址', array('status' => 400));
    }
    
    // 解析headers
    $headers_array = array();
    if (!empty($headers)) {
        $headers_data = json_decode($headers, true);
        if (is_array($headers_data)) {
            foreach ($headers_data as $key => $value) {
                $headers_array[sanitize_text_field($key)] = sanitize_text_field($value);
            }
        }
    }
    
    // 发送请求
    $start_time = microtime(true);
    
    $args = array(
        'method' => $method,
        'headers' => $headers_array,
        'timeout' => 30,
        'sslverify' => false,
    );
    
    if (in_array($method, array('POST', 'PUT', 'PATCH')) && !empty($body)) {
        $args['body'] = $body;
    }
    
    $response = wp_remote_request($url, $args);
    $end_time = microtime(true);
    
    $response_time = round(($end_time - $start_time) * 1000, 2);
    
    if (is_wp_error($response)) {
        return array(
            'success' => false,
            'error' => $response->get_error_message(),
            'response_time' => $response_time
        );
    }
    
    $response_code = wp_remote_retrieve_response_code($response);
    $response_body = wp_remote_retrieve_body($response);
    $response_headers = wp_remote_retrieve_headers($response);
    
    // 尝试解析JSON响应
    $json_response = json_decode($response_body);
    if (json_last_error() === JSON_ERROR_NONE) {
        $formatted_body = json_encode($json_response, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
    } else {
        $formatted_body = $response_body;
    }
    
    return array(
        'success' => true,
        'status_code' => $response_code,
        'headers' => $response_headers,
        'body' => $formatted_body,
        'response_time' => $response_time,
        'size' => strlen($response_body)
    );
}

public function enqueue_api_tester_assets() {
    wp_enqueue_style('api-tester-css', get_template_directory_uri() . '/css/api-tester.css');
    wp_enqueue_script('api-tester-js', get_template_directory_uri() . '/js/api-tester.js', array('jquery'), '1.0.0', true);
    
    wp_localize_script('api-tester-js', 'apiTesterConfig', array(
        'ajax_url' => admin_url('admin-ajax.php'),
        'rest_url' => rest_url('api-tester/v1/'),
        'nonce' => wp_create_nonce('api_tester_nonce')
    ));
}

}

new API_Test_Tool();


### 3.3 数据可视化工具

集成数据可视化工具,支持在知识库中直接创建和展示图表。

// 数据可视化工具
class Data_Visualization_Tool {


public function __construct() {
    // 注册图表文章类型
    add_action('init', array($this, 'register_chart_post_type'));
    
    // 添加快捷码
    add_shortcode('chart', array($this, 'chart_shortcode'));
    
    // 添加图表编辑器元框
    add_action('add_meta_boxes', array($this, 'add_chart_editor_meta_box'));
    add_action('save_post_chart', array($this, 'save_chart_data'));
    
    // 加载图表库
    add_action('wp_enqueue_scripts', array($this, 'enqueue_chart_library'));
}

public function register_chart_post_type() {
    $args = array(
        'public' => true,
        'label'  => '数据图表',
        'menu_icon' => 'dashicons-chart-line',
        'supports' => array('title', 'author'),
        'show_in_rest' => true,
        'has_archive' => true,
    );
    
    register_post_type('chart', $args);
}

public function add_chart_editor_meta_box() {
    add_meta_box(
        'chart-editor',
        '图表编辑器',
        array($this, 'render_chart_editor'),
        'chart',
        'normal',
        'high'
    );
}

public function render_chart_editor($post) {
    wp_nonce_field('save_chart_data', 'chart_data_nonce');
    
    $chart_type = get_post_meta($post->ID, '_chart_type', true) ?: 'line';
    $chart_data = get_post_meta($post->ID, '_chart_data', true) ?: '{}';
    $chart_options = get_post_meta($post->ID, '_chart_options', true) ?: '{}';
    
    ?>
    <div class="chart-editor-container">
        <div class="chart-settings">
            <div class="setting-group">
                <label for="chart-type">图表类型:</label>
                <select id="chart-type" name="chart_type">
                    <option value="line" <?php selected($chart_type, 'line'); ?>>折线图</option>
                    <option value="bar" <?php selected($chart_type, 'bar'); ?>>柱状图</option>
                    <option value="pie" <?php selected($chart_type, 'pie'); ?>>饼图</option>
                    <option value="doughnut" <?php selected($chart_type, 'doughnut'); ?>>环形图</option>
                    <option value="radar" <?php selected($chart_type, 'radar'); ?>>雷达图</option>
                    <option value="scatter" <?php selected($chart_type, 'scatter'); ?>>散点图</option>
                </select>
            </div>
            
            <div class="setting-group">
                <label for="chart-data">图表数据 (JSON格式):</label>
                <textarea id="chart-data" name="chart_data" rows="10"><?php echo esc_textarea($chart_data); ?></textarea>
                <p class="description">示例: {"labels": ["一月", "二月", "三月"], "datasets": [{"label": "销售额", "data": [65, 59, 80]}]}</p>
            </div>
            
            <div class="setting-group">
                <label for="chart-options">图表选项 (JSON格式):</label>
                <textarea id="chart-options" name="chart_options" rows="10"><?php echo esc_textarea($chart_options); ?></textarea>
                <p class="description">配置图表显示选项,如颜色、标题等</p>
            </div>
        </div>
        
        <div class="chart-preview">
            <h4>预览:</h4>
            <canvas id="chart-preview-canvas" width="400" height="300"></canvas>
        </div>
    </div>
    
    <style>
    .chart-editor-container {
        display: flex;
        gap: 20px;
    }
    .chart-settings {
        flex: 1;
    }
    .chart-preview {
        flex: 1;
    }
    .setting-group {
        margin-bottom: 15px;
    }
    .setting-group label {
        display: block;
        margin-bottom: 5px;
        font-weight: bold;
    }
    .setting-group textarea,
    .setting-group select {
        width: 100%;
        padding: 8px;
    }
    </style>
    
    <script>
    jQuery(document).ready(function($) {
        function updateChartPreview() {
            var type = $('#chart-type').val();
            var data = $('#chart-data').val();
            var options = $('#chart-options').val();
            
            try {
                var chartData = JSON.parse(data);
                var chartOptions = JSON.parse(options);
                
                var ctx = document.getElementById('chart-preview-canvas').getContext('2d');
                
                // 销毁现有图表
                if (window.previewChart) {
                    window.previewChart.destroy();
                }
                
                // 创建新图表
                window.previewChart = new Chart(ctx, {
                    type: type,
                    data: chartData,
                    options: chartOptions
                });
            } catch (e) {
                console.error('图表数据解析错误:', e);
            }
        }
        
        // 监听输入变化
        $('#chart-type, #chart-data, #chart-options').on('change keyup', function() {
            updateChartPreview();
        });
        
        // 初始预览
        updateChartPreview();
    });
    </script>
    <?php
}

public function save_chart_data($post_id) {
    if (!isset($_POST['chart_data_nonce']) || 
        !wp_verify_nonce($_POST['chart_data_nonce'], 'save_chart_data')) {
        return;
    }
    
    if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return;
    if (!current_user_can('edit_post', $post_id)) return;
    
    if (isset($_POST['chart_type'])) {
        update_post_meta($post_id, '_chart_type', sanitize_text_field($_POST['chart_type']));
    }
    
    if (isset($_POST['chart_data'])) {
        // 验证JSON格式
        $chart_data = stripslashes($_POST['chart_data']);
        json_decode($chart_data);
        if (json_last_error() === JSON_ERROR_NONE) {
            update_post_meta($
本文来自网络,不代表柔性供应链服务中心立场,转载请注明出处:https://mall.org.cn/5110.html

EXCHANGES®作者

上一篇
下一篇

为您推荐

发表回复

联系我们

联系我们

18559313275

在线咨询: QQ交谈

邮箱: vip@exchanges.center

工作时间:周一至周五,9:00-17:30,节假日休息
返回顶部