










在复杂项目管理中,传统的表格视图往往难以直观展现任务的层级关系与依赖结构。如何让管理者“一眼看清”项目全貌?如何让用户自由切换视角——既能在表格中精细编辑,又能在脑图中宏观把控?
本文将基于真实的 Vue3 + TypeScript 项目代码与 UI 界面,深度解析如何构建一个支持多视图切换的企业级督办任务系统。我们将聚焦于脑图模式渲染引擎、五级任务层级控制、状态标签可视化以及批量操作联动机制,带你掌握现代企业级应用的核心架构能力。
本系统突破传统任务管理工具的局限,实现“数据驱动 + 视觉表达”的双重升级:
系统采用“数据层 - 视图层”分离架构,所有视图共享同一份 taskTree 数据结构,仅通过组件渲染逻辑差异实现不同呈现形式。
// 统一数据结构定义
interface TaskNode {
id: number;
name: string;
level: 1 | 2 | 3 | 4 | 5; // 任务层级
status: 'pending' | 'processing' | 'completed' | 'failed';
children?: TaskNode[];
parentId?: number;
deadline?: string;
assignee?: string;
}
// 视图模式枚举
enum ViewMode {
LIST = 'list',
TABLE = 'table',
MINDMAP = 'mindmap'
}
const currentViewMode = ref<ViewMode>(ViewMode.MINDMAP);
UI 实现:
currentViewMode 动态渲染对应组件:
ListView.vue → 扁平化列表TableView.vue → Ant Design TableMindMapView.vue → 自定义树形结构渲染器<template>
<div class="view-container">
<ListView v-if="currentViewMode === 'list'" :data="filteredTasks" />
<TableView v-else-if="currentViewMode === 'table'" :data="filteredTasks" />
<MindMapView v-else-if="currentViewMode === 'mindmap'" :data="rootTask" />
</div>
</template>
脑图模式是本系统的视觉核心,采用递归组件 + 自定义 SVG 连线的方式,实现清晰美观的树状结构展示。
<!-- MindMapNode.vue -->
<template>
<div class="node-wrapper">
<!-- 当前节点卡片 -->
<div class="node-card" :class="getNodeClass(node.status)">
<span class="node-title">{{ node.name }}</span>
<span class="node-status" :class="getStatusClass(node.status)">
{{ getStatusText(node.status) }}
</span>
<!-- 子节点容器 -->
<div v-if="node.children && node.children.length > 0" class="children-container">
<MindMapNode
v-for="child in node.children"
:key="child.id"
:node="child"
:level="level + 1"
/>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { computed } from 'vue';
const props = defineProps<{
node: TaskNode;
level: number;
}>();
const getNodeClass = (status: string) => {
return {
'node-pending': status === 'pending',
'node-processing': status === 'processing',
'node-completed': status === 'completed',
'node-failed': status === 'failed',
};
};
const getStatusText = (status: string) => {
const map = {
pending: '待办',
processing: '进行中',
completed: '已完成',
failed: '发布失败',
};
return map[status] || '';
};
</script>
<style scoped lang="less">
.node-card {
padding: 8px 12px;
border-radius: 6px;
background: #fff;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
margin: 8px 0;
position: relative;
&.node-pending { border-left: 4px solid #1890ff; }
&.node-processing { border-left: 4px solid #faad14; }
&.node-completed { border-left: 4px solid #52c41a; }
&.node-failed { border-left: 4px solid #f5222d; }
}
.node-status {
font-size: 12px;
margin-left: 8px;
padding: 2px 6px;
border-radius: 4px;
&.status-pending { background: #e6f7ff; color: #1890ff; }
&.status-processing { background: #fffbe6; color: #faad14; }
&.status-completed { background: #f6ffed; color: #52c41a; }
&.status-failed { background: #fff1f0; color: #f5222d; }
}
</style>
如需更专业的脑图效果,可使用 d3.js 或 vx 库绘制贝塞尔曲线连接父子节点,提升视觉专业度。
为避免深层级任务导致页面混乱,系统提供“任务展示层级”滑块,用户可自由选择显示 1~5 级中的任意组合。
<template>
<div class="filter-panel">
<div class="filter-title">任务展示层级</div>
<div class="slider-container">
<input
type="range"
min="1"
max="5"
v-model="displayLevels"
@input="handleLevelChange"
class="level-slider"
/>
<div class="level-labels">
<span v-for="i in 5" :key="i" :class="{ active: displayLevels.includes(i) }">
{{ i }}级
</span>
</div>
</div>
</div>
</template>
<script setup>
const displayLevels = ref([1, 2, 3]); // 默认显示前三级
const handleLevelChange = () => {
// 重新过滤任务树,只保留指定层级的节点
filteredTasks.value = filterByLevels(rootTask.value, displayLevels.value);
};
const filterByLevels = (node: TaskNode, levels: number[]): TaskNode | null => {
if (!levels.includes(node.level)) return null;
const newNode = { ...node };
if (node.children) {
newNode.children = node.children
.map(child => filterByLevels(child, levels))
.filter(Boolean) as TaskNode[];
}
return newNode;
};
</script>
<style scoped>
.level-slider {
width: 100%;
accent-color: #1890ff;
}
.level-labels {
display: flex;
justify-content: space-between;
margin-top: 8px;
font-size: 12px;
color: #8c8c8c;
span.active {
color: #1890ff;
font-weight: bold;
}
}
</style>
无论在列表、表格还是脑图模式下,用户均可选中多个节点执行批量操作,系统自动同步状态并刷新所有视图。
const handleBatchCreate = async () => {
const selectedNodes = getSelectedNodes(); // 获取当前视图选中的节点ID数组
if (selectedNodes.length === 0) {
message.warning('请至少选择一个任务节点');
return;
}
Modal.confirm({
title: `确定要批量发起 ${selectedNodes.length} 个任务吗?`,
content: '新任务将沿用原任务的层级结构和负责人,仅更新截止时间。',
onOk: async () => {
await batchCreateTasks({ taskIds: selectedNodes });
message.success('批量发起成功!');
refreshAllViews(); // 刷新所有视图数据
},
});
};
<template>
<a-button @click="handleBatchReport" :disabled="selectedKeys.length === 0">
<template #icon><FileTextOutlined /></template>
批量进度汇报
</a-button>
</template>
<script setup>
const handleBatchReport = () => {
showBatchReportModal(selectedKeys.value);
};
</script>
支持导出当前视图为 PNG/SVG 图片,或导出完整数据为 Excel/PDF。
const handleExportImage = async () => {
const svgElement = document.querySelector('.mindmap-svg');
if (!svgElement) return;
const canvas = await svg2canvas(svgElement);
const link = document.createElement('a');
link.download = `督办任务脑图_${formatDate(new Date())}.png`;
link.href = canvas.toDataURL('image/png');
link.click();
};
每个任务节点的状态通过颜色和图标双重标识,符合人类视觉认知习惯:
| 状态 | 颜色 | 图标 | 含义 |
|---|---|---|---|
| 待办 | 蓝色 | ⏳ | 尚未开始 |
| 进行中 | 橙色 | 🔄 | 正在执行 |
| 已完成 | 绿色 | ✅ | 已成功完成 |
| 发布失败 | 红色 | ❌ | 提交或分发失败 |
<span class="node-status" :class="`status-${node.status}`">
<IconComponent :name="getStatusIcon(node.status)" />
{{ getStatusText(node.status) }}
</span>
computed 缓存过滤后的任务树,避免重复计算。这套督办任务系统不仅是一个管理工具,更是组织执行力的可视化载体。它通过将抽象的目标转化为具象的节点网络,帮助团队建立共同的语言和节奏感。无论是政府机关、大型企业还是教育机构,都能从中获得高效协同的价值。
💡 未来展望:后续可引入 AI 辅助任务拆解、甘特图时间轴、资源冲突检测等功能,让系统更加智能化、自动化。
技术栈:Vue3 | TypeScript | Ant Design Vue | D3.js (可选) | SVG | FileSaver
适用场景:政务督办 | 企业OKR管理 | 教育项目跟踪 | 研发任务分解
如果你觉得这篇文章对你有帮助,欢迎点赞、收藏!有任何关于脑图渲染优化或多视图同步的问题,欢迎在评论区交流~
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。