亲手打造可视化故事线管理工具:开发全流程、难点突破与开发过程经验总结


在这里插入图片描述

作为还没入门的业余编程爱好者,奋战了2天,借助AI开发一款FLASK小工具,功能还在完善中(时间轴可以跟随关联图缩放,加了一个用C键控制开关的十字光标),还有不少逻辑没有实现。通过实战,可以更好把握学习的方向,比如说开发同样一款功能的工具,可能有很多方法,要学会选择最优解;第二点,逻辑是编程的基本功,也就是说数学基础确实很重要咱是暂时业余爱好者,慢慢来,下面就把开发的经验过程的一点经验向大家分享一下咯。


一、引言

在创作小说的过程中,管理复杂的故事线是一项极具挑战性的任务。为了帮助作者更高效地组织和管理小说的情节、人物和时间线,我们计划开发一款基于Python Flask应用的可视化故事线管理工具。该工具将以直观的方式展示故事中的各个事件及其关联,同时提供丰富的功能来满足作者的需求。

二、功能需求梳理

(一)核心功能

  1. 节点管理:用节点表示事件,每个节点具备事件、时间、地点、人物、伏笔(起/止)、概要、内容等属性。支持新建节点,通过模板输入信息,并进行逻辑判断。
  2. 关联展示:用线条表示事件之间的关联,包括基于人物和时间的常规连线以及伏笔连线。
  3. 信息显示控制:通过选择框控制节点信息的显示方式,支持鼠标悬停显示和直接显示。

(二)界面功能

  1. 左侧功能区:提供界面明暗切换、格栅开关、新建节点、修改颜色和线型、显示选项设置、文件列表管理、伏笔提示列表展示、导入导出文件等功能。
  2. 右侧画板区:自适应框体,支持滑动和缩放操作,根据时间顺序展示节点和连线,并显示时间刻度。

(三)逻辑判断功能

对输入的事件信息进行逻辑判断,如判断时间、地点和人物的合理性,以及伏笔的起止顺序是否正确,并给出相应的错误提示。

三、技术栈和架构

(一)技术栈选择

  1. 后端:采用Python的Flask框架,它是一个轻量级的Web框架,易于上手和扩展,适合快速开发。
  2. 前端:使用HTML、CSS和JavaScript进行页面设计和交互实现。借助Flask的模板引擎,将后端数据动态渲染到前端页面。
  3. 数据存储:使用单个文件(如MD文本或CSV文本)存储节点信息,便于管理和维护。

(二)架构设计

  1. 分层架构:采用MVC(Model-View-Controller)架构,将应用分为模型层、视图层和控制层。

    • 模型层:负责处理数据的存储和逻辑判断,如读取和写入文件、判断事件信息的合理性等。
    • 视图层:负责展示用户界面,包括左侧功能区和右侧画板区,使用HTML和CSS进行页面布局和样式设计。
    • 控制层:负责处理用户请求和业务逻辑,如接收用户输入的节点信息、生成连线等,使用Flask实现路由和请求处理。
  2. 前后端交互:通过AJAX技术实现前后端的异步交互,提高用户体验。例如,在新建节点时,前端将用户输入的信息发送到后端进行逻辑判断,后端返回判断结果,前端根据结果进行相应的提示和更新。

四、安装依赖

(一)安装Python和Flask

确保你已经安装了Python 3.9及以上版本。可以使用以下命令安装Flask:

pip install flask

(二)配置开发环境

在VSCode中安装Python扩展,以便更好地进行代码编辑和调试。同时,配置PowerShell作为终端,方便执行命令。

五、详细开发步骤

(一)创建项目目录结构

storyline_manager/
│
├── app.py              # Flask应用主文件
├── templates/          # 存放HTML模板文件
│   ├── index.html      # 主页面模板
│   └── ...
├── static/             # 存放静态文件,如CSS、JavaScript和图片
│   ├── css/
│   │   └── style.css
│   ├── js/
│   │   └── script.js
│   └── ...
└── data/               # 存放数据文件,如MD或CSV文件
    └── storyline.md

(二)编写后端代码

  1. 创建Flask应用:在app.py中创建Flask应用实例,并定义路由和视图函数。
from flask import Flask, render_template, request, jsonify

app = Flask(__name__)

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/create_node', methods=['POST'])
def create_node():
    # 处理新建节点的逻辑
    data = request.get_json()
    # 进行逻辑判断
    # 保存节点信息到文件
    return jsonify({'status': 'success'})

if __name__ == '__main__':
    app.run(debug=True)
  1. 实现数据存储和逻辑判断功能:在app.py中添加函数来读取和写入数据文件,并实现逻辑判断功能。
import os

def save_node_to_file(node):
    file_path = 'data/storyline.md'
    with open(file_path, 'a') as f:
        # 将节点信息写入文件
        f.write(f"{node['event']},{node['time']},{node['location']},{node['characters']},{node['foreshadowing']},{node['summary']},{node['content']}\n")

def check_node_logic(node):
    # 进行逻辑判断,如时间、地点和人物的合理性,伏笔的起止顺序等
    # 返回判断结果和错误信息
    pass

(三)编写前端代码

  1. 设计HTML模板:在templates/index.html中设计主页面的HTML结构,包括左侧功能区和右侧画板区。
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Storyline Manager</title>
    <link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
</head>
<body>
    <div class="left-panel">
        <!-- 左侧功能区 -->
        <button id="toggle-dark-mode">切换明暗</button>
        <button id="toggle-grid">格栅开关</button>
        <button id="create-node">新建节点</button>
        <!-- 其他功能按钮和选项 -->
    </div>
    <div class="right-panel">
        <!-- 右侧画板区 -->
        <div id="canvas">
            <!-- 节点和连线将在这里显示 -->
        </div>
    </div>
    <script src="{{ url_for('static', filename='js/script.js') }}"></script>
</body>
</html>
  1. 实现前端交互功能:在static/js/script.js中编写JavaScript代码,实现用户交互功能,如点击按钮、输入信息、发送请求等。
document.getElementById('create-node').addEventListener('click', function() {
    // 弹出输入文本框
    const node = {
        event: prompt('请输入事件名称'),
        time: prompt('请输入事件时间'),
        location: prompt('请输入事件地点'),
        characters: prompt('请输入事件人物,用逗号分隔'),
        foreshadowing: prompt('请输入伏笔(起/止),可为空'),
        summary: prompt('请输入事件概要,可为空'),
        content: prompt('请输入事件内容,可为空')
    };
    // 发送请求到后端
    fetch('/create_node', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify(node)
    })
   .then(response => response.json())
   .then(data => {
        if (data.status === 'success') {
            alert('节点创建成功');
        } else {
            alert(data.error);
        }
    });
});

(四)实现连线功能

  1. 后端逻辑:在app.py中添加函数来生成连线信息,根据人物和时间的关系判断节点之间的连线。
def generate_connections(nodes):
    connections = []
    # 根据人物和时间的关系生成连线
    return connections
  1. 前端展示:在static/js/script.js中根据后端返回的连线信息,在右侧画板区绘制连线。
function draw_connections(connections) {
    const canvas = document.getElementById('canvas');
    connections.forEach(connection => {
        const line = document.createElement('div');
        line.classList.add('connection-line');
        // 设置连线的位置和样式
        canvas.appendChild(line);
    });
}

(五)实现时间刻度功能

  1. 后端处理:在app.py中添加函数来生成时间刻度信息,根据节点的时间范围确定刻度的范围和间隔。
def generate_time_scale(nodes):
    time_scale = []
    # 根据节点的时间范围生成时间刻度
    return time_scale
  1. 前端展示:在static/js/script.js中根据后端返回的时间刻度信息,在右侧画板区绘制时间刻度,并实现鼠标悬停显示功能。
function draw_time_scale(time_scale) {
    const canvas = document.getElementById('canvas');
    time_scale.forEach(scale => {
        const line = document.createElement('div');
        line.classList.add('time-scale-line');
        // 设置时间刻度的位置和样式
        canvas.appendChild(line);
    });
    // 实现鼠标悬停显示功能
    document.querySelectorAll('.time-scale-line').forEach(line => {
        line.addEventListener('mouseenter', function() {
            // 显示刻度年份
        });
        line.addEventListener('mouseleave', function() {
            // 隐藏刻度年份
        });
    });
}

六、调试和本地化部署

(一)调试

在开发过程中,可以使用Flask的调试模式来方便地进行调试。在app.py中启动应用时,将debug参数设置为True

if __name__ == '__main__':
    app.run(debug=True)

这样,当代码发生变化时,Flask会自动重新加载应用,并且在出现错误时会在浏览器中显示详细的错误信息。

(二)本地化部署

将开发好的应用部署到本地服务器上,可以使用以下步骤:

  1. 确保已经安装了Python和Flask。
  2. 在项目根目录下,打开PowerShell窗口,运行以下命令启动应用:
python app.py
  1. 打开浏览器,访问http://127.0.0.1:5000,即可看到应用的主页面。

七、测试

(一)功能测试

对应用的各个功能进行测试,包括新建节点、修改颜色和线型、显示选项设置、导入导出文件等,确保功能正常运行。

(二)逻辑测试

对应用的逻辑判断功能进行测试,输入不同的事件信息,检查是否能正确判断时间、地点和人物的合理性,以及伏笔的起止顺序是否正确,并给出相应的错误提示。

(三)界面测试

对应用的界面进行测试,检查界面的布局和样式是否美观,是否支持自适应和缩放操作,以及鼠标悬停和点击事件是否正常响应。

八、困难点及经验介绍

在利用AI辅助开发这款工具的过程中,遇到了不少挑战,也积累了一些实用经验。

定期备份代码至关重要:开发中常因架构文件分散、代码量大,加上AI上下文联系能力有限,容易卡在逻辑或细节问题上,若忘记备份,可能导致大量工作白费。因此,经常备份可避免因突发问题(如逻辑错误导致代码无法运行、AI生成代码失误难以回溯等)造成进度倒退。

开发前的整体构思不可或缺:需先规划好界面布局、功能分类,例如将鼠标事件相关逻辑集中在一段时间开发。若在复杂逻辑中临时插入新功能,极易引发冲突,导致原有功能异常。比如在已有节点显示逻辑中突然加入新的鼠标悬停效果,可能因事件监听冲突或样式干扰,使整个界面交互混乱。

采用“小步快跑”的开发策略:每次仅增加1-2个功能,完成后立即测试对之前功能的影响。例如先实现节点新建与基本逻辑判断,测试无误后,再添加连线功能,避免一次性堆积过多功能导致问题排查困难。AI生成代码虽高效,但一次性处理复杂需求易出错,拆分功能点逐步实现,能降低风险。

合理搭配AI工具:如deepseek逻辑性强,但存在繁忙限制,可将其用于核心逻辑代码生成;小问题或简单代码检查修改,可借助豆包或VSCode的Copilot。当deepseek生成代码后找不到插入位置时,可让Copilot辅助插入,并明确要求不修改其他功能。例如在整合前端界面与后端数据传输代码时,deepseek负责核心逻辑,Copilot处理代码插入细节,提升开发效率。

九、未来拓展

(一)增加更多功能

  1. 支持节点的编辑和删除功能,方便用户对已有的事件进行修改和管理。
  2. 提供更多的可视化效果,如节点的动画效果、连线的颜色和样式定制等,增强用户体验。
  3. 支持多人协作功能,允许多个用户同时编辑和管理同一个故事线。

(二)优化性能

随着故事线的复杂度增加,应用的性能可能会受到影响。可以对代码进行优化,如采用缓存机制、优化数据存储和查询方式等,提高应用的响应速度和处理能力。

(三)集成第三方工具

可以将该工具与其他写作工具(如Markdown编辑器、思维导图工具等)进行集成,方便用户在不同的工具之间切换和协作。

十、总结

通过以上步骤,我们可以利用Python的Flask框架开发一个可视化故事线管理工具。该工具将帮助作者更高效地组织和管理小说的情节、人物和时间线,提高写作效率和质量。在开发过程中,我们需要仔细梳理功能需求,选择合适的技术栈和架构,按照详细的开发步骤进行编码和调试,并进行充分的测试和优化。同时,我们还可以考虑未来的拓展方向,不断完善和提升工具的功能和性能。利用AI辅助开发不仅能亲身体验编程魅力,还能在实操中锻炼能力,比单纯看书或看教学视频更有趣、更具成效。

Logo

助力广东及东莞地区开发者,代码托管、在线学习与竞赛、技术交流与分享、资源共享、职业发展,成为松山湖开发者首选的工作与学习平台

更多推荐