工序路径主子分节点树状图层级展示组件
·
依据上述代码文件夹,开发一个主页面包含工序路径的主子分节点树状图的页面,相关功能菜单工序查看看板页面,预备5,6组工序数据,项目框架主要使用ASP.NET Core Razor Pages,实现本地文件数据库的Web端页面实现的代码解决方案实现组件
ASP.NET Core Razor Pages 工序路径树状图解决方案
一、项目结构
plaintext
ProcessTreeDemo/
├── Data/
│ ├── AppDbContext.cs // 数据库上下文(本地文件数据库)
│ └── ProcessData.json // 本地JSON数据文件
├── Models/
│ └── ProcessNode.cs // 工序节点模型
├── Pages/
│ ├── ProcessDashboard.cshtml // 工序查看看板页面
│ ├── ProcessDashboard.cshtml.cs
│ ├── _Layout.cshtml // 布局页面
│ └── Index.cshtml // 主页面
├── wwwroot/
│ ├── css/
│ │ └── treeview.css // 树状图样式
│ └── js/
│ ├── jquery.min.js // jQuery(树状图依赖)
│ └── treeview.js // 树状图逻辑
├── Program.cs
└── appsettings.json


二、核心实现代码
1. 模型定义(ProcessNode.cs)
csharp
运行
using System;
using System.Collections.Generic;
namespace ProcessTreeDemo.Models
{
/// <summary>
/// 工序节点模型
/// </summary>
public class ProcessNode
{
/// <summary>
/// 节点ID
/// </summary>
public int Id { get; set; }
/// <summary>
/// 节点名称
/// </summary>
public string Name { get; set; }
/// <summary>
/// 父节点ID(0表示根节点)
/// </summary>
public int ParentId { get; set; }
/// <summary>
/// 工序编码
/// </summary>
public string Code { get; set; }
/// <summary>
/// 工序描述
/// </summary>
public string Description { get; set; }
/// <summary>
/// 子节点集合
/// </summary>
public List<ProcessNode> Children { get; set; } = new List<ProcessNode>();
}
}
2. 本地文件数据库上下文(AppDbContext.cs)
csharp
运行
using System;
using System.Collections.Generic;
using System.IO;
using System.Text.Json;
using ProcessTreeDemo.Models;
namespace ProcessTreeDemo.Data
{
public class AppDbContext
{
private readonly string _dataFilePath;
public AppDbContext(IWebHostEnvironment env)
{
// 配置JSON数据文件路径
_dataFilePath = Path.Combine(env.ContentRootPath, "Data", "ProcessData.json");
// 初始化数据(如果文件不存在)
InitDataIfNotExists();
}
/// <summary>
/// 获取所有工序节点
/// </summary>
public List<ProcessNode> GetAllProcessNodes()
{
var json = File.ReadAllText(_dataFilePath);
return JsonSerializer.Deserialize<List<ProcessNode>>(json) ?? new List<ProcessNode>();
}
/// <summary>
/// 初始化测试数据
/// </summary>
private void InitDataIfNotExists()
{
if (!File.Exists(_dataFilePath))
{
var testData = new List<ProcessNode>
{
// 根节点1:总装工序
new ProcessNode { Id = 1, Name = "总装工序", ParentId = 0, Code = "ZG001", Description = "产品总装主流程" },
// 子节点1-1:壳体装配
new ProcessNode { Id = 2, Name = "壳体装配", ParentId = 1, Code = "ZG001-01", Description = "产品壳体组装" },
// 子节点1-1-1:壳体打磨
new ProcessNode { Id = 3, Name = "壳体打磨", ParentId = 2, Code = "ZG001-01-01", Description = "壳体表面打磨处理" },
// 子节点1-1-2:壳体拼接
new ProcessNode { Id = 4, Name = "壳体拼接", ParentId = 2, Code = "ZG001-01-02", Description = "壳体各部件拼接" },
// 子节点1-2:核心部件安装
new ProcessNode { Id = 5, Name = "核心部件安装", ParentId = 1, Code = "ZG001-02", Description = "核心功能部件安装" },
// 根节点2:检测工序
new ProcessNode { Id = 6, Name = "检测工序", ParentId = 0, Code = "JC001", Description = "产品质量检测主流程" },
// 子节点2-1:通电检测
new ProcessNode { Id = 7, Name = "通电检测", ParentId = 6, Code = "JC001-01", Description = "产品通电功能检测" },
// 子节点2-2:外观检测
new ProcessNode { Id = 8, Name = "外观检测", ParentId = 6, Code = "JC001-02", Description = "产品外观缺陷检测" },
// 根节点3:包装工序
new ProcessNode { Id = 9, Name = "包装工序", ParentId = 0, Code = "BZ001", Description = "产品包装主流程" },
new ProcessNode { Id = 10, Name = "防静电包装", ParentId = 9, Code = "BZ001-01", Description = "电子部件防静电包装" },
new ProcessNode { Id = 11, Name = "外箱封装", ParentId = 9, Code = "BZ001-02", Description = "成品外箱密封封装" },
// 根节点4:调试工序
new ProcessNode { Id = 12, Name = "调试工序", ParentId = 0, Code = "TS001", Description = "产品功能调试主流程" },
new ProcessNode { Id = 13, Name = "参数调试", ParentId = 12, Code = "TS001-01", Description = "产品运行参数调试" },
new ProcessNode { Id = 14, Name = "兼容性调试", ParentId = 12, Code = "TS001-02", Description = "多场景兼容性调试" },
// 根节点5:入库工序
new ProcessNode { Id = 15, Name = "入库工序", ParentId = 0, Code = "RK001", Description = "成品入库主流程" },
new ProcessNode { Id = 16, Name = "库位分配", ParentId = 15, Code = "RK001-01", Description = "成品库位自动分配" },
new ProcessNode { Id = 17, Name = "入库登记", ParentId = 15, Code = "RK001-02", Description = "成品入库系统登记" },
// 根节点6:物流工序
new ProcessNode { Id = 18, Name = "物流工序", ParentId = 0, Code = "WL001", Description = "产品物流配送主流程" },
new ProcessNode { Id = 19, Name = "物流打包", ParentId = 18, Code = "WL001-01", Description = "物流专用打包处理" },
new ProcessNode { Id = 20, Name = "物流配送", ParentId = 18, Code = "WL001-02", Description = "按区域物流配送" }
};
var json = JsonSerializer.Serialize(testData, new JsonSerializerOptions { WriteIndented = true });
File.WriteAllText(_dataFilePath, json);
}
}
}
}
3. 程序入口配置(Program.cs)
csharp
运行
using ProcessTreeDemo.Data;
var builder = WebApplication.CreateBuilder(args);
// 添加Razor Pages支持
builder.Services.AddRazorPages();
// 注册本地文件数据库上下文
builder.Services.AddScoped<AppDbContext>();
var app = builder.Build();
// 配置中间件
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
// 配置Razor Pages路由
app.MapRazorPages();
app.Run();
4. 布局页面(_Layout.cshtml)
html
预览
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - 工序路径管理系统</title>
<link rel="stylesheet" href="~/css/treeview.css" />
<script src="~/js/jquery.min.js"></script>
</head>
<body>
<header>
<nav style="background-color: #333; padding: 15px;">
<div style="display: flex; gap: 20px;">
<a href="/" style="color: white; text-decoration: none; font-size: 16px;">首页</a>
<a href="/ProcessDashboard" style="color: white; text-decoration: none; font-size: 16px;">工序查看看板</a>
</div>
</nav>
</header>
<div style="padding: 20px;">
@RenderBody()
</div>
@RenderSection("Scripts", required: false)
</body>
</html>
5. 主页面(Index.cshtml + Index.cshtml.cs)
Index.cshtml.cs
csharp
运行
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using ProcessTreeDemo.Data;
using ProcessTreeDemo.Models;
using System.Collections.Generic;
using System.Linq;
namespace ProcessTreeDemo.Pages
{
public class IndexModel : PageModel
{
private readonly AppDbContext _dbContext;
public IndexModel(AppDbContext dbContext)
{
_dbContext = dbContext;
}
/// <summary>
/// 层级化的工序节点数据
/// </summary>
public List<ProcessNode> HierarchicalProcessNodes { get; set; }
public void OnGet()
{
// 获取所有节点
var allNodes = _dbContext.GetAllProcessNodes();
// 构建层级结构
HierarchicalProcessNodes = BuildHierarchicalTree(allNodes);
}
/// <summary>
/// 构建树状层级结构
/// </summary>
private List<ProcessNode> BuildHierarchicalTree(List<ProcessNode> allNodes)
{
// 根节点(ParentId=0)
var rootNodes = allNodes.Where(n => n.ParentId == 0).ToList();
// 递归构建子节点
foreach (var root in rootNodes)
{
root.Children = GetChildNodes(root.Id, allNodes);
}
return rootNodes;
}
/// <summary>
/// 递归获取子节点
/// </summary>
private List<ProcessNode> GetChildNodes(int parentId, List<ProcessNode> allNodes)
{
var childNodes = allNodes.Where(n => n.ParentId == parentId).ToList();
foreach (var child in childNodes)
{
child.Children = GetChildNodes(child.Id, allNodes);
}
return childNodes;
}
}
}
Index.cshtml
html
预览
@page
@model ProcessTreeDemo.Pages.IndexModel
@{
ViewData["Title"] = "工序路径树状图";
}
<h1>工序路径主子分节点树状图</h1>
<div class="tree-view">
@foreach (var rootNode in Model.HierarchicalProcessNodes)
{
<partial name="_ProcessNodePartial" model="rootNode" />
}
</div>
@section Scripts {
<script src="~/js/treeview.js"></script>
}
<!-- 节点分部视图 -->
<partial name="_ProcessNodePartial" model="Model.HierarchicalProcessNodes.FirstOrDefault()" />
6. 工序节点分部视图(_ProcessNodePartial.cshtml)
html
预览
@model ProcessTreeDemo.Models.ProcessNode
<div class="tree-node">
<div class="node-header" data-node-id="@Model.Id">
<span class="toggle-icon">⊞</span>
<span class="node-info">
<strong>@Model.Name</strong>
(编码:@Model.Code) - @Model.Description
</span>
</div>
@if (Model.Children.Any())
{
<div class="node-children">
@foreach (var child in Model.Children)
{
<partial name="_ProcessNodePartial" model="child" />
}
</div>
}
</div>
7. 工序查看看板页面(ProcessDashboard.cshtml + ProcessDashboard.cshtml.cs)
ProcessDashboard.cshtml.cs
csharp
运行
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using ProcessTreeDemo.Data;
using ProcessTreeDemo.Models;
using System.Collections.Generic;
namespace ProcessTreeDemo.Pages
{
public class ProcessDashboardModel : PageModel
{
private readonly AppDbContext _dbContext;
public ProcessDashboardModel(AppDbContext dbContext)
{
_dbContext = dbContext;
}
/// <summary>
/// 所有工序节点数据
/// </summary>
public List<ProcessNode> AllProcessNodes { get; set; }
public void OnGet()
{
AllProcessNodes = _dbContext.GetAllProcessNodes();
}
}
}
ProcessDashboard.cshtml
html
预览
@page
@model ProcessTreeDemo.Pages.ProcessDashboardModel
@{
ViewData["Title"] = "工序查看看板";
}
<h1>工序查看看板</h1>
<!-- 工序数据表格 -->
<table style="width: 100%; border-collapse: collapse; margin-top: 20px;">
<thead>
<tr style="background-color: #f2f2f2;">
<th style="border: 1px solid #ddd; padding: 8px;">节点ID</th>
<th style="border: 1px solid #ddd; padding: 8px;">工序名称</th>
<th style="border: 1px solid #ddd; padding: 8px;">工序编码</th>
<th style="border: 1px solid #ddd; padding: 8px;">父节点ID</th>
<th style="border: 1px solid #ddd; padding: 8px;">描述</th>
</tr>
</thead>
<tbody>
@foreach (var node in Model.AllProcessNodes)
{
<tr>
<td style="border: 1px solid #ddd; padding: 8px;">@node.Id</td>
<td style="border: 1px solid #ddd; padding: 8px;">@node.Name</td>
<td style="border: 1px solid #ddd; padding: 8px;">@node.Code</td>
<td style="border: 1px solid #ddd; padding: 8px;">@node.ParentId</td>
<td style="border: 1px solid #ddd; padding: 8px;">@node.Description</td>
</tr>
}
</tbody>
</table>
<!-- 树状图预览 -->
<h2 style="margin-top: 30px;">工序路径预览</h2>
<div class="tree-view" style="margin-top: 10px;">
@{
var rootNodes = Model.AllProcessNodes.Where(n => n.ParentId == 0).ToList();
foreach (var rootNode in rootNodes)
{
<partial name="_ProcessNodePartial" model="rootNode" />
}
}
</div>
@section Scripts {
<script src="~/js/treeview.js"></script>
}
8. 树状图样式(treeview.css)
css
.tree-view {
margin: 20px 0;
font-family: Arial, sans-serif;
}
.tree-node {
margin-left: 10px;
padding: 5px 0;
}
.node-header {
cursor: pointer;
padding: 5px 10px;
background-color: #f8f9fa;
border-radius: 4px;
display: inline-block;
width: 100%;
}
.node-header:hover {
background-color: #e9ecef;
}
.toggle-icon {
display: inline-block;
width: 20px;
text-align: center;
font-weight: bold;
color: #007bff;
}
.node-info {
margin-left: 5px;
}
.node-children {
margin-left: 30px;
margin-top: 5px;
display: none; /* 默认折叠子节点 */
}
.node-children.expanded {
display: block; /* 展开子节点 */
}
table {
font-size: 14px;
}
9. 树状图交互逻辑(treeview.js)
javascript
运行
$(document).ready(function () {
// 节点展开/折叠逻辑
$('.node-header').click(function () {
var $this = $(this);
var $children = $this.next('.node-children');
// 切换展开/折叠状态
$children.toggleClass('expanded');
// 更新切换图标
var $toggleIcon = $this.find('.toggle-icon');
if ($children.hasClass('expanded')) {
$toggleIcon.text('⊟');
} else {
$toggleIcon.text('⊞');
}
});
// 初始化根节点为展开状态
$('.tree-node > .node-header').each(function () {
$(this).click();
});
});
三、功能说明
- 数据存储:使用 JSON 文件作为本地数据库,初始化包含 6 组核心工序(总装、检测、包装、调试、入库、物流),每组工序包含多级子节点
- 树状图展示:
- 支持主子分节点层级展示
- 点击节点头部可展开 / 折叠子节点
- 节点包含工序名称、编码、描述等核心信息
- 工序查看看板:
- 表格形式展示所有工序数据
- 同步展示树状图预览
- 支持快速查看工序层级关系
- 交互体验:
- 节点 hover 高亮
- 根节点默认展开
- 折叠 / 展开状态可视化(⊞/⊟图标)
四、部署与运行
- 创建ASP.NET Core Razor Pages 项目(.NET 6+/7+/8+)
- 按上述项目结构创建文件并粘贴对应代码
- 确保 wwwroot 目录下引入 jQuery(可从 CDN 下载或使用本地文件)
- 运行项目,访问
/查看主页面树状图,访问/ProcessDashboard查看工序看板
五、扩展建议
- 数据持久化:可替换为 SQLite/EF Core 实现更稳定的本地数据库
- 搜索功能:添加工序名称 / 编码搜索框,过滤树状图数据
- 节点编辑:增加新增 / 修改 / 删除工序节点的功能
- 导出功能:支持将工序数据导出为 Excel/CSV 格式
- 权限控制:添加用户认证,限制工序数据操作权限
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)