一、需求:
做一個部門的結構樹,樣子大概是如下圖這樣展示:
示例圖
二、分析:
做成這樣的一個效果圖,雖然可以寫但會比較麻煩,其實現在是有很多這樣的前端控件幫我們實現,只需要我們按照要求傳遞數據即可,這就不需要重複造輪子。
例如:Esay UI的tree控件,Echarts的圖表展示,這兩個都是常用的。
本文就是用Echarts來展示結構樹。
三、Echarts的基本使用
Echarts的使用很簡單,只需要從官網下載引入js文件,或直接引入CDN<script src="https://cdn.bootcss.com/echarts/4.4.0-rc.1/echarts.min.js"></script>
然後只需要在js裏調用,並傳JSON數據即可,直接看我下方代碼例子,應該都能看懂的,至於有關於Echarts的其他參數的配置說明,可以再自行查看官網。
//展示結構樹的容器
<div id="item" style="width:1200px; height: 500px;">
<script>
//初始化echarts實例
var myChart = echarts.init(document.getElementById('item'));
//使用制定的配置項和數據顯示圖表
//myChart.showLoading(); //顯示Loading標誌;
//$.get('data/asset/data/flare.json', function (data) {
// myChart.hideLoading(); //得到數據後隱藏Loading標誌
// echarts.util.each(data.children, function (datum, index) {
// index % 2 === 0 && (datum.collapsed = true);
// }); //間隔展開子數據,animate,display,physics,scale,vis是展開的
option = {
calculable: false,
tooltip: {
// show:'true',//默認:true;是否顯示提示框組件,包括提示框浮層和 axisPointer。
trigger: 'item',//默認:item;觸發類型。item:數據項圖形觸發,主要在散點圖,餅圖等無類目軸的圖表中使用。'axis':座標軸觸發,主要在柱狀圖,折線圖等會使用類目軸的圖表中使用。'none':什麼都不觸發。
//formatter: '{b}:{c}',
hideDelay: 0 // chart.refresh();刷新時會維持當時圖表的所有狀態,所以設置隱藏延遲爲0,否則在快速選擇另一個節點時(尤其是數據比較多時)導致無法顯示選擇中的tooltip
//無法完全避免但是很大減輕了副作用
},
series: [
{
name: '樹圖',
type: 'tree',
orient: 'vertical', // vertical horizontal
rootLocation: { x: 'center', y: 30 }, // 根節點位置 {x: 100, y: 'center'}
nodePadding: 50,//節點間距
symbolSize: 50,//tree圖上的原型的大小
//symbol: 'circle',
//roam: true,//設置次參數後,針對該圖表可以放大和縮小,移動
initialTreeDepth: 3,//初始顯示節點深度
itemStyle: {
normal: {
label: {
show: true,
formatter: "{b}",
position: 'inside',
textStyle: {
color: '#000',
fontSize: 12,
fontWeight: 'bolder'
}
},
lineStyle: {
color: '#48b',
shadowColor: '#000',
shadowBlur: 4,
shadowOffsetX: 3,
shadowOffsetY: 5,
type: 'curve' // 'curve'|'broken'|'solid'|'dotted'|'dashed'
}
},
emphasis: {
label: {
show: true
}
}
},
data: [
{
name: '根節點',
value: 6,
children: [
{
name: '節點1',
value: 4,
children: [
{
name: '葉子節點1',
value: 4
},
{
name: '葉子節點2',
value: 4
},
{
name: '葉子節點3',
value: 2
}
]
},
{
name: '節點2',
value: 4,
children: [{
name: '葉子節點7',
value: 4
},
{
name: '葉子節點8',
value: 4
}]
},
{
name: '節點3',
value: 1,
children: [
{
name: '葉子節點9',
value: 4
},
{
name: '葉子節點10',
value: 4
},
{
name: '葉子節點11',
value: 2
},
{
name: '葉子節點12',
value: 2
}
]
},
{
name: '節點8',
value: 1,
children: [
{
name: '葉子節點9',
value: 4
},
{
name: '節點2',
value: 4,
children: [{
name: '葉子節點7',
value: 4
},
{
name: '葉子節點8',
value: 4
}]
}
]
}
]
}
]
}
]
};
myChart.setOption(option);
</script>
Echarts官方示例
四、遞歸構建JSON
所以,從上面的Echarts使用可以知道,我們接下來需要做的就是生成一個對應結構的json傳遞到前端。
先說明一下,我的數據特點,ID
是主鍵,不存在會有相同列的數據,NAME_SHORT
就是一個展示名稱,BELONG_ID
表示一個層級關係,相同根節點下的子節點,BELONG_ID
相同,數據取自ID
。
1. 建立用來保存樹結構數據的目標對象
public class TreeObject
{
public string name { get; set; }
public string value { get; set; }
public IList<TreeObject> children = new List<TreeObject>();
public void Addchildren(TreeObject node)
{
this.children.Add(node);
}
}
2.查詢表獲得數據源
/// <summary>
///數據庫的連接字符串
/// </summary>
private static readonly string connstr = @"server=.;database=userInfo;uid=sa;pwd=123456";;
public DataTable getTable(string cmdText)
{
using (SqlConnection cnn = new SqlConnection(connstr))
{
using (SqlCommand comm = new SqlCommand(cmdText, cnn))
{
comm.CommandType = CommandType.Text;
SqlDataAdapter da = new SqlDataAdapter();
da.SelectCommand = comm;
DataTable mytable = new DataTable();
da.Fill(mytable);
return mytable;
}
}
}
public DataTable GetDataTable()
{
string sql = @"select ID,NAME_SHORT,BELONGTO_ID
from UserInfo
order by BELONGTO_ID"
;
DataTable dt = getTable(sql);
return dt;
}
3.遞歸循環生成樹
//全局變量用於保存數據
public List<TreeObject> treeNodes = new List<TreeObject>();
//建立樹的遞歸方法
/// </summary>
/// <param name="dtSource">數據源</param>
/// <param name="parentNode">父節點</param>
/// <param name="parentID">節點的歸屬ID</param>
public void BindTree(DataTable dtSource, TreeObject parentNode, string parentID)
{
DataRow[] rows = dtSource.Select(string.Format("BELONGTO_ID={0}", parentID));
foreach (DataRow row in rows)
{
TreeObject tree = new TreeObject();
tree.name = row["NAME_SHORT"].ToString();
tree.value = row["ID"].ToString();
//遞歸性質,函數內調用自身函數
BindTree(dtSource, tree, row["ID"].ToString());
//遞歸結束的終點條件
if (parentNode == null)
{
treeNodes.Add(tree);
}
else
{
parentNode.children.Add(tree);
}
}
}
4.調用
//調用SQL,獲取數據源
DataTable dt = GetDataTable();
//調用遞歸函數,傳入數據源,根節點
BindTree(dt, null, "0");
//反序列化對象,生成json字符串
string jsonData = JsonConvert.SerializeObject(treeNodes);
return jsonData;
5.效果
[{
"name": 'A',
"value": '10000',
"children": [{
"name": 'B1',
"value": '10002',
"children": [{
"children": [],
"name": 'C',
"value": '10007'
},
{
"children": [],
"name": 'D',
"value": '10008'
},
{
"children": [],
"name": 'E',
"value": '10009'
}
]
},
{
"name": 'B2',
"value": '10003',
"children": [{
"children": [],
"name": 'F',
"value": '10010'
},
{
"children": [],
"name": 'G',
"value": '10011'
}
]
},
{
"name": 'B3',
"value": '10004',
"children": [{
"children": [],
"name": 'H',
"value": '10012'
},
{
"children": [],
"name": 'I',
"value": '10013'
},
{
"children": [],
"name": 'J',
"value": '10014'
}
]
},
{
"name": 'B4',
"value": '10005',
"children": [{
"children": [],
"name": 'K',
"value": '10015'
},
{
"name": 'L',
"value": '10016',
"children": [{
"children": [],
"name": 'L1',
"value": '10017'
},
{
"children": [],
"name": 'L2',
"value": '10018'
}
]
}
]
}
]
}]
效果圖
五、總結
以上就是全部代碼了,從代碼來說,不難,整個過程就是引入Echarts,傳遞json數據。
因此最需要做的就是生成對應結構的json,而做這些循環嵌套,使用遞歸逐步深入還是比較簡單,可能先嚐試遞歸兩三層來找到遞歸的規律,這個還是需要根據自己數據結構來做。