首页 / 应用软件 / 一步步教你,在WordPress中添加网站内容自动生成思维导图与知识图谱工具

一步步教你,在WordPress中添加网站内容自动生成思维导图与知识图谱工具

一步步教你,在WordPress中添加网站内容自动生成思维导图与知识图谱工具

引言:当WordPress遇见知识可视化

在信息爆炸的时代,网站内容的管理和呈现方式直接影响着用户体验和知识传递效率。传统的线性文章结构虽然清晰,却难以展现复杂概念间的关联性。想象一下,当读者浏览一篇关于“人工智能发展史”的长文时,如果能同时看到一个动态生成的思维导图,清晰展示从图灵测试到深度学习的关键节点及其关联,理解效率将大幅提升。

WordPress作为全球最流行的内容管理系统,其强大之处不仅在于开箱即用的功能,更在于无限的可扩展性。通过代码二次开发,我们可以将这种知识可视化能力直接集成到WordPress中,让每一篇文章、每一个知识点都能自动转化为结构化的思维导图和知识图谱。

本文将详细指导您如何通过WordPress代码二次开发,实现网站内容的自动可视化,不仅提升用户体验,也为您的网站增添独特的智能工具功能。

第一部分:理解基础概念与技术选型

1.1 思维导图与知识图谱的核心区别

在开始技术实现之前,我们需要明确两个核心概念:

思维导图(Mind Map)是一种放射状的树形结构,以一个中心主题出发,逐级展开相关子主题,强调发散性思维和记忆关联。它适合用于内容摘要、思路整理和快速浏览。

知识图谱(Knowledge Graph)则是更为复杂的网络结构,由实体、属性和关系构成,能够表达多对多的复杂关联。它更适合表现深层次的知识体系和概念间的多维联系。

在WordPress中实现这两种可视化工具,需要根据内容类型和用户需求进行选择。例如,教程类文章更适合思维导图,而学术类或产品比较类内容则更适合知识图谱。

1.2 技术栈选择与评估

实现这一功能,我们需要考虑以下技术组件:

前端可视化库:

  • Mind Map库:Markmap、jsMind、MindElixir都是优秀的选择。Markmap基于Markdown,与WordPress编辑器兼容性好;jsMind功能丰富,支持多种布局;MindElixir界面现代,交互流畅。
  • 知识图谱库:Vis.js、D3.js、Cytoscape.js。Vis.js易于上手,性能良好;D3.js功能强大但学习曲线陡峭;Cytoscape.js专为复杂网络设计,适合大型知识图谱。

后端处理方案:

  • 纯前端方案:内容直接在前端解析生成,适合小型网站,减轻服务器压力。
  • 前后端结合:后端预处理内容结构,前端负责渲染,适合内容复杂、需要优化的场景。
  • API服务集成:利用第三方NLP服务进行内容分析,适合需要深度语义理解的场景。

WordPress集成方式:

  • 短代码(Shortcode)实现:最简单的方式,通过短代码嵌入可视化内容
  • Gutenberg块开发:现代WordPress编辑器的原生扩展方式
  • 元数据字段扩展:为文章添加结构化数据字段
  • 独立插件开发:最灵活、可复用性最高的方式

考虑到可维护性和扩展性,本文将采用Gutenberg块开发为主,短代码为辅的混合方案。

第二部分:开发环境搭建与基础配置

2.1 本地开发环境配置

在开始编码前,我们需要搭建合适的开发环境:

  1. 本地服务器环境:推荐使用Local by Flywheel或XAMPP,它们提供了完整的PHP+MySQL环境,并针对WordPress进行了优化。
  2. 代码编辑器:VS Code是当前最流行的选择,安装以下扩展:

    • PHP Intelephense(PHP智能提示)
    • WordPress Snippet(WordPress代码片段)
    • ESLint(JavaScript代码检查)
    • GitLens(版本管理)
  3. 浏览器开发工具:Chrome DevTools是前端调试的必备工具,特别是Elements和Console面板。
  4. 版本控制:初始化Git仓库,定期提交代码变更。

2.2 创建自定义插件框架

我们首先创建一个独立的插件,避免直接修改主题文件:

<?php
/**
 * Plugin Name: Content Visualizer - Mind Map & Knowledge Graph
 * Plugin URI: https://yourwebsite.com/
 * Description: 自动将WordPress内容转换为思维导图和知识图谱
 * Version: 1.0.0
 * Author: Your Name
 * License: GPL v2 or later
 */

// 防止直接访问
if (!defined('ABSPATH')) {
    exit;
}

// 定义插件常量
define('CV_PLUGIN_PATH', plugin_dir_path(__FILE__));
define('CV_PLUGIN_URL', plugin_dir_url(__FILE__));
define('CV_VERSION', '1.0.0');

// 初始化插件
class Content_Visualizer {
    
    private static $instance = null;
    
    public static function get_instance() {
        if (null === self::$instance) {
            self::$instance = new self();
        }
        return self::$instance;
    }
    
    private function __construct() {
        $this->init_hooks();
    }
    
    private function init_hooks() {
        // 前后端钩子
        add_action('init', array($this, 'register_blocks'));
        add_action('wp_enqueue_scripts', array($this, 'enqueue_frontend_assets'));
        add_action('enqueue_block_editor_assets', array($this, 'enqueue_editor_assets'));
        
        // 短代码注册
        add_shortcode('mind_map', array($this, 'mind_map_shortcode'));
        add_shortcode('knowledge_graph', array($this, 'knowledge_graph_shortcode'));
    }
    
    // 后续方法将在这里添加
}

// 启动插件
Content_Visualizer::get_instance();

2.3 资源文件组织架构

创建清晰的目录结构:

content-visualizer/
├── content-visualizer.php      # 主插件文件
├── includes/                   # PHP类文件
│   ├── class-content-parser.php
│   ├── class-mindmap-generator.php
│   └── class-knowledgegraph-generator.php
├── assets/                     # 静态资源
│   ├── css/
│   ├── js/
│   └── lib/                    # 第三方库
├── blocks/                     # Gutenberg块
│   ├── mind-map/
│   └── knowledge-graph/
├── templates/                  # 前端模板
└── languages/                  # 国际化文件

第三部分:内容解析与结构化处理

3.1 自动提取文章结构

内容解析是自动生成可视化的核心。我们需要从文章中提取层次结构和关键概念:

// includes/class-content-parser.php
class Content_Parser {
    
    /**
     * 从文章内容中提取标题层次结构
     */
    public static function extract_headings($content) {
        $pattern = '/<h([1-6])[^>]*>(.*?)</h[1-6]>/i';
        preg_match_all($pattern, $content, $matches, PREG_SET_ORDER);
        
        $structure = array();
        foreach ($matches as $match) {
            $level = intval($match[1]);
            $text = strip_tags($match[2]);
            $id = sanitize_title($text);
            
            $structure[] = array(
                'level' => $level,
                'text' => $text,
                'id' => $id,
                'children' => array()
            );
        }
        
        // 构建层次树
        return self::build_heading_tree($structure);
    }
    
    /**
     * 将扁平标题列表转换为树形结构
     */
    private static function build_heading_tree($headings) {
        $tree = array();
        $stack = array();
        
        foreach ($headings as $heading) {
            $node = array(
                'text' => $heading['text'],
                'id' => $heading['id'],
                'children' => array()
            );
            
            // 确定父节点
            while (!empty($stack)) {
                $last = end($stack);
                if ($last['level'] < $heading['level']) {
                    // 当前节点是最后一个节点的子节点
                    $tree_ref = &$this->find_node_ref($tree, $last['id']);
                    $tree_ref['children'][] = &$node;
                    break;
                } else {
                    array_pop($stack);
                }
            }
            
            // 如果没有父节点,添加到根
            if (empty($stack)) {
                $tree[] = &$node;
            }
            
            $stack[] = array(
                'level' => $heading['level'],
                'id' => $heading['id'],
                'node' => &$node
            );
            unset($node);
        }
        
        return $tree;
    }
    
    /**
     * 提取文章中的关键实体(人名、地名、专业术语等)
     */
    public static function extract_entities($content) {
        // 简化版实体提取,实际项目中可集成NLP服务
        $text = strip_tags($content);
        
        // 提取可能的技术术语(大写字母开头的单词序列)
        preg_match_all('/b[A-Z][a-z]+(?:s+[A-Z][a-z]+)*b/', $text, $matches);
        $technical_terms = array_unique($matches[0]);
        
        // 提取引号内的概念
        preg_match_all('/["']([^"']+)["']/', $text, $matches);
        $quoted_concepts = array_unique($matches[1]);
        
        // 合并并过滤
        $entities = array_merge($technical_terms, $quoted_concepts);
        $entities = array_filter($entities, function($entity) {
            return strlen($entity) > 2 && strlen($entity) < 50;
        });
        
        return array_values($entities);
    }
    
    /**
     * 分析实体间的关系(基于共现分析)
     */
    public static function analyze_relationships($content, $entities) {
        $relationships = array();
        $text = strip_tags($content);
        $sentences = preg_split('/[.!?]+/', $text);
        
        foreach ($sentences as $sentence) {
            $sentence_entities = array();
            foreach ($entities as $entity) {
                if (stripos($sentence, $entity) !== false) {
                    $sentence_entities[] = $entity;
                }
            }
            
            // 如果句子中包含多个实体,建立关系
            if (count($sentence_entities) > 1) {
                for ($i = 0; $i < count($sentence_entities); $i++) {
                    for ($j = $i + 1; $j < count($sentence_entities); $j++) {
                        $key = $sentence_entities[$i] . '|' . $sentence_entities[$j];
                        if (!isset($relationships[$key])) {
                            $relationships[$key] = 0;
                        }
                        $relationships[$key]++;
                    }
                }
            }
        }
        
        // 转换为前端需要的格式
        $result = array();
        foreach ($relationships as $key => $strength) {
            list($source, $target) = explode('|', $key);
            if ($strength > 1) { // 只保留强度大于1的关系
                $result[] = array(
                    'source' => $source,
                    'target' => $target,
                    'strength' => $strength,
                    'label' => '相关' // 可进一步分析关系类型
                );
            }
        }
        
        return $result;
    }
}

3.2 缓存机制优化性能

内容解析可能消耗较多资源,我们需要实现缓存机制:

class Content_Cache {
    
    private static $cache_group = 'content_visualizer';
    
    /**
     * 获取缓存内容
     */
    public static function get($post_id, $type) {
        $key = "{$type}_{$post_id}";
        $cached = wp_cache_get($key, self::$cache_group);
        
        if ($cached !== false) {
            return $cached;
        }
        
        // 从数据库获取
        $transient_key = "cv_{$key}";
        $cached = get_transient($transient_key);
        
        if ($cached !== false) {
            wp_cache_set($key, $cached, self::$cache_group, 3600);
            return $cached;
        }
        
        return false;
    }
    
    /**
     * 设置缓存
     */
    public static function set($post_id, $type, $data, $expiration = 3600) {
        $key = "{$type}_{$post_id}";
        
        // 设置内存缓存
        wp_cache_set($key, $data, self::$cache_group, $expiration);
        
        // 设置数据库缓存
        $transient_key = "cv_{$key}";
        set_transient($transient_key, $data, $expiration);
        
        // 建立缓存索引,便于文章更新时清理
        $index = get_option('cv_cache_index', array());
        if (!isset($index[$post_id])) {
            $index[$post_id] = array();
        }
        $index[$post_id][] = $transient_key;
        update_option('cv_cache_index', $index, false);
    }
    
    /**
     * 清理文章缓存
     */
    public static function clear_post_cache($post_id) {
        $index = get_option('cv_cache_index', array());
        
        if (isset($index[$post_id])) {
            foreach ($index[$post_id] as $transient_key) {
                delete_transient($transient_key);
            }
            unset($index[$post_id]);
            update_option('cv_cache_index', $index, false);
        }
        
        // 清理内存缓存
        wp_cache_delete("mindmap_{$post_id}", self::$cache_group);
        wp_cache_delete("knowledgegraph_{$post_id}", self::$cache_group);
    }
}

// 文章更新时清理缓存
add_action('save_post', function($post_id) {
    if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return;
    Content_Cache::clear_post_cache($post_id);
});

第四部分:思维导图功能实现

4.1 集成Markmap可视化库

Markmap是基于D3.js的思维导图库,支持Markdown直接转换:

// assets/js/mindmap-renderer.js
class MindmapRenderer {
    
    constructor(containerId, options = {}) {
        this.container = document.getElementById(containerId);
        this.options = Object.assign({
            autoFit: true,
            duration: 500,
            maxWidth: 800,
            nodeMinHeight: 16,
            spacingVertical: 5,
            spacingHorizontal: 80,
            paddingX: 8
        }, options);
        
        this.mindmap = null;
        this.initialized = false;
    }
    
    /**
     * 从文章结构数据生成思维导图
     */
    async renderFromStructure(structure) {
        if (!this.initialized) {
            await this.initialize();
        }
        
        // 转换结构为Markdown格式
        const markdown = this.structureToMarkdown(structure);
        
        // 创建Markmap
        const { Markmap } = window.markmap;
        const mm = Markmap.create(this.container, this.options, markdown);
        
        this.mindmap = mm;
        return mm;
    }
    
    /**
     * 将树形结构转换为Markdown
     */
    structureToMarkdown(node, level = 0) {
        let markdown = '';
        const indent = '  '.repeat(level);
        
        if (Array.isArray(node)) {
            // 根节点数组
            node.forEach(child => {
                markdown += this.structureToMarkdown(child, level);
            });
        } else {
            // 单个节点
            markdown += `${indent}- ${node.text}n`;
            
            if (node.children && node.children.length > 0) {
                node.children.forEach(child => {
                    markdown += this.structureToMarkdown(child, level + 1);
                });
            }
        }
        
        return markdown;
    }
    
    /**
     * 初始化Markmap库
     */
    async initialize() {
        if (window.markmap) {
            this.initialized = true;
            return;
        }
        
        // 动态加载Markmap库
        await this.loadScript(CV_PLUGIN_URL + 'assets/lib/markmap/markmap.min.js');
        await this.loadStylesheet(CV_PLUGIN_URL + 'assets/lib/markmap/markmap.css');
        
        this.initialized = true;
    }
    
    /**
     * 动态加载脚本
     */
    loadScript(src) {
        return new Promise((resolve, reject) => {
            const script = document.createElement('script');
            script.src = src;
            script.onload = resolve;
            script.onerror = reject;
            document.head.appendChild(script);
        });
    }
    
    /**
     * 动态加载样式
     */
    loadStylesheet(href) {
        return new Promise((resolve, reject) => {
            const link = document.createElement('link');
            link.rel = 'stylesheet';
            link.href = href;
            link.onload = resolve;
            link.onerror = reject;
            document.head.appendChild(link);
        });
    }
    
    /**
     * 导出功能
     */
    exportAsImage(format = 'png') {
        if (!this.mindmap) return;
        
        const container = this.container;
        const svg = container.querySelector('svg');
        
        if (format === 'svg') {
            // 导出SVG
            const serializer = new XMLSerializer();
            const source = serializer.serializeToString(svg);
            const blob = new Blob([source], { type: 'image/svg+xml' });
            this.downloadBlob(blob, 'mindmap.svg');
        } else if (format === 'png') {
            // 导出PNG
            const canvas = document.createElement('canvas');
            const ctx = canvas.getContext('2d');
            const data = new XMLSerializer().serializeToString(svg);
            const img = new Image();
            
            img.onload = () => {
                canvas.width = img.width;
                canvas.height = img.height;
                ctx.drawImage(img, 0, 0);
                
                canvas.toBlob(blob => {
                    this.downloadBlob(blob, 'mindmap.png');
                }, 'image/png');
            };
            

btoa(unescape(encodeURIComponent(data)));

    }
}

/**
 * 下载Blob文件
 */
downloadBlob(blob, filename) {
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = filename;
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
    URL.revokeObjectURL(url);
}

}

// 全局可用
window.MindmapRenderer = MindmapRenderer;


#### 4.2 创建Gutenberg思维导图块

// blocks/mind-map/block.js
const { registerBlockType } = wp.blocks;
const {

InspectorControls, 
useBlockProps,
BlockControls

} = wp.blockEditor;
const {

PanelBody,
SelectControl,
ToggleControl,
RangeControl,
ColorPicker

} = wp.components;
const { useState, useEffect } = wp.element;

registerBlockType('content-visualizer/mind-map', {

title: '思维导图',
icon: 'chart-line',
category: 'widgets',
attributes: {
    postId: {
        type: 'number',
        default: 0
    },
    autoGenerate: {
        type: 'boolean',
        default: true
    },
    layout: {
        type: 'string',
        default: 'tree'
    },
    depth: {
        type: 'number',
        default: 3
    },
    primaryColor: {
        type: 'string',
        default: '#3366cc'
    },
    showControls: {
        type: 'boolean',
        default: true
    }
},

edit: function({ attributes, setAttributes, clientId }) {
    const blockProps = useBlockProps();
    const [isLoading, setIsLoading] = useState(false);
    const [structure, setStructure] = useState(null);
    const [error, setError] = useState(null);

    // 获取当前文章ID
    useEffect(() => {
        if (attributes.postId === 0) {
            const currentPostId = wp.data.select('core/editor').getCurrentPostId();
            setAttributes({ postId: currentPostId });
        }
    }, []);

    // 加载文章结构
    useEffect(() => {
        if (attributes.autoGenerate && attributes.postId > 0) {
            fetchStructure();
        }
    }, [attributes.postId, attributes.autoGenerate]);

    const fetchStructure = async () => {
        setIsLoading(true);
        setError(null);
        
        try {
            const response = await wp.apiFetch({
                path: `/content-visualizer/v1/mindmap/${attributes.postId}`,
                method: 'GET'
            });
            
            if (response.success) {
                setStructure(response.data);
            } else {
                setError(response.message || '获取文章结构失败');
            }
        } catch (err) {
            setError('网络请求失败: ' + err.message);
        } finally {
            setIsLoading(false);
        }
    };

    const renderPreview = () => {
        if (isLoading) {
            return (
                <div className="mindmap-loading">
                    <div className="spinner is-active"></div>
                    <p>正在生成思维导图...</p>
                </div>
            );
        }

        if (error) {
            return (
                <div className="mindmap-error">
                    <p>❌ {error}</p>
                    <button 
                        className="components-button is-secondary"
                        onClick={fetchStructure}
                    >
                        重试
                    </button>
                </div>
            );
        }

        if (structure) {
            // 简化预览
            return (
                <div className="mindmap-preview">
                    <div className="mindmap-tree">
                        {renderTreePreview(structure)}
                    </div>
                    <p className="mindmap-hint">
                        前端将显示交互式思维导图
                    </p>
                </div>
            );
        }

        return (
            <div className="mindmap-empty">
                <p>请确保已选择文章并启用自动生成</p>
            </div>
        );
    };

    const renderTreePreview = (nodes, level = 0) => {
        if (!nodes || nodes.length === 0) return null;
        
        return (
            <ul style={{ paddingLeft: level * 20 }}>
                {nodes.slice(0, 3).map((node, index) => (
                    <li key={index}>
                        <span>{node.text}</span>
                        {node.children && level < attributes.depth - 1 && 
                            renderTreePreview(node.children, level + 1)}
                    </li>
                ))}
                {nodes.length > 3 && (
                    <li>... 还有 {nodes.length - 3} 个节点</li>
                )}
            </ul>
        );
    };

    return (
        <div {...blockProps}>
            <BlockControls>
                <div className="components-toolbar">
                    <button 
                        className="components-button is-button"
                        onClick={fetchStructure}
                        disabled={isLoading}
                    >
                        {isLoading ? '刷新中...' : '刷新导图'}
                    </button>
                </div>
            </BlockControls>
            
            <InspectorControls>
                <PanelBody title="基本设置" initialOpen={true}>
                    <ToggleControl
                        label="自动生成"
                        checked={attributes.autoGenerate}
                        onChange={(value) => setAttributes({ autoGenerate: value })}
                    />
                    
                    <SelectControl
                        label="布局方式"
                        value={attributes.layout}
                        options={[
                            { label: '树状图', value: 'tree' },
                            { label: '放射状', value: 'radial' },
                            { label: '鱼骨图', value: 'fishbone' }
                        ]}
                        onChange={(value) => setAttributes({ layout: value })}
                    />
                    
                    <RangeControl
                        label="显示深度"
                        value={attributes.depth}
                        onChange={(value) => setAttributes({ depth: value })}
                        min={1}
                        max={6}
                    />
                </PanelBody>
                
                <PanelBody title="样式设置" initialOpen={false}>
                    <div className="color-picker-control">
                        <label>主色调</label>
                        <ColorPicker
                            color={attributes.primaryColor}
                            onChangeComplete={(color) => 
                                setAttributes({ primaryColor: color.hex })
                            }
                            disableAlpha
                        />
                    </div>
                    
                    <ToggleControl
                        label="显示控制按钮"
                        checked={attributes.showControls}
                        onChange={(value) => setAttributes({ showControls: value })}
                    />
                </PanelBody>
            </InspectorControls>
            
            <div className="mindmap-block">
                <h3>思维导图预览</h3>
                {renderPreview()}
            </div>
        </div>
    );
},

save: function() {
    // 动态块,由前端渲染
    return null;
}

});


#### 4.3 前端渲染与交互实现

// 在前端渲染思维导图
add_action('wp_footer', function() {

if (!has_block('content-visualizer/mind-map')) {
    return;
}
?>
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', function() {
    // 查找所有思维导图容器
    const mindmapContainers = document.querySelectorAll('.wp-block-content-visualizer-mind-map');
    
    mindmapContainers.forEach(async (container, index) => {
        const blockId = container.getAttribute('data-block-id');
        const postId = container.getAttribute('data-post-id');
        const config = JSON.parse(container.getAttribute('data-config') || '{}');
        
        // 创建唯一容器ID
        const renderContainerId = `mindmap-${postId}-${index}`;
        const renderDiv = document.createElement('div');
        renderDiv.id = renderContainerId;
        renderDiv.className = 'mindmap-render-container';
        container.appendChild(renderDiv);
        
        try {
            // 获取思维导图数据
            const response = await fetch(
                `<?php echo rest_url('content-visualizer/v1/mindmap/'); ?>${postId}`
            );
            
            if (!response.ok) {
                throw new Error('获取数据失败');
            }
            
            const data = await response.json();
            
            if (data.success) {
                // 初始化渲染器
                const renderer = new MindmapRenderer(renderContainerId, {
                    autoFit: true,
                    maxWidth: config.maxWidth || 800,
                    primaryColor: config.primaryColor || '#3366cc'
                });
                
                // 渲染思维导图
                await renderer.renderFromStructure(data.data);
                
                // 添加控制按钮
                if (config.showControls !== false) {
                    addControlButtons(renderDiv, renderer);
                }
            } else {
                renderDiv.innerHTML = `<p class="error">${data.message}</p>`;
            }
        } catch (error) {
            renderDiv.innerHTML = `<p class="error">加载失败: ${error.message}</p>`;
        }
    });
    
    function addControlButtons(container, renderer) {
        const controls = document.createElement('div');
        controls.className = 'mindmap-controls';
        
        const zoomInBtn = createButton('放大', '+', () => {
            if (renderer.mindmap) {
                renderer.mindmap.fit();
                renderer.mindmap.scale(renderer.mindmap.scale() * 1.2);
            }
        });
        
        const zoomOutBtn = createButton('缩小', '-', () => {
            if (renderer.mindmap) {
                renderer.mindmap.scale(renderer.mindmap.scale() * 0.8);
            }
        });
        
        const resetBtn = createButton('重置', '↺', () => {
            if (renderer.mindmap) {
                renderer.mindmap.fit();
            }
        });
        
        const exportPngBtn = createButton('导出PNG', '📷', () => {
            renderer.exportAsImage('png');
        });
        
        const exportSvgBtn = createButton('导出SVG', '🖼️', () => {
            renderer.exportAsImage('svg');
        });
        
        controls.appendChild(zoomInBtn);
        controls.appendChild(zoomOutBtn);
        controls.appendChild(resetBtn);
        controls.appendChild(exportPngBtn);
        controls.appendChild(exportSvgBtn);
        
        container.parentNode.insertBefore(controls, container.nextSibling);
    }
    
    function createButton(title, text, onClick) {
        const button = document.createElement('button');
        button.className = 'mindmap-control-btn';
        button.title = title;
        button.innerHTML = text;
        button.addEventListener('click', onClick);
        return button;
    }
});
</script>

<style>
.mindmap-render-container {
    width: 100%;
    height: 500px;
    border: 1px solid #eee;
    border-radius: 8px;
    overflow: hidden;
    margin: 20px 0;
}

.mindmap-controls {
    display: flex;
    gap: 8px;
    margin-top: 10px;
    justify-content: center;
}

.mindmap-control-btn {
    padding: 6px 12px;
    background: #f5f5f5;
    border: 1px solid #ddd;
    border-radius: 4px;
    cursor: pointer;
    font-size: 14px;
    transition: all 0.2s;
}

.mindmap-control-btn:hover {
    background: #e9e9e9;
    border-color: #ccc;
}

.mindmap-loading,
.mindmap-error,
.mindmap-empty {
    padding: 40px;
    text-align: center;
    background: #f9f9f9;
    border-radius: 8px;
    margin: 20px 0;
}

.mindmap-preview .mindmap-tree {
    max-height: 300px;
    overflow-y: auto;
    padding: 15px;
    background: white;
    border-radius: 6px;
    border: 1px solid #e0e0e0;
}

.mindmap-preview ul {
    list-style-type: none;
    margin: 0;
    padding: 0;
}

.mindmap-preview li {
    padding: 4px 0;
    color: #333;
}

.mindmap-preview li span {
    padding: 2px 6px;
    background: #f0f7ff;
    border-radius: 3px;
    border-left: 3px solid #3366cc;
}

.mindmap-hint {
    font-size: 12px;
    color: #666;
    text-align: center;
    margin-top: 10px;
    font-style: italic;
}
</style>
<?php

});


### 第五部分:知识图谱功能实现

#### 5.1 集成Vis.js网络图库

// includes/class-knowledgegraph-generator.php
class KnowledgeGraph_Generator {


/**
 * 生成知识图谱数据
 */
public static function generate_graph_data($post_id) {
    // 检查缓存
    $cached = Content_Cache::get($post_id, 'knowledgegraph');
    if ($cached !== false) {
        return $cached;
    }
    
    $post = get_post($post_id);
    if (!$post) {
        return new WP_Error('invalid_post', '文章不存在');
    }
    
    // 提取实体和关系
    $entities = Content_Parser::extract_entities($post->post_content);
    $relationships = Content_Parser::analyze_relationships($post->post_content, $entities);
    
    // 构建Vis.js格式的数据
    $nodes = array();
    $edges = array();
    
    // 创建节点
    foreach ($entities as $index => $entity) {
        $nodes[] = array(
            'id' => $index,
            'label' => $entity,
            'value' => self::calculate_entity_importance($entity, $post->post_content),
            'title' => self::generate_entity_tooltip($entity, $post->post_content),
            'group' => self::categorize_entity($entity),
            'font' => array(
                'size' => 16,
                'bold' => true
            )
        );
    }
    
    // 创建边(关系)
    $entity_index = array_flip($entities);
    foreach ($relationships as $rel) {
        if (isset($entity_index[$rel['source']], $entity_index[$rel['target']])) {
            $edges[] = array(
                'from' => $entity_index[$rel['source']],
                'to' => $entity_index[$rel['target']],
                'label' => $rel['label'],
                'value' => $rel['strength'],
                'title' => "关联强度: {$rel['strength']}",
                'arrows' => 'to',
                'smooth' => array('type' => 'continuous')
            );
        }
    }
    
    $graph_data = array(
        'nodes' => $nodes,
        'edges' => $edges,
        'metadata' => array(
            'entity_count' => count($entities),
            'relationship_count' => count($edges),
            'generated_at' => current_time('mysql')
        )
    );
    
    // 缓存结果
    Content_Cache::set($post_id, 'knowledgegraph', $graph_data, 86400); // 缓存24小时
    
    return $graph_data;
}

/**
 * 计算实体重要性
 */
private static function calculate_entity_importance($entity, $content) {
    // 基于出现频率和位置计算重要性
    $frequency = substr_count(strtolower($content), strtolower($entity));
    
    // 检查是否出现在标题中
    $title_importance = 0;
    $post_title = get_the_title();
    if (stripos($post_title, $entity) !== false) {
        $title_importance = 5;
    }
    
    // 检查是否出现在开头段落
    $first_paragraph = wp_trim_words($content, 50);
    $position_importance = stripos($first_paragraph, $entity) !== false ? 3 : 1;
    
    return ($frequency * 2) + $title_importance + $position_importance;
}

/**
 * 生成实体悬停提示
 */
private static function generate_entity_tooltip($entity, $content) {
    $sentences = array();
    $pattern = '/[^.!?]*b' . preg_quote($entity, '/') . 'b[^.!?]*[.!?]/i';
    preg_match_all($pattern, $content, $matches);
    
    if (!empty($matches[0])) {
        $sentences = array_slice($matches[0], 0, 3); // 取前3个包含实体的句子
    }
    
    $tooltip = "<strong>{$entity}</strong><br><br>";
    if (!empty($sentences)) {
        $tooltip .= "相关描述:<br>";
        foreach ($sentences as $sentence) {
            $tooltip .= "• " . trim($sentence) . "<br>";
        }
    } else {
        $tooltip .= "在文章中多次提及";
    }
    
    return $tooltip;
}

/**
 * 实体分类
 */
private static function categorize_entity($entity) {
    // 简单的分类逻辑,可根据需要扩展
    $tech_keywords = ['AI', '算法', '编程', '数据', '网络', '系统'];
    $business_keywords = ['市场', '营销', '管理', '战略', '投资', '财务'];
    $people_keywords = ['先生', '女士', '博士', '教授', '团队', '专家'];
    
    $entity_lower = strtolower($entity);
    
    foreach ($tech_keywords as $keyword) {
        if (stripos($entity, $keyword) !== false) {
            return 'technology';
        }
    }
    
    foreach ($business_keywords as $keyword) {
        if (stripos($entity, $keyword) !== false) {
            return 'business';
        }
    }
    
    foreach ($people_keywords as $keyword) {
        if (stripos($entity_lower, strtol
本文来自网络,不代表柔性供应链服务中心立场,转载请注明出处:https://mall.org.cn/5347.html

EXCHANGES®作者

上一篇
下一篇

为您推荐

发表回复

联系我们

联系我们

18559313275

在线咨询: QQ交谈

邮箱: vip@exchanges.center

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