开发智联笔记项目时所遇问题(7)

问题:点击新建脑图,可以命名,但是没有节点,页面报错:Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'name')
at Object.get_mind (jsmind.js:8:7688)
at c.load (jsmind.js:8:14534)
at z._show (jsmind.js:8:43134)
at z.show (jsmind.js:8:43411)
at initMind (index.html:378:16)
at openMap (index.html:303:17)
4jsmind.js:8 Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'name')
at Object.get_mind (jsmind.js:8:7688)
at c.load (jsmind.js:8:14534)
at z._show (jsmind.js:8:43134)
at z.show (jsmind.js:8:43411)
at openMap (index.html:301:20)
2jsmind.js:8 Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'name')
at Object.get_mind (jsmind.js:8:7688)
at c.load (jsmind.js:8:14534)
at z._show (jsmind.js:8:43134)
at z.show (jsmind.js:8:43411)
at openMap (index.html:301:20)
get_mind @ jsmind.js:8
load @ jsmind.js:8
_show @ jsmind.js:8
show @ jsmind.js:8
openMap @ index.html:301
9jsmind.js:8 Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'name')
at Object.get_mind (jsmind.js:8:7688)
at c.load (jsmind.js:8:14534)
at z._show (jsmind.js:8:43134)
at z.show (jsmind.js:8:43411)
at openMap (index.html:301:20)
jsmind.js:8 Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'name')
at Object.get_mind (jsmind.js:8:7688)
at c.load (jsmind.js:8:14534)
at z._show (jsmind.js:8:43134)
at z.show (jsmind.js:8:43411)
at openMap (index.html:301:20)

解决方法如下:
这个错误表明 jsmind 无法正确解析脑图数据。问题在于数据格式不兼容。

修复方案

1. 修改 index.html 中的关键函数

/* 新建 */
function newMap() {
    document.getElementById('newModal').style.display = 'block';
}

async function createMap() {
    const name = document.getElementById('mName').value.trim();
    const topic = document.getElementById('mTopic').value.trim();
    if (!name || !topic) return alert('请填写完整');
    
    // 使用 jsmind 标准格式
    const data = {
        "meta": {
            "name": name,
            "author": document.getElementById('user').textContent,
            "version": "1.0"
        },
        "format": "node_tree",
        "data": {
            "id": "root",
            "topic": topic,
            "children": []
        }
    };
    
    try {
        const res = await fetch('/api/mindmaps', {
            method: 'POST',
            headers: {'Content-Type': 'application/json'},
            body: JSON.stringify({name, data}),
            credentials: 'include'
        });
        
        if (!res.ok) {
            throw new Error('创建失败: ' + res.status);
        }
        
        const m = await res.json();
        mapList.push(m);
        renderList();
        closeModal('newModal');
        openMap(m.id);
    } catch (error) {
        console.error('Create map error:', error);
        alert('创建失败: ' + error.message);
    }
}

/* 打开脑图 */
async function openMap(id) {
    try {
        currentId = id;
        renderList();
        
        const res = await fetch(`/api/mindmaps/${id}`, {credentials: 'include'});
        if (!res.ok) throw new Error('加载脑图失败: ' + res.status);
        
        const m = await res.json();
        console.log('Loaded mind map:', m);
        
        // 处理数据格式
        let mindData = m.data;
        
        // 如果数据是字符串,尝试解析
        if (typeof mindData === 'string') {
            try {
                mindData = JSON.parse(mindData);
            } catch (e) {
                console.error('Parse data error:', e);
            }
        }
        
        // 确保数据格式正确
        if (mindData && mindData.format === 'node_tree') {
            // 使用完整格式
            if (jm) {
                jm.show(mindData);
            } else {
                initMind(mindData);
            }
        } else if (mindData && mindData.id) {
            // 只有节点数据,包装成完整格式
            const wrappedData = {
                "meta": {
                    "name": m.name,
                    "author": document.getElementById('user').textContent,
                    "version": "1.0"
                },
                "format": "node_tree",
                "data": mindData
            };
            if (jm) {
                jm.show(wrappedData);
            } else {
                initMind(wrappedData);
            }
        } else {
            // 创建默认数据
            const defaultData = {
                "meta": {
                    "name": m.name,
                    "author": document.getElementById('user').textContent,
                    "version": "1.0"
                },
                "format": "node_tree",
                "data": {
                    "id": "root",
                    "topic": m.name || "中心主题",
                    "children": []
                }
            };
            if (jm) {
                jm.show(defaultData);
            } else {
                initMind(defaultData);
            }
        }
    } catch (error) {
        console.error('Open map error:', error);
        alert('打开脑图失败: ' + error.message);
    }
}

/* 初始化脑图 */
function initMind(data) {
    try {
        jm = new jsMind({
            container: 'jsmind_container',
            theme: 'primary',
            editable: true,
            view: { 
                hmargin: 100, 
                vmargin: 50, 
                line_width: 2, 
                line_color: '#409eff'
            },
            layout: { 
                hspace: 80, 
                vspace: 20, 
                pspace: 13
            }
        });
        
        console.log('Initializing mind with data:', data);
        jm.show(data);
        
    } catch (error) {
        console.error('Init mind error:', error);
        alert('初始化脑图失败: ' + error.message);
        
        // 创建默认脑图作为后备
        const defaultData = {
            "meta": {
                "name": "默认脑图",
                "author": "用户",
                "version": "1.0"
            },
            "format": "node_tree",
            "data": {
                "id": "root",
                "topic": "中心主题",
                "children": []
            }
        };
        jm.show(defaultData);
    }
}

2. 修改 app.py 中的数据保存逻辑

app.py 中修改 API 路由,确保数据格式正确:

@app.route('/api/mindmaps', methods=['POST'])
@login_required
def api_add():
    data = request.get_json()
    name, map_data = data.get('name'), data.get('data')
    if not name: return jsonify({'msg': '名称不能为空'}), 400
    
    # 确保数据格式正确
    if not map_data:
        map_data = {
            "meta": {
                "name": name,
                "author": current_user.username,
                "version": "1.0"
            },
            "format": "node_tree",
            "data": {
                "id": "root",
                "topic": name,
                "children": []
            }
        }
    elif isinstance(map_data, dict) and 'id' in map_data and 'format' not in map_data:
        # 如果只有节点数据,包装成完整格式
        map_data = {
            "meta": {
                "name": name,
                "author": current_user.username,
                "version": "1.0"
            },
            "format": "node_tree",
            "data": map_data
        }
    
    m = MindMap(user_id=current_user.id, name=name, data=json.dumps(map_data))
    db.session.add(m)
    db.session.commit()
    return jsonify({'id': m.id, 'name': m.name, 'data': json.loads(m.data)}), 201

@app.route('/api/mindmaps/<int:mid>', methods=['GET'])
@login_required
def api_get(mid):
    m = MindMap.query.filter_by(id=mid, user_id=current_user.id).first_or_404()
    mind_data = json.loads(m.data)
    
    # 确保返回的数据格式正确
    if isinstance(mind_data, dict) and 'format' in mind_data:
        # 已经是完整格式
        return jsonify({'id': m.id, 'name': m.name, 'data': mind_data})
    else:
        # 包装成完整格式
        wrapped_data = {
            "meta": {
                "name": m.name,
                "author": current_user.username,
                "version": "1.0"
            },
            "format": "node_tree",
            "data": mind_data
        }
        return jsonify({'id': m.id, 'name': m.name, 'data': wrapped_data})

3. 简化测试方案

如果上述方法仍有问题,可以使用这个简化版本:

/* 新建脑图 - 简化版本 */
async function createMap() {
    const name = document.getElementById('mName').value.trim();
    const topic = document.getElementById('mTopic').value.trim();
    if (!name || !topic) return alert('请填写完整');
    
    // 最简单的数据格式
    const data = {
        "id": "root",
        "topic": topic,
        "children": []
    };
    
    try {
        const res = await fetch('/api/mindmaps', {
            method: 'POST',
            headers: {'Content-Type': 'application/json'},
            body: JSON.stringify({name, data}),
            credentials: 'include'
        });
        
        if (!res.ok) throw new Error('创建失败');
        
        const m = await res.json();
        mapList.push(m);
        renderList();
        closeModal('newModal');
        
        // 直接初始化脑图,不使用 openMap
        if (!jm) {
            initMind(m.data);
        } else {
            jm.show(m.data);
        }
        currentId = m.id;
        
    } catch (error) {
        console.error('Create map error:', error);
        alert('创建失败: ' + error.message);
    }
}

/* 初始化脑图 - 简化版本 */
function initMind(data) {
    try {
        jm = new jsMind({
            container: 'jsmind_container',
            theme: 'primary',
            editable: true
        });
        
        jm.show(data);
        console.log('Mind map initialized successfully');
        
    } catch (error) {
        console.error('Init mind error:', error);
        // 创建最基本的脑图
        const basicData = {"id":"root","topic":"中心主题"};
        jm.show(basicData);
    }
}

4. 检查 jsmind 版本

确保使用的是兼容的 jsmind 版本。可以尝试重新下载:

# 下载稳定版本的 jsmind
curl -o static/jsmind.js https://cdn.jsdelivr.net/npm/jsmind@0.4.6/js/jsmind.js
curl -o static/jsmind.css https://cdn.jsdelivr.net/npm/jsmind@0.4.6/style/jsmind.css
posted @ 2025-11-21 20:06  Jade_Z  阅读(5)  评论(0)    收藏  举报