当前位置: 首页 > news >正文

永久免费搭建网站网页设计与网站建设选择题

永久免费搭建网站,网页设计与网站建设选择题,wordpress创建页面模板,开发一个微信公众号多少钱📊 小说写作中的时间轴管理:基于 Vue 3 的事序图技术实现 💡 本文深入探讨了在小说写作软件中实现类似甘特图的事序图功能的技术方案,包括时间轴可视化、事件管理、拖拽交互等核心功能的完整实现,为开发者提供一套完整…

📊 小说写作中的时间轴管理:基于 Vue 3 的事序图技术实现

💡 本文深入探讨了在小说写作软件中实现类似甘特图的事序图功能的技术方案,包括时间轴可视化、事件管理、拖拽交互等核心功能的完整实现,为开发者提供一套完整的时间轴管理解决方案。

📋 目录

  • 项目背景
  • 技术架构设计
  • 核心功能实现
  • 拖拽交互实现
  • 数据持久化方案
  • 性能优化策略
  • 技术亮点总结
  • 总结与展望

🎯 项目背景

在小说创作过程中,作者需要管理复杂的时间线和事件序列。传统的时间线管理工具往往过于复杂,不适合小说创作场景。因此,我们在 51mazi 中设计了一个专门的事序图功能,类似甘特图但更贴近小说创作需求。

📊 事序图功能展示

事序图

可视化事序图管理 - 直观展示事件时间轴和进度

✨ 核心功能特性

  • 🕐 时间轴可视化: 基于时间单元格的可视化事件展示
  • 📝 事件管理: 支持创建、编辑、删除事件,包含简介、详情、进度等信息
  • 🖱️ 拖拽调整: 直观的拖拽操作调整事件时间位置
  • 📈 进度跟踪: 事件进度条显示,支持0-100%进度管理
  • 📚 多事序图: 支持创建多个独立的事序图,满足不同章节或故事线需求
  • 💾 数据持久化: 本地文件存储,确保数据安全

🏗️ 技术架构设计

核心技术栈

  • Vue 3.5.13: 渐进式 JavaScript 框架
  • Element Plus 2.10.1: 企业级 UI 组件库
  • Electron 35.0.3: 跨平台桌面应用框架

系统架构设计

┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   渲染进程      │    │   主进程        │    │   文件系统      │
│   (Vue 3)       │◄──►│   (Node.js)     │◄──►│   (JSON存储)    │
└─────────────────┘    └─────────────────┘    └─────────────────┘

📁 组件结构设计

// src/renderer/src/views/EventsSequence.vue
<template><LayoutTool :title="`事序图 - ${bookName}`"><!-- 事序图列表 --><div class="sequence-charts"><div v-for="chart in sequenceCharts" :key="chart.id" class="sequence-chart"><!-- 甘特图表格 --><div class="gantt-table"><!-- 表格头部 --><div class="table-header">...</div><!-- 表格主体 --><div class="table-body"><div class="table-left">...</div><div class="table-right">...</div></div></div></div></div></LayoutTool>
</template>

🔧 核心功能实现

1. 数据结构设计

// 事序图数据结构
const sequenceCharts = ref([{id: 'chart-1',title: '第一章事件',cellCount: 100,events: [{id: 'event-1',index: 1,introduction: '事件简介',detail: '事件详细描述',progress: 50,startTime: 1,endTime: 5,color: '#409EFF'}]}
])

2. 时间轴渲染实现

// 时间轴单元格渲染
<div class="right-header"><div v-for="i in chart.cellCount || 100" :key="i" class="time-cell">{{ i }}</div>
</div>// 背景网格渲染
<div class="grid-background"><divv-for="rowIndex in chart.events.length":key="`row-${rowIndex}`"class="grid-row"><divv-for="colIndex in chart.cellCount || 100":key="`cell-${rowIndex}-${colIndex}`"class="grid-cell"></div></div>
</div>

3. 事件条样式计算

// 事件条样式计算
const getEventBarStyle = (event) => {if (!event.startTime || !event.endTime) return {}const left = (event.startTime - 1) * 40 // 40px 单元格宽度const width = (event.endTime - event.startTime + 1) * 40return {left: `${left}px`,width: `${width}px`,backgroundColor: event.color || '#409EFF'}
}

4. 进度条可视化

// 进度条宽度计算
const getEventProgressWidth = (event) => {const progress = typeof event.progress === 'number' ? event.progress : Number(event.progress) || 0const clamped = Math.max(0, Math.min(100, progress))return `${clamped}%`
}
/* 进度条样式 */
.event-progress {position: absolute;inset: 0;background: rgba(255, 255, 255, 0.22);width: 0%;transition: width 0.3s ease;pointer-events: none;background-image: repeating-linear-gradient(45deg,transparent,transparent 4px,rgba(255, 255, 255, 0.1) 4px,rgba(255, 255, 255, 0.1) 8px);animation: progressStripes 1s linear infinite;
}@keyframes progressStripes {0% { background-position: 0 0; }100% { background-position: 8px 8px; }
}

🖱️ 拖拽交互实现

1. 拖拽状态管理

// 拖拽相关状态
const draggingEvent = ref(null)
const dragStartX = ref(0)
const dragStartLeft = ref(0)
const isDragging = ref(false)
const hasMovedWhileMouseDown = ref(false)
const isPointerDown = ref(false)
let clickSuppressTimer = null

2. 拖拽开始处理

const startDrag = (event, eventData) => {event.preventDefault()draggingEvent.value = eventDatadragStartX.value = event.clientXdragStartLeft.value = (eventData.startTime - 1) * 40hasMovedWhileMouseDown.value = falseisPointerDown.value = true// 添加全局鼠标事件监听document.addEventListener('mousemove', handleDrag)document.addEventListener('mouseup', stopDrag)// 设置拖拽状态isDragging.value = true// 添加拖拽样式document.body.style.cursor = 'grabbing'document.body.style.userSelect = 'none'document.body.classList.add('dragging')
}

3. 拖拽移动处理

const handleDrag = (event) => {if (!isDragging.value || !draggingEvent.value) returnconst deltaX = event.clientX - dragStartX.valueif (Math.abs(deltaX) > 3) {hasMovedWhileMouseDown.value = true}const newLeft = dragStartLeft.value + deltaX// 计算新的时间位置(基于40px单元格宽度)const newStartTime = Math.round(newLeft / 40) + 1// 边界检查const chart = sequenceCharts.value.find((c) => c.events.includes(draggingEvent.value))if (chart) {const eventDuration = draggingEvent.value.endTime - draggingEvent.value.startTime + 1const maxStartTime = chart.cellCount - eventDuration + 1// 限制在有效范围内const clampedStartTime = Math.max(1, Math.min(newStartTime, maxStartTime))const clampedEndTime = clampedStartTime + eventDuration - 1// 更新事件时间draggingEvent.value.startTime = clampedStartTimedraggingEvent.value.endTime = clampedEndTime}
}

4. 拖拽结束处理

const stopDrag = async () => {if (!isDragging.value || !draggingEvent.value) return// 显示拖拽结果const chart = sequenceCharts.value.find((c) => c.events.includes(draggingEvent.value))if (chart) {if (hasMovedWhileMouseDown.value) {ElMessage.success(`事件"${draggingEvent.value.introduction}"已移动到时间 ${draggingEvent.value.startTime}-${draggingEvent.value.endTime}`)await saveSequenceCharts()// 拖动结束后,短暂抑制 mouseup 触发编辑if (clickSuppressTimer) clearTimeout(clickSuppressTimer)clickSuppressTimer = setTimeout(() => {hasMovedWhileMouseDown.value = falseclickSuppressTimer = null}, 120)}}// 清理拖拽状态isDragging.value = falsedraggingEvent.value = null// 移除全局事件监听document.removeEventListener('mousemove', handleDrag)document.removeEventListener('mouseup', stopDrag)// 恢复样式document.body.style.cursor = ''document.body.style.userSelect = ''document.body.classList.remove('dragging')isPointerDown.value = false
}

5. 点击与拖拽冲突解决

// mouseup 时决定是否打开弹框(仅未发生拖动)
const onEventBarMouseUp = (chartId, event) => {if (hasMovedWhileMouseDown.value) {// 刚刚发生过拖动,不打开return}openEventEditor(chartId, event)
}

💾 数据持久化方案

1. 主进程文件操作

// src/main/index.js
const { ipcMain } = require('electron')
const fs = require('fs').promises
const path = require('path')// 读取事序图数据
ipcMain.handle('read-sequence-charts', async (event, bookId) => {try {const bookDir = path.join(booksDirectory, bookId)const filePath = path.join(bookDir, 'sequence-charts.json')// 确保目录存在await fs.mkdir(bookDir, { recursive: true })const data = await fs.readFile(filePath, 'utf8')return JSON.parse(data)} catch (error) {console.error('读取事序图数据失败:', error)return []}
})// 写入事序图数据
ipcMain.handle('write-sequence-charts', async (event, bookId, data) => {try {const bookDir = path.join(booksDirectory, bookId)const filePath = path.join(bookDir, 'sequence-charts.json')// 确保目录存在await fs.mkdir(bookDir, { recursive: true })await fs.writeFile(filePath, JSON.stringify(data, null, 2), 'utf8')return { success: true }} catch (error) {console.error('保存事序图数据失败:', error)return { success: false, error: error.message }}
})

2. 预加载脚本暴露API

// src/preload/index.js
const { contextBridge, ipcRenderer } = require('electron')contextBridge.exposeInMainWorld('electron', {// 事序图相关APIreadSequenceCharts: (bookId) => ipcRenderer.invoke('read-sequence-charts', bookId),writeSequenceCharts: (bookId, data) => ipcRenderer.invoke('write-sequence-charts', bookId, data)
})

3. 渲染进程数据管理

// 加载事序图数据
const loadSequenceCharts = async () => {try {const data = await window.electron.readSequenceCharts(currentBookId.value)sequenceCharts.value = data || []} catch (error) {console.error('加载事序图数据失败:', error)ElMessage.error('加载事序图数据失败')}
}// 保存事序图数据
const saveSequenceCharts = async () => {try {const result = await window.electron.writeSequenceCharts(currentBookId.value, sequenceCharts.value)if (!result.success) {throw new Error(result.error)}} catch (error) {console.error('保存事序图数据失败:', error)ElMessage.error('保存事序图数据失败')}
}// 监听数据变化自动保存
watch(sequenceCharts, saveSequenceCharts, { deep: true })

⚡ 性能优化策略

1. 虚拟滚动优化

// 对于大量事件的情况,可以考虑虚拟滚动
const visibleEvents = computed(() => {const start = scrollTop.value / itemHeightconst end = start + visibleCount.valuereturn sequenceCharts.value.slice(start, end)
})

2. 事件防抖处理

// 拖拽过程中的防抖处理
const debouncedSave = debounce(saveSequenceCharts, 300)// 在拖拽过程中使用防抖保存
const handleDrag = (event) => {// ... 拖拽逻辑debouncedSave()
}

3. 内存优化

// 组件卸载时清理定时器
onUnmounted(() => {if (clickSuppressTimer) {clearTimeout(clickSuppressTimer)}// 清理全局事件监听document.removeEventListener('mousemove', handleDrag)document.removeEventListener('mouseup', stopDrag)
})

🎯 技术亮点总结

1. 创新的交互设计

  • 拖拽与点击分离: 通过 mouseup 事件和位移检测,完美解决拖拽与点击的冲突
  • 视觉反馈: 拖拽时的视觉状态变化,提升用户体验
  • 边界限制: 智能的边界检查,防止事件拖拽到无效位置

2. 高性能渲染

  • 分层渲染: 背景网格、事件条分层渲染,提升性能
  • CSS动画: 使用CSS动画实现进度条效果,性能更优
  • 响应式设计: 基于Vue 3的响应式系统,数据变化自动更新UI

3. 数据持久化

  • 本地存储: 基于文件系统的本地存储,数据安全可靠
  • 自动保存: 数据变化自动保存,防止数据丢失
  • 错误处理: 完善的错误处理机制,提升系统稳定性

🔮 总结与展望

本文详细介绍了在小说写作软件中实现事序图功能的技术方案。通过Vue 3的响应式系统、Element Plus的UI组件、以及精心设计的交互逻辑,我们实现了一个功能完善、用户体验优秀的时间轴管理工具。

技术优势

  • 高性能: 基于Vue 3的响应式系统,渲染性能优秀
  • 易扩展: 模块化设计,易于功能扩展
  • 用户友好: 直观的拖拽交互,操作简单
  • 数据安全: 本地文件存储,数据安全可靠

未来优化方向

  • 🔮 实时协作: 支持多用户实时协作编辑
  • 🔮 模板系统: 提供预设的事件模板
  • 🔮 导出功能: 支持导出为图片或PDF格式
  • 🔮 AI辅助: 集成AI功能,智能推荐事件安排

通过这套技术方案,我们为小说创作者提供了一个强大而直观的时间轴管理工具,大大提升了创作效率和体验。


📚 相关链接

  • 项目地址: GitHub - 51mazi,给个 Star 哦~
  • 技术栈: Electron + Vue 3 + Element Plus
  • 关键词: 事序图、甘特图、时间轴管理、拖拽交互、Vue 3

🏷️ 标签

#Vue3 #ElementPlus #事序图 #甘特图 #时间轴管理 #拖拽交互 #小说写作 #前端开发


💡 如果这篇文章对你有帮助,请给个 ⭐️ 支持一下!

http://www.dtcms.com/a/495134.html

相关文章:

  • 【Spring AI】MCP Server 从 sse 升级到 streamableHttp
  • 如何基于Deepseek进行文本章节结构恢复
  • 颠覆传统测试范式:Keploy 如何用 eBPF 技术让测试“偷懒“却更高效?
  • 设计网站推荐html代码全媒体广告策划与营销
  • 企业服务网站开发简要说明网站制作的基本步骤
  • 伊萨推出升级版SUPRAREX™ PRO自动化切割设备:更大尺寸、更强结构、更高安全性、更易维护
  • 如何在本地部署大语言模型(Windows,Mac,Linux)三系统教程
  • 营销型网站建设营销型套网站模板软件
  • 【昆明市不动产登记中心-注册安全分析报告】
  • 2008iis添加网站打不开深圳前50强网站建设公司
  • graph neural architecture search
  • HTTP方法GET,HEAD,POST,PUT,PATCH,DELETE,OPTIONS,TRACE,RESTful API设计的核心详解
  • 用CMake 实现U8g2 的 SDL2 模拟环境
  • 企业网站排名提升软件智能优化wordpress 创业
  • 企业网站建设调查问卷网站开发周记30篇
  • 网站模板网站免费建商城网站
  • 安徽感智教育科技有限公司成功加入安徽省物流协会
  • Chart.js 雷达图
  • 百分点科技发布中国首个AI原生GEO产品Generforce,助力品牌决胜AI搜索新时代
  • 微算法科技(MLGO)突破性AI推理控制:一种基于集成学习优化算法的无线传感设备边缘协同推理控制技术
  • 智存跃迁,阿里云存储面向 AI 升级全栈数据存储能力
  • 临淄专业网站优化哪家好g3云推广官网
  • python离线包安装方法总结
  • Docker网络和存储卷
  • REFRAG技术详解:如何通过压缩让RAG处理速度提升30倍
  • C++ stack、queue栈和队列的使用——附加算法题
  • 论文解读--RCBEVDet++:Toward High-accuracy Radar-Camera Fusion 3D Perception Network
  • 网站建设公司 温州百度优化大师
  • Kubernetes:Ingress - Traefik
  • 自然的铁律与理想的迷梦:论阿伦特政治哲学的局限与谬误​​