首先看页面效果:
AntV官网下载F6文件到项目中与uViewUI插件
{{navTitle}}
:change:option="treeGraph.changeTreeGraphData"
style="width: 100%;height: 100%;display: flex;justify-content: center;align-items: center;">
非 APP、H5 环境不支持
storage.js文件获取session方法:
// sessionStorage获取
export function getSession(key) {
return getObjectValue(sessionStorage.getItem(getMixKey(key)))
}
graphConfig.js文件公共方法:
/** 获取Path贝塞尔曲线控制点坐标
* @param {Number} startX 弧线起始x坐标
* @param {Number} startY 弧线起始Y坐标
* @param {Number} endX 弧线结束X坐标
* @param {Number} endY 弧线结束Y坐标
* @param {Number} angle 弧线角度
*/
export function getArcPosition (startX, startY, endX, endY, angle) {
const PI = Math.PI;
// 两点间的x轴夹角弧度
const yOffset = endY - startY
const xOffset = endX - startX
let xAngle = Math.atan2(yOffset, xOffset);
// 转为角度
xAngle = 360 * xAngle / (2 * PI);
// 两点间的长度
const L = Math.sqrt(yOffset * yOffset + xOffset * xOffset);
// 计算等腰三角形斜边长度
const L2 = L / 2 / Math.cos(angle * 2 * PI / 360);
// 求第一个顶点坐标,位于下边
const top = {};
// 求第二个顶点坐标,位于上边
const bottom = {};
top.x = startX + Math.round(L2 * Math.cos((xAngle + angle) * 2 * PI / 360));
top.y = startY + Math.round(L2 * Math.sin((xAngle + angle) * 2 * PI / 360));
bottom.x = startX + Math.round(L2 * Math.cos((xAngle - angle) * 2 * PI / 360));
bottom.y = startY + Math.round(L2 * Math.sin((xAngle - angle) * 2 * PI / 360));
return { top, bottom }
}
// 折叠图标
const COLLAPSE_ICON = function COLLAPSE_ICON(x, y, r) {
return [
['M', x - r, y],
['L', x + r, y],
]
}
// 展开图标
const EXPAND_ICON = function EXPAND_ICON(x, y, r) {
return [
['M', x - r, y],
['L', x + r, y],
['M', x, y - r],
['L', x, y + r]
]
}
// 添加展开/折叠节点(canvas)
export function addCollapseNode (group, w, cfg) {
const isLeft = cfg.x < 0
const x = isLeft ? -w / 2 - 11 : w / 2 - 1
const radius = isLeft ? [2, 0, 0, 2] : [0, 2, 2, 0]
group.addShape('rect', {
attrs: {
x,
y: -8,
width: 10,
height: 18,
stroke: '#E5E5E5',
fill: '#EEF2F8',
radius,
},
name: 'marker-box',
});
//+/-
group.addShape('marker', {
attrs: {
x: x + (isLeft ? 6 : 6),
y: 1,
r: 3,
stroke: '#A9ADB7',
lineWidth: 1,
cursor: 'pointer',
symbol: cfg.collapsed ? EXPAND_ICON : COLLAPSE_ICON
},
name: 'collapse-icon',
})
}
// 默认边和箭头样式
export const defaultEdgeStyle = {
stroke: '#3849B4',
endArrow: {
path: 'M 0,0 L 5,4 L 5,-4 Z',
lineWidth: 1,
fill: '#3849B4',
},
}
/**
* 计算节点宽度和高度
* @param {Array} content 要展示的实体内容
* @param {StrNumbering} vPadding 横向内部padding
* @param {Number} hPadding 纵向内部padding
* @param {Number} defaultWidth 默认宽度
* @param {Number} maxWidth 最大宽度
* @param {Number} defaultHeight 默认高度
* @param {Number} maxHeight 最大高度
* @param {Number} otherHeight 其他占用高度
* @returns
*/
export function computeWidthHeight ({ content, vPadding = 12, hPadding = 16, defaultWidth = 200, maxWidth = 240, defaultHeight = 50, maxHeight = 160, otherHeight = 34 }) {
let rowNum = content.length
let width = defaultWidth
let defaultLength = Math.floor((width - 2 - vPadding) / 12)
let res = []
// 判断150宽度能否满足每一行数据要求
const isDissatisfy = content.some((item) => computeStrOccupyLength(item) > defaultLength)
// 如果不满足则切割字符串
if (isDissatisfy) {
width = maxWidth
defaultLength = Math.floor((width - 2 - vPadding) / 12)
for (let i = 0, l = content.length; i < l; i++) {
let item = content[i]
const matchItems = splitStr(item, defaultLength)
rowNum += (matchItems.length - 1)
res.push(...matchItems)
}
} else {
res = content
}
let height = Math.max(defaultHeight, rowNum * 14 + hPadding)
height = Math.min(height, maxHeight) + otherHeight
return {
width,
height,
content: res
}
}
// 计算字符串占用长度
function computeStrOccupyLength (str) {
let num = 0
str.split('').forEach((s) => {
if (/[0123456789.?()-:]/.test(s)) {
num += 0.5
} else {
num += 1
}
})
return Math.ceil(num)
}
// 根据数量截取字符串
function splitStr (str, maxNum) {
let num = maxNum
const res = []
let tmp = []
str.split('').forEach((s, i) => {
tmp.push(s)
if (/[0123456789.?()-:]/.test(s)) {
num -= 0.5
} else {
num -= 1
}
if (num < 1 || i === str.length - 1) {
res.push(tmp.join(''))
tmp = []
num = maxNum
}
})
return res
}
// 处理添加子节点
export function handleChildrenData (data, level) {
const res = [];
data.forEach((item) => {
const { children, name, parentId, nodeInterpret } = item;
children.forEach((subItem, index) => {
let content = subItem.name;
if (content) {
const { showType, isChildren } = subItem;
const id = `${subItem.id}_${index}`;
content = content.split('\n').filter((item) => item);
res.push({
id,
parentId,
content,
name,
nodeInterpret,
showType,
level,
collapsed: true,
hasChildren: Boolean(isChildren),
});
}
});
});
return res;
}
表格插件文件:
去插件市场下载表格插件:
我这里改了排序,数据为空默认展示,列点击事件源代码,直接复制就好:
{{item.label}}
:style="{color:lastSortItem===item.key&&sortWay=='desc'?'#3849B4':'#bcbcbc'}" />
暂无数据
style="display:flex;table-layout: fixed;min-width: 100%;" @click.native="getRow(content)">
align="center" :style="{display:header.hidden?'none':'flex',textAlign:'center',width:header.width,
left:columnFixed>0?fixedLeft(hindex):'unset',
right:columnFixed<0?fixedRight(hindex):'unset',
justifyContent:'center',
alignItems:'center',
position:isFixed(hindex)?'sticky':'unset',
borderLeft:columnFixed<0&&isFixed(hindex)?'1px solid #f0f0f0':'unset',
zIndex:hindex<=columnFixed-1?9:'unset',
backgroundColor:'inherit',
overflow:'hidden'}">
v-if="header.format.type==='progress'&&!isNaN(parseFloat(content[header.key]))"
:percent="content[header.key].toFixed(2)" show-info round>
{{content[header.key]}}
{{content[header.key]}}
@click.native="getRow(content)">
合计
v-if="typeof header.format!=='undefined'&& header.format.type==='progress'&&!isNaN(parseFloat(renderTotalRow(header)))"
:percent="renderTotalRow(header)" :show-info="true" round>
{{ renderTotalRow(header)}}
排序字体图标需要缩小,在css文件中iconfont.css文件里面改字体图标样式即可:
.iconfont {
font-family: "iconfont" !important;
font-size: 12px !important;
transform: scale(0.7); // 图标缩小,根据需求自己定义缩小值,因浏览器默认字体是12px,设置即可小于12px
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}