要求する:
1:フローチャートを動的に生成する
2:やること、すでにやったこと(または他の同様のニーズ)に応じて異なる背景色を区別する
3:マウスオーバーして対応する情報を表示します
4:生成されたフローチャートは、各ステップに複数の受信者がいる可能性があるため、階層関係にあります。たとえば、プロセスの最初のステップは1つのX軸上にあり、2番目のステップは同じX軸上にあるというように、ヒエラルキー感があり、散らかっていないようです
成し遂げる
単純なヒストグラムや円グラフなどの他のechartsチャートを使用し、それらの間のAPIを知っていることが前提です。それが最初の連絡先である場合は、公式アドレスhttps://echarts.apache.org/に移動してください。 zh /index.html。
この例では、echarts関係図、x軸とy軸のレイアウトを使用します
1:フローチャートを動的に生成する
これは扱いが簡単です。実際、これはシリーズのデータ属性にすぎません。echarts図を自分で見てください。
2:やることとすでに行われたことに従って異なる背景色を区別する
公式ドキュメントは、シリーズのシンボル属性であるデフォルトのグローバルカラーです。
ここでは、それをデータにカプセル化し、公式Webサイトにアクセスして簡単な実装を行うことができるため、さまざまな背景画像をデータでパーソナライズできます。
3:マウスオーバーして対応する情報を表示します
単純なテキストは、次のようなフォーマッタ関数を使用して、データのフィールドとともに直接表示できます。
tooltip: {
formatter: function(x) {
return x.data.toolText;
}
}
ただし、テキストのスプライシングが多い場合は使いにくいです。上記のことから、toolTextは依然としてデータの属性であるため、アイデアは明確です。toolTextなどのデータにさらに多くのテキストをカプセル化してから、それをechartするフィールドを組み立てる
4:生成されたフローチャートには階層関係があります
バックグラウンドデータの実装では、上記の分析を考慮して、データベースにordernumフィールドを設定します。最初のステップは1で、ordernumは次のステップごとに1ずつ増加し、x軸とy軸の座標はordernumと量に従って動的に決定されます。データ、およびその他のデータの関係図apiと同様
対応するフロントエンドコード:
親ページのロジック
viewProcessはフォアグラウンドクリックイベントです。完全なフローチャートは、プロセスのメインIDに従って取得されます。現在、水平方向の単一プロセスの長さは15ステップに設定されています。必要に応じてパーソナライズできます。適切な方法は見つかりませんでした。これまでのところ、15件の注文のみが死んで書かれています
<template>
<div>
<!-- 其他隐藏,点击事件根据需求自己添加 -->
<!-- 流程图公共弹窗 -->
<relationBar v-bind="relationBarOptions" @close="clickCloseRelationBar"></relationBar>
</div>
</template>
<script>
import relationBar from "./relationBar.vue";
export default {
name: "xxx",
props: {
title: {
type: String,
default: ""
},
show: {
type: Boolean,
default: false
},
},
data() {
return {
//======流程图属性 ======START
relationBarOptions: {
data: [],
showFlag: false
},
order2: 1,
order3: 1,
order4: 1,
order5: 1,
order6: 1,
order7: 1,
order8: 1,
order9: 1,
order10: 1,
order11: 1,
order12: 1,
order13: 1,
order14: 1,
order15: 1,
dataInit: []
//======流程图属性 ======END
};
},
components: {
relationBar
},
watch: {
},
mounted() {
},
methods: {
//查看流程图
viewProcess() {
this.order1 = 1;
this.order2 = 1;
this.order3 = 1;
this.order4 = 1;
this.order5 = 1;
this.order6 = 1;
this.order7 = 1;
this.order8 = 1;
this.order9 = 1;
this.order10 = 1;
this.order11 = 1;
this.order12 = 1;
this.order13 = 1;
this.order14 = 1;
this.order15 = 1;
//echarts数据
let echartsData = [];
//echarts关系数据
let echartslinks = [];
let dataAfterComBine = [];
//根据insid获取数据
let params = {};
params.insId = this.editForm.id;
params.mark = "2";
this.$api
.getProcessListByInsId({ params })
.then(res => {
if (res.code == 0) {
let dataInitTemp = res.result;
//解决名字重复问题,自己看官网API就知道原因了
dataInitTemp.forEach(data => {
let theSameNUm = 0;
let deptname = data.deptname;
res.result.forEach(data2 => {
if (data2.deptname == deptname) {
theSameNUm++;
}
if (theSameNUm == 2) {
data2.deptname = data2.deptname + " ";
}
if (theSameNUm == 3) {
data2.deptname = data2.deptname + " ";
}
});
});
this.dataInit = res.result;
}
})
.then(res => {
//################################计算位移 START###########################################
//获取最大步长
let maxOrderNum = 0;
this.dataInit.forEach(d => {
if (Number(d.ordernum) > maxOrderNum) {
maxOrderNum = Number(d.ordernum);
}
});
//初始值 x步长:1*200 y:1*100
let addStepX = 1;
let addStepY = 1;
//判断 最大ordernum 根据ordernum和数据量进行X,Y判断,为了方便 使用*3计算
for (let i = 3; i < 10; i++) {
if (maxOrderNum >= i) {
if (this.dataInit.length > i * 3) {
addStepX = maxOrderNum - 1;
addStepY = maxOrderNum - 1;
}
}
}
//添加数据
this.dataInit.forEach(d => {
let ordernumOfx = Number(d.ordernum) * 300 * Number(addStepX);
let ordernumOfy = Number(d.ordernum) * 100 * Number(addStepY);
//公共属性,开始节点特殊化
let commnDataInit = {
toolText:
d.deptname +
"</br>" +
"新增人员: " +
d.reciveuser +
"</br>" +
"新增时间: " +
d.recivedate +
"</br>" +
"办理人员: " +
d.opeuser +
"</br>" +
"办理时间: " +
d.opedate,
user: d.opeuser,
date: d.opedate,
name: d.deptname,
x: ordernumOfx,
text: d.currentcontent,
//背景图可以用网上的,这里是用nginx代理的服务器图片,根据自己需求来
symbol:
"image://http://XXXX.XXXX.XXXX:8096/XXX/processImg/redDone.jpg"
};
//公共属性,流程节点属性
let commnData = {
toolText:
d.deptname +
"</br>" +
"签收人员: " +
d.reciveuser +
"</br>" +
"签收时间: " +
d.recivedate +
"</br>" +
"办理人员: " +
d.opeuser +
"</br>" +
"办理时间: " +
d.opedate +
"</br>" +
"意 见: " +
d.currentcontent +
"</br>",
user: d.opeuser,
date: d.opedate,
name: d.deptname,
x: ordernumOfx,
text: d.currentcontent
};
if (d.ordernum == "1") {
echartsData.push({
...commnDataInit,
y: 0
});
} else {
this.setEchartsData(
echartsData,
d,
ordernumOfx,
ordernumOfy,
commnData
);
}
let databeforeComBine = {
id: d.id,
name: d.deptname,
childrens: []
};
dataAfterComBine.push(databeforeComBine);
this.comBineLinks(d.id, databeforeComBine, this.dataInit);
});
dataAfterComBine.forEach(e => {
e.childrens.forEach(element => {
echartslinks.push({
source: e.name,
target: element
});
});
});
this.relationBarOptions.data = echartsData;
this.relationBarOptions.links = echartslinks;
this.relationBarOptions.showFlag = true;
});
},
setEchartsData(echartsData, d, ordernumOfx, ordernumOfy, commnData) {
if (d.status == "0") {
commnData.symbol =
"image://http://XXXX.XXXX.XXXX:8096/XXX/processImg/processImg/grennTodo.jpg";
} else {
commnData.symbol =
"image://http://XXXX.XXXX.XXXX:8096/XXX/processImg/processImg/redDone.jpg";
}
if (d.ordernum == "2") {
echartsData.push({
...commnData,
y: this.order2 == 1 ? 0 : this.order2 * ordernumOfy
});
this.order2++;
}
if (d.ordernum == "3") {
echartsData.push({
...commnData,
y: this.order3 == 1 ? 0 : this.order3 * ordernumOfy
});
this.order3++;
}
if (d.ordernum == "4") {
echartsData.push({
...commnData,
y: this.order4 == 1 ? 0 : this.order4 * ordernumOfy
});
this.order4++;
}
if (d.ordernum == "5") {
echartsData.push({
...commnData,
y: this.order5 == 1 ? 0 : this.order5 * ordernumOfy
});
this.order5++;
}
if (d.ordernum == "6") {
echartsData.push({
...commnData,
y: this.order6 == 1 ? 0 : this.order6 * ordernumOfy
});
this.order6++;
}
if (d.ordernum == "7") {
echartsData.push({
...commnData,
y: this.order7 == 1 ? 0 : this.order7 * ordernumOfy
});
this.order7++;
}
if (d.ordernum == "8") {
echartsData.push({
...commnData,
y: this.order8 == 1 ? 0 : this.order8 * ordernumOfy
});
this.order8++;
}
if (d.ordernum == "9") {
echartsData.push({
...commnData,
y: this.order9 == 1 ? 0 : this.order9 * ordernumOfy
});
this.order9++;
}
if (d.ordernum == "10") {
echartsData.push({
...commnData,
y: this.order10 == 1 ? 0 : this.order10 * ordernumOfy
});
this.order10++;
}
if (d.ordernum == "11") {
echartsData.push({
...commnData,
y: this.order11 == 1 ? 0 : this.order11 * ordernumOfy
});
this.order11++;
}
if (d.ordernum == "12") {
echartsData.push({
...commnData,
y: this.order12 == 1 ? 0 : this.order12 * ordernumOfy
});
this.order12++;
}
if (d.ordernum == "13") {
echartsData.push({
...commnData,
y: this.order13 == 1 ? 0 : this.order13 * ordernumOfy
});
this.order13++;
}
if (d.ordernum == "14") {
echartsData.push({
...commnData,
y: this.order14 == 1 ? 0 : this.order14 * ordernumOfy
});
this.order14++;
}
if (d.ordernum == "15") {
echartsData.push({
...commnData,
y: this.order15 == 1 ? 0 : this.order15 * ordernumOfy
});
this.order15++;
}
},
comBineLinks(id, databeforeComBine, data) {
data.forEach(d => {
if (d.parentId == id) {
databeforeComBine.childrens.push(d.deptname);
}
});
},
processTypeFlt(row) {
//0下发1请示2反馈3退回4结束
switch (row.processType) {
case "0":
if (row.ordernum == "1") {
return "下发";
} else {
return "流转";
}
break;
case "1":
return "请示";
break;
case "2":
return "回报";
break;
break;
case "4":
return "结束";
break;
default:
if (row.iscopy == "0") {
if (row.ordernum == "1") {
return "新增";
} else {
return "签收";
}
} else {
return "接收";
}
}
}
//################################计算位移 END###########################################
},
filters: {
}
};
</script>
<style lang="scss">
</style>
サブページ(echartsコンポーネント):
<template>
<el-dialog :visible="show" @close="clickClose()" append-to-body width="60%">
<template slot="title">
<span style="width: calc(100% - 60px);display: inline-block;" class="single-line">
<slot name="title">{
{dialogtitle}}</slot>
</span>
</template>
<div class="relationBar">
<div class="relationBarDiv" ref="relationEcharts"></div>
</div>
<span slot="footer" class="dialog-footer">
<el-button>关 闭</el-button>
</span>
</el-dialog>
</template>
<script>
var option = {
title: {
text: "",
x: "center",
textStyle: {
fontWeight: "normal" //标题颜色
}
},
//个性化划过事件
tooltip: {},
series: [
{
// symbol:"image://data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7",
// symbol: "rect", //circle圆形 rect矩形
type: "graph", //关系图
layout: "none", // 图的布局。[ default: 'none' ] 'none' 不采用任何布局,使用节点中提供的 x, y 作为节点的位置。 'circular' 采用环形布局;'force' 采用力引导布局.
symbolSize: 50,
roam: true,
label: {
show: true
},
edgeSymbol: ["circle", "arrow"],
edgeSymbolSize: [4, 10],
edgeLabel: {
fontSize: 20
},
//color:'#A6FFA6',
data: [],
links: [],
lineStyle: {
opacity: 0.9,
width: 2,
curveness: 0,
//color: '#000', // 线的颜色[ default: '#aaa' ]
// width: 1, // 线宽[ default: 1 ]
// type: 'solid', // 线的类型[ default: solid ] 'dashed' 'dotted'
// opacity: 0.5, // 图形透明度。支持从 0 到 1 的数字,为 0 时不绘制该图形。[ default: 0.5 ]
// curveness: 0 // 边的曲度,支持从 0 到 1 的值,值越大曲度越大。[ default: 0 ]
}
}
]
};
export default {
name: "relationBar",
props: {
data: {
type: Array,
default: () => {
[];
}
},
links: {
type: Array,
default: () => {
[];
}
},
title: {
type: String,
default: ""
},
showFlag: {
type: Boolean,
default: false
}
},
data() {
return {
dialogtitle: "流程关系图",
show: false
};
},
created() {},
watch: {
showFlag: {
handler(n, o) {
this.show = n;
if (n) {
this.initEcharts();
}
},
immediate: true
}
},
mounted() {
//this.initEcharts();
},
methods: {
clickClose() {
this.$emit("close");
},
setOption(data) {
let op = JSON.parse(JSON.stringify(option));
op.series[0].data = this.data;
op.series[0].links = this.links;
op.tooltip = {
formatter: function(x) {
return x.data.toolText;
}
};
return op;
},
initEcharts() {
this.$nextTick(() => {
let ctx = this;
let myChart = ctx.$echarts.init(ctx.$refs.relationEcharts);
myChart.setOption(ctx.setOption(ctx.data));
ctx.$refs.relationEcharts.style.width = "100%";
});
}
}
};
</script>
<style lang="scss">
.relationBar {
width: 100%;
height: 700px;
border: #e3e3e3 1px solid;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12), 0 0 6px rgba(0, 0, 0, 0.04);
overflow: scroll;
.relationBarDiv {
width: 100%;
height: 100%;
min-height: 700px;
min-width: 250px;
}
}
</style>
最終的な効果は現在3番目のステップであり、ステップ数が増加し、それに応じてページが変更されます。赤い画像は完了を表し、緑色の画像はやることを表し、プロセスポップアップウィンドウには処理に関するコメントがあります。