update 流程详情-流程图
This commit is contained in:
@@ -0,0 +1,339 @@
|
|||||||
|
<template>
|
||||||
|
<div :id="domId"></div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import insertCss from 'insert-css'
|
||||||
|
import G6 from '@antv/g6'
|
||||||
|
import DeleteIcon from '../assets/image/iconDelete.svg'
|
||||||
|
|
||||||
|
// 流程图用到的属性
|
||||||
|
const ChartAttrs = {
|
||||||
|
nodeStrokeColor: '#739FC8', // 节点边框颜色
|
||||||
|
nodeFillColor: '#EEF4F8', // 节点背景颜色
|
||||||
|
nodeTextColor: '#227CCF', // 节点文字颜色
|
||||||
|
nodeWidth: 210, // 节点宽度
|
||||||
|
nodeHeight: 40, // 节点高度
|
||||||
|
ellipseLength: 12, // 文本显示最大长度
|
||||||
|
returnLineSpacing: 30, // 文本左右绕的加宽
|
||||||
|
edgeColor: '#86909c', // 线的颜色
|
||||||
|
edgeWidth: 1,
|
||||||
|
btnColor: '#1f1f1f', // 按钮颜色
|
||||||
|
btnSize: 20, // 按钮的宽高
|
||||||
|
btnPadding: 2 // 按钮边框和内部图标的距离
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加图标
|
||||||
|
const AddIcon = function EXPAND_ICON (x, y, r) {
|
||||||
|
return [['M', x + 2, y], ['L', x + 2 * r - 2, y], ['M', x + r, y - r + 2], ['L', x + r, y + r - 2]]
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理图的tooltip样式
|
||||||
|
insertCss(`
|
||||||
|
.g6-tooltip {
|
||||||
|
border-radius: 6px;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #fff;
|
||||||
|
background-color: #000;
|
||||||
|
padding: 2px 8px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
`)
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'FlowChart',
|
||||||
|
props: {
|
||||||
|
// 元素的id
|
||||||
|
domId: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
// 流程图用到的数据
|
||||||
|
chartData: {
|
||||||
|
type: Object,
|
||||||
|
required: false,
|
||||||
|
default: () => {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 是否仅查看
|
||||||
|
isViewOnly: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
isLoadEnd: false, // 页面是否加载完成
|
||||||
|
graph: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
chartData: {
|
||||||
|
handler () {
|
||||||
|
if (this.isLoadEnd) {
|
||||||
|
if (this.graph) {
|
||||||
|
this.graph.destroy()
|
||||||
|
this.graph = null
|
||||||
|
this.initChart()
|
||||||
|
} else {
|
||||||
|
this.initChart()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
deep: true,
|
||||||
|
immediate: true
|
||||||
|
},
|
||||||
|
isLoadEnd () {
|
||||||
|
if (this.isLoadEnd && Object.keys(this.chartData).length > 0) {
|
||||||
|
this.initChart()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted () {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.isLoadEnd = true
|
||||||
|
})
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
initChart () {
|
||||||
|
const canOperate = !this.isViewOnly
|
||||||
|
// 自定义节点
|
||||||
|
G6.registerNode('default-node', {
|
||||||
|
drawShape (cfg, group) {
|
||||||
|
const rect = group.addShape('rect', {
|
||||||
|
attrs: {
|
||||||
|
x: -(ChartAttrs.nodeWidth / 2),
|
||||||
|
y: -(ChartAttrs.nodeHeight / 2),
|
||||||
|
width: ChartAttrs.nodeWidth,
|
||||||
|
height: ChartAttrs.nodeHeight,
|
||||||
|
radius: ChartAttrs.nodeHeight / 2,
|
||||||
|
fill: ChartAttrs.nodeFillColor,
|
||||||
|
stroke: ChartAttrs.nodeStrokeColor
|
||||||
|
},
|
||||||
|
name: 'default-node-box'
|
||||||
|
})
|
||||||
|
// 处理文本显示及文本超长
|
||||||
|
if (cfg.name) {
|
||||||
|
const text = cfg.name.length > ChartAttrs.ellipseLength ? cfg.name.substring(0, ChartAttrs.ellipseLength) + '...' : cfg.name
|
||||||
|
group.addShape('text', {
|
||||||
|
attrs: {
|
||||||
|
text,
|
||||||
|
fill: ChartAttrs.nodeTextColor,
|
||||||
|
fontSize: 14,
|
||||||
|
textAlign: 'center',
|
||||||
|
textBaseline: 'middle',
|
||||||
|
fontWeight: 'bold'
|
||||||
|
},
|
||||||
|
name: 'default-node-text'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 可以添加,添加虽然在线上,但代码要写在自定义点里,不然获取不到节点id
|
||||||
|
if (cfg.isApprovalNode === 1 && canOperate) {
|
||||||
|
group.addShape('rect', {
|
||||||
|
attrs: {
|
||||||
|
x: -(ChartAttrs.btnSize / 2),
|
||||||
|
y: 1.5 * ChartAttrs.btnSize,
|
||||||
|
width: ChartAttrs.btnSize,
|
||||||
|
height: ChartAttrs.btnSize,
|
||||||
|
radius: 4,
|
||||||
|
symbol: AddIcon,
|
||||||
|
fill: 'white',
|
||||||
|
cursor: 'pointer',
|
||||||
|
stroke: ChartAttrs.btnColor,
|
||||||
|
lineWidth: 1
|
||||||
|
},
|
||||||
|
name: 'add-btn'
|
||||||
|
})
|
||||||
|
group.addShape('marker', {
|
||||||
|
attrs: {
|
||||||
|
x: -(ChartAttrs.btnSize / 2) + ChartAttrs.btnPadding,
|
||||||
|
y: 2 * ChartAttrs.btnSize,
|
||||||
|
r: (ChartAttrs.btnSize / 2) - ChartAttrs.btnPadding,
|
||||||
|
symbol: AddIcon,
|
||||||
|
stroke: ChartAttrs.btnColor,
|
||||||
|
fill: 'white',
|
||||||
|
cursor: 'pointer',
|
||||||
|
lineWidth: 1
|
||||||
|
},
|
||||||
|
name: 'add-btn-icon'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 可以删除
|
||||||
|
if (cfg.isCanDeleted === 1 && canOperate) {
|
||||||
|
group.addShape('rect', {
|
||||||
|
attrs: {
|
||||||
|
x: ChartAttrs.nodeWidth / 2 + ChartAttrs.btnSize / 2,
|
||||||
|
y: -ChartAttrs.btnSize / 2,
|
||||||
|
width: ChartAttrs.btnSize,
|
||||||
|
height: ChartAttrs.btnSize,
|
||||||
|
radius: 4,
|
||||||
|
symbol: AddIcon,
|
||||||
|
fill: 'white',
|
||||||
|
cursor: 'pointer',
|
||||||
|
stroke: ChartAttrs.btnColor
|
||||||
|
},
|
||||||
|
name: 'delete-btn'
|
||||||
|
})
|
||||||
|
group.addShape('image', {
|
||||||
|
attrs: {
|
||||||
|
x: ChartAttrs.nodeWidth / 2 + ChartAttrs.btnSize / 2 + ChartAttrs.btnPadding,
|
||||||
|
y: -ChartAttrs.btnSize / 2 + ChartAttrs.btnPadding,
|
||||||
|
img: DeleteIcon,
|
||||||
|
width: ChartAttrs.btnSize - ChartAttrs.btnPadding * 2,
|
||||||
|
height: ChartAttrs.btnSize - ChartAttrs.btnPadding * 2
|
||||||
|
},
|
||||||
|
name: 'delete-btn-icon'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return rect
|
||||||
|
},
|
||||||
|
// 设置锚点,上下中心
|
||||||
|
getAnchorPoints () {
|
||||||
|
return [
|
||||||
|
[0.5, 0],
|
||||||
|
[0.5, 1]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}, 'single-node')
|
||||||
|
|
||||||
|
// 自定义边
|
||||||
|
G6.registerEdge('default-edge', {
|
||||||
|
// 处理线条
|
||||||
|
draw (cfg, group) {
|
||||||
|
const startPoint = cfg.startPoint
|
||||||
|
const endPoint = cfg.endPoint
|
||||||
|
let path = []
|
||||||
|
// 如果起始点在终点的右下方
|
||||||
|
if (startPoint.y > endPoint.y && startPoint.x >= endPoint.x) {
|
||||||
|
path = [
|
||||||
|
['M', startPoint.x, startPoint.y],
|
||||||
|
['L', startPoint.x, startPoint.y + ChartAttrs.nodeHeight], // 从下面出来
|
||||||
|
['L', startPoint.x + ChartAttrs.nodeWidth / 2 + ChartAttrs.returnLineSpacing, startPoint.y + ChartAttrs.nodeHeight], // 右侧绕一下
|
||||||
|
['L', startPoint.x + ChartAttrs.nodeWidth / 2 + ChartAttrs.returnLineSpacing, endPoint.y - ChartAttrs.nodeHeight], // 右侧绕一下
|
||||||
|
['L', endPoint.x, endPoint.y - ChartAttrs.nodeHeight], // 到入点的上方
|
||||||
|
['L', endPoint.x, endPoint.y]
|
||||||
|
]
|
||||||
|
} else if (startPoint.y > endPoint.y && startPoint.x < endPoint.x) { // 起始点在终点的左下方
|
||||||
|
path = [
|
||||||
|
['M', startPoint.x, startPoint.y],
|
||||||
|
['L', startPoint.x, startPoint.y + ChartAttrs.nodeHeight], // 从下面出来
|
||||||
|
['L', startPoint.x - ChartAttrs.nodeWidth - ChartAttrs.returnLineSpacing, startPoint.y + ChartAttrs.nodeHeight], // 左侧绕一下
|
||||||
|
['L', startPoint.x - ChartAttrs.nodeWidth - ChartAttrs.returnLineSpacing, endPoint.y - ChartAttrs.nodeHeight], // 右侧绕一下
|
||||||
|
['L', endPoint.x, endPoint.y - ChartAttrs.nodeHeight], // 到入点的上方
|
||||||
|
['L', endPoint.x, endPoint.y]
|
||||||
|
]
|
||||||
|
} else {
|
||||||
|
path = [
|
||||||
|
['M', startPoint.x, startPoint.y],
|
||||||
|
['L', startPoint.x, (endPoint.y - startPoint.y) / 2 + startPoint.y],
|
||||||
|
['L', endPoint.x, (endPoint.y - startPoint.y) / 2 + startPoint.y],
|
||||||
|
['L', endPoint.x, endPoint.y]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
const shape = group.addShape('path', {
|
||||||
|
attrs: {
|
||||||
|
path,
|
||||||
|
stroke: ChartAttrs.edgeColor,
|
||||||
|
lineWidth: ChartAttrs.edgeWidth,
|
||||||
|
endArrow: true
|
||||||
|
},
|
||||||
|
className: 'edge-shape',
|
||||||
|
// must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item type
|
||||||
|
name: 'edge-shape'
|
||||||
|
})
|
||||||
|
// 处理label
|
||||||
|
if (cfg.label && cfg.label.length > 0) {
|
||||||
|
console.log(cfg.label)
|
||||||
|
group.addShape('text', {
|
||||||
|
attrs: {
|
||||||
|
text: cfg.label,
|
||||||
|
textAlign: 'center',
|
||||||
|
x: endPoint.x,
|
||||||
|
y: (endPoint.y - startPoint.y) / 2 + startPoint.y,
|
||||||
|
fill: 'black'
|
||||||
|
},
|
||||||
|
name: 'edge-label'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return shape
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
this.graph = new G6.Graph({
|
||||||
|
container: this.domId,
|
||||||
|
width: document.getElementById(this.domId).clientWidth,
|
||||||
|
height: document.getElementById(this.domId).clientHeight,
|
||||||
|
layout: {
|
||||||
|
type: 'dagre',
|
||||||
|
nodesep: 70,
|
||||||
|
ranksep: 30,
|
||||||
|
controlPoints: true,
|
||||||
|
preventOverlap: true // 防止节点重叠
|
||||||
|
},
|
||||||
|
defaultNode: {
|
||||||
|
type: 'default-node',
|
||||||
|
sortByCombo: true,
|
||||||
|
size: [210, 40]
|
||||||
|
},
|
||||||
|
defaultEdge: {
|
||||||
|
type: 'default-edge' // 在数据中已经指定 type,这里无需再次指定
|
||||||
|
},
|
||||||
|
modes: {
|
||||||
|
default: [
|
||||||
|
'drag-canvas',
|
||||||
|
'zoom-canvas',
|
||||||
|
{
|
||||||
|
type: 'tooltip',
|
||||||
|
formatText (model) {
|
||||||
|
return model.name
|
||||||
|
},
|
||||||
|
offset: 30
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
this.graph.data(this.chartData)
|
||||||
|
this.graph.render()
|
||||||
|
this.graph.on('node:click', event => {
|
||||||
|
this.handleNodeClick(event)
|
||||||
|
})
|
||||||
|
window.onresize = () => {
|
||||||
|
if (!this.graph || this.graph.get('destroyed')) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.graph.changeSize(document.getElementById(this.domId).clientWidth, document.getElementById(this.domId).clientHeight)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 节点点击事件
|
||||||
|
* @param target
|
||||||
|
* @param item
|
||||||
|
*/
|
||||||
|
handleNodeClick ({ target, item }) {
|
||||||
|
// 处理新增
|
||||||
|
if (target.cfg.name === 'add-btn' || target.cfg.name === 'add-btn-icon') {
|
||||||
|
this.handleAdd(item)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 处理删除
|
||||||
|
if (target.cfg.name === 'delete-btn' || target.cfg.name === 'delete-btn-icon') {
|
||||||
|
this.handleDelete(item)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleAdd (item) {
|
||||||
|
this.$emit('add', item)
|
||||||
|
},
|
||||||
|
handleDelete (item) {
|
||||||
|
this.$emit('delete', item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="less">
|
||||||
|
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
<template>
|
||||||
|
<j-modal
|
||||||
|
:title="$t('workCenter.processDetail.flowChart')"
|
||||||
|
:width="width"
|
||||||
|
:visible="visible"
|
||||||
|
switchFullscreen
|
||||||
|
:maskClosable="false"
|
||||||
|
:confirmLoading="confirmLoading"
|
||||||
|
:footer="null"
|
||||||
|
@cancel="close">
|
||||||
|
<a-spin :spinning="confirmLoading">
|
||||||
|
<flow-chart dom-id="flowChart" :chart-data="chartData" is-view-only />
|
||||||
|
</a-spin>
|
||||||
|
|
||||||
|
</j-modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import FlowChart from './FlowChart.vue'
|
||||||
|
import { getFlowNodeList } from '../api/workCenter.js'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'FlowChartModal',
|
||||||
|
components: { FlowChart },
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
width: 1000,
|
||||||
|
visible: false,
|
||||||
|
confirmLoading: false,
|
||||||
|
chartData: {},
|
||||||
|
processId: null // 流程id
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
open () {
|
||||||
|
this.visible = true
|
||||||
|
this.initChartData()
|
||||||
|
},
|
||||||
|
close () {
|
||||||
|
this.visible = false
|
||||||
|
},
|
||||||
|
initChartData () {
|
||||||
|
this.confirmLoading = true
|
||||||
|
getFlowNodeList({ modelId: this.processId }).then(res => {
|
||||||
|
if (res.success) {
|
||||||
|
this.chartData = Object.assign({}, res.result || {})
|
||||||
|
} else {
|
||||||
|
this.$message.warning(res.message)
|
||||||
|
}
|
||||||
|
}).finally(() => {
|
||||||
|
this.confirmLoading = false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="less">
|
||||||
|
#flowChart {
|
||||||
|
width: 100%;
|
||||||
|
height: calc(100vh - 200px - 55px - 48px);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -71,6 +71,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<flow-chart-modal ref="flowChartModal" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -82,6 +84,7 @@ import { ACCESS_TOKEN } from '../store/mutation-types.js'
|
|||||||
import { downloadFile, getFileAccessHttpUrl } from '../api/manage.js'
|
import { downloadFile, getFileAccessHttpUrl } from '../api/manage.js'
|
||||||
import { previewPdf } from '../utils/previewPdf.js'
|
import { previewPdf } from '../utils/previewPdf.js'
|
||||||
import { Base64 } from 'js-base64'
|
import { Base64 } from 'js-base64'
|
||||||
|
import FlowChartModal from './FlowChartModal.vue'
|
||||||
|
|
||||||
// 支持预览的文件后缀
|
// 支持预览的文件后缀
|
||||||
const CAN_PREVIEW_FILE_SUFFIX = ['jpg', 'jpeg', 'png', 'raw', 'pdf', 'docx', 'doc']
|
const CAN_PREVIEW_FILE_SUFFIX = ['jpg', 'jpeg', 'png', 'raw', 'pdf', 'docx', 'doc']
|
||||||
@@ -90,7 +93,7 @@ const FILE_TYPE_PDF = 'pdf'
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'ProcessDetailList',
|
name: 'ProcessDetailList',
|
||||||
components: { JTable },
|
components: { JTable, FlowChartModal },
|
||||||
mixins: [JeroListMixin],
|
mixins: [JeroListMixin],
|
||||||
props: {
|
props: {
|
||||||
// 需要有list属性,用于混入里的接口获取
|
// 需要有list属性,用于混入里的接口获取
|
||||||
@@ -131,7 +134,7 @@ export default {
|
|||||||
},
|
},
|
||||||
// 任务受理人
|
// 任务受理人
|
||||||
{
|
{
|
||||||
dataIndex: 'projectName',
|
dataIndex: 'projectName1',
|
||||||
title: this.$t('workCenter.processDetail.taskHandler'),
|
title: this.$t('workCenter.processDetail.taskHandler'),
|
||||||
width: 120
|
width: 120
|
||||||
},
|
},
|
||||||
@@ -143,7 +146,7 @@ export default {
|
|||||||
},
|
},
|
||||||
// 完成时间
|
// 完成时间
|
||||||
{
|
{
|
||||||
dataIndex: 'nameWorkNo',
|
dataIndex: 'nameWorkNo1',
|
||||||
title: this.$t('workCenter.processDetail.completionTime'),
|
title: this.$t('workCenter.processDetail.completionTime'),
|
||||||
width: 150
|
width: 150
|
||||||
},
|
},
|
||||||
@@ -192,6 +195,8 @@ export default {
|
|||||||
* 跳转流程图页面
|
* 跳转流程图页面
|
||||||
*/
|
*/
|
||||||
viewFlowChart () {
|
viewFlowChart () {
|
||||||
|
this.$refs.flowChartModal.processId = '62507'
|
||||||
|
this.$refs.flowChartModal.open()
|
||||||
},
|
},
|
||||||
handlePreview (file) {
|
handlePreview (file) {
|
||||||
if (!file || !file.url) {
|
if (!file || !file.url) {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<internal-detail-page :title="$route.meta.title" :content-padding="0" :loading="loading">
|
<internal-detail-page :title="$route.meta.title" :content-padding="0" :loading="loading">
|
||||||
<div class="detail-page-scroll-content">
|
<div class="detail-page-scroll-content">
|
||||||
<!--流程图dom-->
|
<!--流程图dom-->
|
||||||
<div id="flowChart"></div>
|
<flow-chart dom-id="flowChart" :chart-data="chartData" @add="handleAdd" @delete="handleDelete" />
|
||||||
</div>
|
</div>
|
||||||
<div class="detail-page-bottom-operate-box">
|
<div class="detail-page-bottom-operate-box">
|
||||||
<!--取消-->
|
<!--取消-->
|
||||||
@@ -17,48 +17,13 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import InternalDetailPage from '../../../components/InternalDetailPage.vue'
|
import InternalDetailPage from '../../../components/InternalDetailPage.vue'
|
||||||
import G6 from '@antv/g6'
|
|
||||||
import { getFlowNodeList, deleteFlowNode } from '../../../api/workCenter.js'
|
import { getFlowNodeList, deleteFlowNode } from '../../../api/workCenter.js'
|
||||||
import insertCss from 'insert-css'
|
|
||||||
import FlowNodeModal from './modules/FlowNodeModal.vue'
|
import FlowNodeModal from './modules/FlowNodeModal.vue'
|
||||||
import DeleteIcon from '../../../assets/image/iconDelete.svg'
|
import FlowChart from '../../../components/FlowChart.vue'
|
||||||
|
|
||||||
// 流程图用到的属性
|
|
||||||
const ChartAttrs = {
|
|
||||||
nodeStrokeColor: '#739FC8', // 节点边框颜色
|
|
||||||
nodeFillColor: '#EEF4F8', // 节点背景颜色
|
|
||||||
nodeTextColor: '#227CCF', // 节点文字颜色
|
|
||||||
nodeWidth: 210, // 节点宽度
|
|
||||||
nodeHeight: 40, // 节点高度
|
|
||||||
ellipseLength: 12, // 文本显示最大长度
|
|
||||||
returnLineSpacing: 30, // 文本左右绕的加宽
|
|
||||||
edgeColor: '#86909c', // 线的颜色
|
|
||||||
edgeWidth: 1,
|
|
||||||
btnColor: '#1f1f1f', // 按钮颜色
|
|
||||||
btnSize: 20, // 按钮的宽高
|
|
||||||
btnPadding: 2 // 按钮边框和内部图标的距离
|
|
||||||
}
|
|
||||||
|
|
||||||
// 添加图标
|
|
||||||
const AddIcon = function EXPAND_ICON (x, y, r) {
|
|
||||||
return [['M', x + 2, y], ['L', x + 2 * r - 2, y], ['M', x + r, y - r + 2], ['L', x + r, y + r - 2]]
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理图的tooltip样式
|
|
||||||
insertCss(`
|
|
||||||
.g6-tooltip {
|
|
||||||
border-radius: 6px;
|
|
||||||
font-size: 12px;
|
|
||||||
color: #fff;
|
|
||||||
background-color: #000;
|
|
||||||
padding: 2px 8px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
`)
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'EditFlowNode',
|
name: 'EditFlowNode',
|
||||||
components: { InternalDetailPage, FlowNodeModal },
|
components: { InternalDetailPage, FlowNodeModal, FlowChart },
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
loading: false,
|
loading: false,
|
||||||
@@ -79,17 +44,6 @@ export default {
|
|||||||
getFlowNodeList({ modelId: this.$route.query.id }).then(res => {
|
getFlowNodeList({ modelId: this.$route.query.id }).then(res => {
|
||||||
if (res.success) {
|
if (res.success) {
|
||||||
this.chartData = Object.assign({}, res.result || {})
|
this.chartData = Object.assign({}, res.result || {})
|
||||||
if (!this.graph) {
|
|
||||||
this.$nextTick(() => {
|
|
||||||
this.initFlowChart()
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
this.graph.destroy()
|
|
||||||
this.graph = null
|
|
||||||
this.$nextTick(() => {
|
|
||||||
this.initFlowChart()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
this.$message.warning(res.message)
|
this.$message.warning(res.message)
|
||||||
}
|
}
|
||||||
@@ -97,225 +51,6 @@ export default {
|
|||||||
this.loading = false
|
this.loading = false
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
/**
|
|
||||||
* 初始化流程图
|
|
||||||
*
|
|
||||||
* #86909c
|
|
||||||
*/
|
|
||||||
initFlowChart () {
|
|
||||||
// 自定义节点
|
|
||||||
G6.registerNode('default-node', {
|
|
||||||
drawShape (cfg, group) {
|
|
||||||
const rect = group.addShape('rect', {
|
|
||||||
attrs: {
|
|
||||||
x: -(ChartAttrs.nodeWidth / 2),
|
|
||||||
y: -(ChartAttrs.nodeHeight / 2),
|
|
||||||
width: ChartAttrs.nodeWidth,
|
|
||||||
height: ChartAttrs.nodeHeight,
|
|
||||||
radius: ChartAttrs.nodeHeight / 2,
|
|
||||||
fill: ChartAttrs.nodeFillColor,
|
|
||||||
stroke: ChartAttrs.nodeStrokeColor
|
|
||||||
},
|
|
||||||
name: 'default-node-box'
|
|
||||||
})
|
|
||||||
// 处理文本显示及文本超长
|
|
||||||
if (cfg.name) {
|
|
||||||
const text = cfg.name.length > ChartAttrs.ellipseLength ? cfg.name.substring(0, ChartAttrs.ellipseLength) + '...' : cfg.name
|
|
||||||
group.addShape('text', {
|
|
||||||
attrs: {
|
|
||||||
text,
|
|
||||||
fill: ChartAttrs.nodeTextColor,
|
|
||||||
fontSize: 14,
|
|
||||||
textAlign: 'center',
|
|
||||||
textBaseline: 'middle',
|
|
||||||
fontWeight: 'bold'
|
|
||||||
},
|
|
||||||
name: 'default-node-text'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
// 可以添加,添加虽然在线上,但代码要写在自定义点里,不然获取不到节点id
|
|
||||||
if (cfg.isApprovalNode === 1) {
|
|
||||||
group.addShape('rect', {
|
|
||||||
attrs: {
|
|
||||||
x: -(ChartAttrs.btnSize / 2),
|
|
||||||
y: 1.5 * ChartAttrs.btnSize,
|
|
||||||
width: ChartAttrs.btnSize,
|
|
||||||
height: ChartAttrs.btnSize,
|
|
||||||
radius: 4,
|
|
||||||
symbol: AddIcon,
|
|
||||||
fill: 'white',
|
|
||||||
cursor: 'pointer',
|
|
||||||
stroke: ChartAttrs.btnColor,
|
|
||||||
lineWidth: 1
|
|
||||||
},
|
|
||||||
name: 'add-btn'
|
|
||||||
})
|
|
||||||
group.addShape('marker', {
|
|
||||||
attrs: {
|
|
||||||
x: -(ChartAttrs.btnSize / 2) + ChartAttrs.btnPadding,
|
|
||||||
y: 2 * ChartAttrs.btnSize,
|
|
||||||
r: (ChartAttrs.btnSize / 2) - ChartAttrs.btnPadding,
|
|
||||||
symbol: AddIcon,
|
|
||||||
stroke: ChartAttrs.btnColor,
|
|
||||||
fill: 'white',
|
|
||||||
cursor: 'pointer',
|
|
||||||
lineWidth: 1
|
|
||||||
},
|
|
||||||
name: 'add-btn-icon'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
// 可以删除
|
|
||||||
if (cfg.isCanDeleted === 1) {
|
|
||||||
group.addShape('rect', {
|
|
||||||
attrs: {
|
|
||||||
x: ChartAttrs.nodeWidth / 2 + ChartAttrs.btnSize / 2,
|
|
||||||
y: -ChartAttrs.btnSize / 2,
|
|
||||||
width: ChartAttrs.btnSize,
|
|
||||||
height: ChartAttrs.btnSize,
|
|
||||||
radius: 4,
|
|
||||||
symbol: AddIcon,
|
|
||||||
fill: 'white',
|
|
||||||
cursor: 'pointer',
|
|
||||||
stroke: ChartAttrs.btnColor
|
|
||||||
},
|
|
||||||
name: 'delete-btn'
|
|
||||||
})
|
|
||||||
group.addShape('image', {
|
|
||||||
attrs: {
|
|
||||||
x: ChartAttrs.nodeWidth / 2 + ChartAttrs.btnSize / 2 + ChartAttrs.btnPadding,
|
|
||||||
y: -ChartAttrs.btnSize / 2 + ChartAttrs.btnPadding,
|
|
||||||
img: DeleteIcon,
|
|
||||||
width: ChartAttrs.btnSize - ChartAttrs.btnPadding * 2,
|
|
||||||
height: ChartAttrs.btnSize - ChartAttrs.btnPadding * 2
|
|
||||||
},
|
|
||||||
name: 'delete-btn-icon'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return rect
|
|
||||||
},
|
|
||||||
// 设置锚点,上下中心
|
|
||||||
getAnchorPoints () {
|
|
||||||
return [
|
|
||||||
[0.5, 0],
|
|
||||||
[0.5, 1]
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}, 'single-node')
|
|
||||||
|
|
||||||
// 自定义边
|
|
||||||
G6.registerEdge('default-edge', {
|
|
||||||
// 处理线条
|
|
||||||
draw (cfg, group) {
|
|
||||||
const startPoint = cfg.startPoint
|
|
||||||
const endPoint = cfg.endPoint
|
|
||||||
let path = []
|
|
||||||
// 如果起始点在终点的右下方
|
|
||||||
if (startPoint.y > endPoint.y && startPoint.x >= endPoint.x) {
|
|
||||||
path = [
|
|
||||||
['M', startPoint.x, startPoint.y],
|
|
||||||
['L', startPoint.x, startPoint.y + ChartAttrs.nodeHeight], // 从下面出来
|
|
||||||
['L', startPoint.x + ChartAttrs.nodeWidth / 2 + ChartAttrs.returnLineSpacing, startPoint.y + ChartAttrs.nodeHeight], // 右侧绕一下
|
|
||||||
['L', startPoint.x + ChartAttrs.nodeWidth / 2 + ChartAttrs.returnLineSpacing, endPoint.y - ChartAttrs.nodeHeight], // 右侧绕一下
|
|
||||||
['L', endPoint.x, endPoint.y - ChartAttrs.nodeHeight], // 到入点的上方
|
|
||||||
['L', endPoint.x, endPoint.y]
|
|
||||||
]
|
|
||||||
} else if (startPoint.y > endPoint.y && startPoint.x < endPoint.x) { // 起始点在终点的左下方
|
|
||||||
path = [
|
|
||||||
['M', startPoint.x, startPoint.y],
|
|
||||||
['L', startPoint.x, startPoint.y + ChartAttrs.nodeHeight], // 从下面出来
|
|
||||||
['L', startPoint.x - ChartAttrs.nodeWidth - ChartAttrs.returnLineSpacing, startPoint.y + ChartAttrs.nodeHeight], // 左侧绕一下
|
|
||||||
['L', startPoint.x - ChartAttrs.nodeWidth - ChartAttrs.returnLineSpacing, endPoint.y - ChartAttrs.nodeHeight], // 右侧绕一下
|
|
||||||
['L', endPoint.x, endPoint.y - ChartAttrs.nodeHeight], // 到入点的上方
|
|
||||||
['L', endPoint.x, endPoint.y]
|
|
||||||
]
|
|
||||||
} else {
|
|
||||||
path = [
|
|
||||||
['M', startPoint.x, startPoint.y],
|
|
||||||
['L', startPoint.x, (endPoint.y - startPoint.y) / 2 + startPoint.y],
|
|
||||||
['L', endPoint.x, (endPoint.y - startPoint.y) / 2 + startPoint.y],
|
|
||||||
['L', endPoint.x, endPoint.y]
|
|
||||||
]
|
|
||||||
}
|
|
||||||
const shape = group.addShape('path', {
|
|
||||||
attrs: {
|
|
||||||
path,
|
|
||||||
stroke: ChartAttrs.edgeColor,
|
|
||||||
lineWidth: ChartAttrs.edgeWidth,
|
|
||||||
endArrow: true
|
|
||||||
},
|
|
||||||
className: 'edge-shape',
|
|
||||||
// must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item type
|
|
||||||
name: 'edge-shape'
|
|
||||||
})
|
|
||||||
// 处理label
|
|
||||||
if (cfg.label && cfg.label.length > 0) {
|
|
||||||
console.log(cfg.label)
|
|
||||||
group.addShape('text', {
|
|
||||||
attrs: {
|
|
||||||
text: cfg.label,
|
|
||||||
textAlign: 'center',
|
|
||||||
x: endPoint.x,
|
|
||||||
y: (endPoint.y - startPoint.y) / 2 + startPoint.y,
|
|
||||||
fill: 'black'
|
|
||||||
},
|
|
||||||
name: 'edge-label'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return shape
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
this.graph = new G6.Graph({
|
|
||||||
container: 'flowChart',
|
|
||||||
width: document.getElementById('flowChart').clientWidth,
|
|
||||||
height: document.getElementById('flowChart').clientHeight,
|
|
||||||
layout: {
|
|
||||||
type: 'dagre',
|
|
||||||
nodesep: 70,
|
|
||||||
ranksep: 30,
|
|
||||||
controlPoints: true,
|
|
||||||
preventOverlap: true // 防止节点重叠
|
|
||||||
},
|
|
||||||
defaultNode: {
|
|
||||||
type: 'default-node',
|
|
||||||
sortByCombo: true,
|
|
||||||
size: [210, 40]
|
|
||||||
},
|
|
||||||
defaultEdge: {
|
|
||||||
type: 'default-edge' // 在数据中已经指定 type,这里无需再次指定
|
|
||||||
},
|
|
||||||
modes: {
|
|
||||||
default: [
|
|
||||||
'drag-canvas',
|
|
||||||
'zoom-canvas',
|
|
||||||
{
|
|
||||||
type: 'tooltip',
|
|
||||||
formatText (model) {
|
|
||||||
return model.name
|
|
||||||
},
|
|
||||||
offset: 30
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
this.graph.data(this.chartData)
|
|
||||||
this.graph.render()
|
|
||||||
this.graph.on('node:click', event => {
|
|
||||||
this.handleNodeClick(event)
|
|
||||||
})
|
|
||||||
window.onresize = () => {
|
|
||||||
if (!this.graph || this.graph.get('destroyed')) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
this.graph.changeSize(document.getElementById('flowChart').clientWidth, document.getElementById('flowChart').clientHeight)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
handleNodeClick ({ target, item }) {
|
|
||||||
if (target.cfg.name === 'add-btn' || target.cfg.name === 'add-btn-icon') {
|
|
||||||
this.handleAdd(item)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
handleAdd (item) {
|
handleAdd (item) {
|
||||||
this.$refs.modalForm.title = this.$t('newlyAdded')
|
this.$refs.modalForm.title = this.$t('newlyAdded')
|
||||||
this.$refs.modalForm.add({
|
this.$refs.modalForm.add({
|
||||||
|
|||||||
@@ -344,7 +344,7 @@ export default {
|
|||||||
sourceOptions: [],
|
sourceOptions: [],
|
||||||
approvalInfoForm: this.$form.createForm(this),
|
approvalInfoForm: this.$form.createForm(this),
|
||||||
loading: false,
|
loading: false,
|
||||||
switchValue: 'user',
|
switchValue: 'base',
|
||||||
personalInfoData: [ // 人员信息的数据
|
personalInfoData: [ // 人员信息的数据
|
||||||
{
|
{
|
||||||
id: 1,
|
id: 1,
|
||||||
|
|||||||
Reference in New Issue
Block a user