效果图
image.png
介绍
- 支持点击任何族人时,高亮显示该族人同一支的信息
- 通过颜色区分族人属性, 属性包括: 男、女、死亡、在世
- 前端go.js
- 后端 python+Flask+sqlAlchemy+Jinja2
变量解释
参数名 |
必选 |
类型 |
说明 |
clansmen_id |
是 |
Integer |
族人id |
current_level |
是 |
string |
当前辈分 |
parent_id |
是 |
Integer |
上辈族人id |
array |
是 |
string |
上下级族人信息列表 |
array列表单个元素数据格式
参数名 |
必选 |
类型 |
说明 |
clansmen_id |
是 |
Integer |
族人id |
level |
是 |
Integer |
族人辈分 |
clansmen_name |
是 |
String |
族人名称 |
parent_id |
是 |
Integer |
上辈族人id |
status |
是 |
String |
族人状态 00-在世 01-去世 |
companion_id |
是 |
Integer |
老伴id |
companion_name |
是 |
String |
老伴姓名 |
companion_status |
是 |
String |
老伴状态 00-在世 01-去世 |
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>红花堂</title>
<meta name="description" content="A larger org chart with an Overview and searching capability."/>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script type="text/javascript" src="{{url_for('family_api.static', filename='js/go.js')}}"></script>
<script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script>
<link rel="icon"
type="image/png"
href="{{url_for('family_api.static', filename='images/favicon.ico')}}">
<style type="text/css">
#myOverviewDiv {
position: absolute;
width: 200px;
height: 100px;
top: 10px;
left: 10px;
background-color: aliceblue;
z-index: 300;
/* make sure its in front */
border: solid 1px blue;
}
</style>
</head>
<body style="background-color: #696969" >
<div style="margin:0 auto;outline: rgba(50,50,50,0.8) ridge 1.5px;">
<div id="sample" style="position: relative;">
<div id="myDiagramDiv"
style="background-color: white; border: solid 1px black; width: 100%; min-height:100vh;"></div>
<!-- <div id="myOverviewDiv"></div>-->
</div>
</div>
<script>
function invite(men_id) {
if (isAndroid()) {
new ModelFactory("android", "invites", "backToAndroid").excuse({
'men_id': men_id
});
} else if (isIOS()) {
window.webkit.messageHandlers.invite.postMessage({
'men_id': men_id
});
} else {
return false;
}
}
function get_men_info(men_id) {
console.log(men_id);
invite(men_id);
};
function isAndroid() {
var u = navigator.userAgent,
app = navigator.appVersion;
return u.indexOf('Android') > -1 || u.indexOf('Linux') > -1;
}
function isIOS() {
var u = navigator.userAgent,
app = navigator.appVersion;
return !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);
}
function ModelFactory(equipment, clz, method) {
if (equipment == 'ios') {
this.modelObj = window.eval("window.webkit.messageHandlers." + method);
this.modelMethod = this.modelObj["postMessage"];
} else if (equipment == 'android') {
this.modelObj = window[clz];
this.modelMethod = this.modelObj[method];
} else {
window.location.href = 'error.html';
}
this.constructor.prototype.excuse = function (args) {
var jsonParams = JSON.stringify(args);
return this.modelMethod.call(this.modelObj, jsonParams);
}
}
</script>
<script type="text/javascript">
window.onload = tree_init();
function tree_init() {
var myGoGrap = go.GraphObject.make; // for conciseness in defining templates
myDiagram = myGoGrap(go.Diagram, "myDiagramDiv", // the DIV HTML element
{
// allowSelect: false,
isReadOnly: true, // 只读
allowDrop: false,
// hasHorizontalScrollbar:false,//去除水平滚动条
// hasVerticalScrollbar:false,//去除竖直滚动条
initialDocumentSpot: go.Spot.TopCenter,
// initialViewportSpot: go.Spot.TopCenter,
initialViewportSpot: go.Spot.TopCenter,
//initialContentAlignment: go.Spot.Center,
layout:
myGoGrap(go.TreeLayout, // use a TreeLayout to position all of the nodes
{
treeStyle: go.TreeLayout.StyleLastParents,
arrangement: go.TreeLayout.ArrangementHorizontal,
angle: 90, // 角度 描述从父节点到子节点的生长方向 0/180 子节点形成垂直的层次-宽度是高度 深度是宽度;90/270 子节点形水平层
layerSpacing: 25, //父节点与子节点之间的距离 宽度是宽度 深度是高度
alternateAngle: 90,
alternateLayerSpacing: 35,
alternateNodeSpacing: 20,
})
});
/**判断第一行内容
儿子:夫
女儿:女
*/
function oneInfoText(info) {
var str = "";
var name = "";
if (info.name != null) {
name = info.name;
}else{
name = "";
}
str = name;
//if (info.sex === "00") {
// str = "夫:" + name;
//} else {
// str = "女:" + name;
//}
//if (info.is_adoptive === "1") {
// str = "【过】" + str
//}
return str;
}
/**判断第二行内容
儿媳:妻
女婿:婿
*/
function twoInfoText(info) {
var str = "";
var name = "";
if (info.companion_name != null) {
name = info.companion_name;
}else{
name = "";
}
str = name;
//if (info.sex === "00") {
// str = "妻:" + name;
//} else {
// str = "婿:" + name;
//}
//if (info.is_ruzhui === "1") {
// str = "【婿】" + str;
//}
return str;
}
/*判断第一行背景颜色
去世: 黑色
儿子-酒红色
女儿-粉红色
*/
function oneInfobackground(info) {
var status = info.status;
if (status === null) {
status = '00';
}
if (info.sex === '00') {
//儿子
if (status === '00') {
//在世 酒红色
return '#99110f'
} else {
//去世
return 'black';
}
} else {
//女儿
if (status === '00') {
//在世 粉红色
return '#FF33CC'
} else {
//去世
return 'black';
}
}
}
/*判断第二行背景颜色
去世: 黑色
儿媳-酒红色
女婿-粉红色
*/
function twoInfobackground(info) {
if (info.companion_name === null || info.companion_name === "") {
return 'white';
}
var companion_status = info.companion_status;
if (companion_status === null) {
companion_status = '00';
}
if (info.sex === '01') {
//女婿
if (companion_status === '00') {
//在世 酒红色
return '#FF33CC'
} else {
//去世
return 'black';
}
} else {
//儿媳
if (companion_status === '00') {
//在世 粉红色
return '#99110f'
} else {
//去世
return 'black';
}
}
}
var node_item_arr = [];
var current_node = "";
/*
* 子节点以及子节点连线高亮函数
*/
function ergodicChildNode(node) {
var item = node.findTreeChildrenNodes().iterator;
if (node_item_arr.indexOf(item) > -1) {
item = node_item_arr.pop();
}
node.findTreeChildrenLinks().each(function (l) { l.isHighlighted = true; });
node.findTreeChildrenNodes().each(function (n) { n.isHighlighted = true; });
if (item.next()) {
current_node = item.value;
node_item_arr.push(item);
ergodicChildNode(current_node);
} else {
item = node_item_arr.pop();
if (item) {
if (item.next()) {
current_node = item.value;
node_item_arr.push(item);
ergodicChildNode(current_node);
} else {
ergodicChildNode(current_node);
}
}
}
}
//点击情况
var click_bool = false;
//当前选择的node
var current_click_node = "";
// define the Node template
myDiagram.nodeTemplate =
myGoGrap(go.Node, "Auto",
{ // when the user clicks on a Node, highlight all Links coming out of the node
// and all of the Nodes at the other ends of those Links.
click: function (e, node) {
if (current_click_node != node) {
current_click_node = node;
click_bool = false;
}
if(click_bool === false){
// highlight all Links and Nodes coming out of a given Node
var diagram = node.diagram;
diagram.startTransaction("highlight");
// remove any previous highlighting
diagram.clearHighlighteds();
//所有父级节点以及连接线高亮
// console.log(node.findTreeParentChain());
node.findTreeParentChain().each(function (n) { n.isHighlighted = true; });
//所有子节点以及连接高亮
ergodicChildNode(node);
diagram.commitTransaction("highlight");
click_bool = true;
}else{
click_bool = false;
get_men_info(node.data.key);
}
}
},
myGoGrap(
go.Shape,
"RoundedRectangle",
{ stroke: "#9f201e", strokeWidth: 3, fill: "white", },
new go.Binding("stroke", "isHighlighted", function (h) { return h ? "#0080FF" : "#9f201e"; }).ofObject()
),
myGoGrap(go.Panel, "Table",
{
margin: 2,
maxSize: new go.Size(120, NaN),
},
myGoGrap(go.RowColumnDefinition,
{
column: 0,
stretch: go.GraphObject.Horizontal,
alignment: go.Spot.Center
}),
// the 夫
myGoGrap(go.TextBlock,
{
row: 0,
column: 0,
width: 200,
textAlign: 'center',
graduatedSkip: false,
stroke: 'white',
maxSize: new go.Size(NaN, NaN),
margin: 2,
font: "400 25px Roboto, sans-serif",
alignment: go.Spot.Center
},
new go.Binding("text", "", oneInfoText),
new go.Binding("background", "", oneInfobackground)),
myGoGrap(go.TextBlock,
{
row: 1,
column: 0,
width: 200,
textAlign: 'center',
background: '#99110f',
graduatedSkip: false,
stroke: 'white',
maxSize: new go.Size(NaN, NaN),
margin: 2,
font: "400 25px Roboto, sans-serif",
alignment: go.Spot.Center
},
new go.Binding("text", "", twoInfoText),
new go.Binding("background", "", twoInfobackground)),
) // end Table Panel
); // end Node
// define the Link template, a simple orthogonal line
myDiagram.linkTemplate =
myGoGrap(
go.Link,
go.Link.Orthogonal,
{ corner: 5, selectable: true, toShortLength: 0 },
myGoGrap(go.Shape,
// the Shape.stroke color depends on whether Link.isHighlighted is true
new go.Binding("stroke", "isHighlighted", function (h) { return h ? "#0080FF" : "#99110f"; })
.ofObject(),
// the Shape.strokeWidth depends on whether Link.isHighlighted is true
new go.Binding("strokeWidth", "isHighlighted", function (h) { return h ? 3 : 1; })
.ofObject(),
),
); // dark gray, rounded corner links
var nodeDataArray_2;
var current_node = "";
var nodeObject = "";
function get_tree_data() {
var tree_data;
$.ajax({
type: "POST",
url: "{{tree_data_url}}",
contentType: "application/json",
dataType: "json",
async: false,
data: JSON.stringify({
"method": "family.app.clansmen.all.data",
"biz_content": {
"clansmen_id": {{clansmen_id}},
"client_type": "h5",
}
}),
success: function (jsonResult) {
tree_data = jsonResult;
}
});
return tree_data;
};
nodeObject = get_tree_data();
nodeDataArray_2 = nodeObject.resp_data.array;
current_node = nodeObject.resp_data.clansmen_id;
delete nodeDataArray_2[0].parent_id;
// create the Model with data for the tree, and assign to the Diagram
myDiagram.model =
myGoGrap(go.TreeModel,
{
nodeParentKeyProperty: "parent_id", // this property refers to the parent node data
nodeDataArray: nodeDataArray_2
});
// 当关系图第一次就绪时调用此事件处理程序 定位中心节点
myDiagram.addDiagramListener("InitialLayoutCompleted", function (e) {
// pick a random node data
var cnt = 0;
for(cnt; cnt< nodeDataArray_2.length;cnt++){
if(current_node === nodeDataArray_2[cnt].key){
break;
}
}
var data = nodeDataArray_2[cnt];
// find the corresponding Node
var node = myDiagram.findNodeForData(data);
// and center it and select it
myDiagram.centerRect(node.actualBounds);
myDiagram.select(node);
});
myDiagram.click = function (e) {
e.diagram.commit(function (d) { d.clearHighlighteds(); }, "no highlighteds");
};
// Overview
//myOverview =
// myGoGrap(go.Overview, "myOverviewDiv", // the HTML DIV element for the Overview
// { observed: myDiagram, contentAlignment: go.Spot.Center }); // tell it which Diagram to show and pan
}
</script>
</body>
</html>
网友评论