Merge remote-tracking branch 'origin/master'

master
chaiyapeng 2024-08-27 09:33:37 +08:00
commit eac3e79c1c
45 changed files with 17962 additions and 65 deletions

View File

@ -40,24 +40,27 @@
"axios": "0.24.0", "axios": "0.24.0",
"clipboard": "2.0.8", "clipboard": "2.0.8",
"core-js": "3.25.3", "core-js": "3.25.3",
"echarts": "^5.5.1", "echarts": "5.4.0",
"element-ui": "2.15.14", "element-ui": "2.9.1",
"file-saver": "2.0.5", "file-saver": "2.0.5",
"fuse.js": "6.4.3", "fuse.js": "6.4.3",
"highlight.js": "9.18.5", "highlight.js": "9.18.5",
"js-beautify": "1.13.0", "js-beautify": "1.13.0",
"js-cookie": "3.0.1", "js-cookie": "3.0.1",
"jsencrypt": "3.0.0-rc.1", "jsencrypt": "3.0.0-rc.1",
"lodash": "4.17.15",
"nprogress": "0.2.0", "nprogress": "0.2.0",
"quill": "1.3.7", "quill": "1.3.7",
"screenfull": "5.0.2", "screenfull": "5.0.2",
"sortablejs": "1.10.2", "sortablejs": "1.10.2",
"vue": "2.6.12", "vue": "2.6.12",
"vue-click-outside": "^1.1.0",
"vue-codemirror": "^4.0.6",
"vue-count-to": "1.0.13", "vue-count-to": "1.0.13",
"vue-cropper": "0.5.5", "vue-cropper": "0.5.5",
"vue-meta": "2.4.0", "vue-meta": "2.4.0",
"vue-router": "3.4.9", "vue-router": "3.4.9",
"vuedraggable": "2.24.3", "vuedraggable": "2.23.0",
"vuex": "3.6.0" "vuex": "3.6.0"
}, },
"devDependencies": { "devDependencies": {
@ -71,6 +74,8 @@
"connect": "3.6.6", "connect": "3.6.6",
"eslint": "7.15.0", "eslint": "7.15.0",
"eslint-plugin-vue": "7.2.0", "eslint-plugin-vue": "7.2.0",
"less": "^4.2.0",
"less-loader": "^12.2.0",
"lint-staged": "10.5.3", "lint-staged": "10.5.3",
"runjs": "4.4.2", "runjs": "4.4.2",
"sass": "1.32.13", "sass": "1.32.13",

View File

@ -36,18 +36,27 @@ export function deleteByTaskId(id) {
} }
//获得所有数据结构信息 //获得所有数据结构信息
export function taskInputList() { export function tableInfoList() {
return request({ return request({
url: "/task/taskInput/list", url: "/task/tableInfo/list",
method: "GET", method: "GET",
}) })
} }
//获得所有数据结构信息 //获得所有数据结构信息
export function findByInputId(id) { export function findByTableId(id) {
return request({ return request({
url: "/task/findByInputId/"+id, url: "/task/tableInfo/findByTableId?id="+id,
method: "POST", method: "POST",
params:id
})
}
//获得所有数据结构信息
export function findStructureList(tableId) {
return request({
url: "/task/structure/findStructureList?tableId="+tableId,
method: "GET"
}) })
} }

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 201 201"><defs><style>.cls-1{opacity:0;}.cls-2,.cls-3{fill:none;stroke:#092370;stroke-miterlimit:10;}.cls-3{stroke-width:0.83px;}.cls-4{fill:#c5a9f1;}.cls-5{fill:#a375e9;}</style></defs><title>10大数据服务</title><g id="图层_2" data-name="图层 2"><g id="图层_1-2" data-name="图层 1"><g class="cls-1"><path class="cls-2" d="M100.5.5h0a100,100,0,0,1,100,100h0a100,100,0,0,1-100,100h0a100,100,0,0,1-100-100h0A100,100,0,0,1,100.5.5Z"/><rect class="cls-2" x="33.83" y="33.83" width="133.33" height="133.33"/><rect class="cls-3" x="44.93" y="44.93" width="111.13" height="111.13"/></g><path class="cls-4" d="M149.93,44.94H67.61a4.41,4.41,0,0,0,0,8.81h78v78.78a4.36,4.36,0,1,0,8.72,0V49.34A4.34,4.34,0,0,0,149.93,44.94Z"/><path class="cls-5" d="M133.57,64.06H51.07a4.34,4.34,0,0,0-4.36,4.41v83.19a4.34,4.34,0,0,0,4.36,4.41h82.32a4.34,4.34,0,0,0,4.36-4.41V68.47A4.1,4.1,0,0,0,133.57,64.06Z"/></g></g></svg>

After

Width:  |  Height:  |  Size: 965 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 201 201"><defs><style>.cls-1{opacity:0;}.cls-2,.cls-3{fill:none;stroke:#092370;stroke-miterlimit:10;}.cls-3{stroke-width:0.83px;}.cls-4{fill:#a375e9;}.cls-5{fill:#c5a9f1;}</style></defs><title>11个人源服务</title><g id="图层_2" data-name="图层 2"><g id="图层_1-2" data-name="图层 1"><g class="cls-1"><path class="cls-2" d="M100.5.5h0a100,100,0,0,1,100,100h0a100,100,0,0,1-100,100h0a100,100,0,0,1-100-100h0A100,100,0,0,1,100.5.5Z"/><rect class="cls-2" x="33.83" y="33.83" width="133.33" height="133.33"/><rect class="cls-3" x="44.93" y="44.93" width="111.13" height="111.13"/></g><rect class="cls-4" x="45.47" y="54.12" width="43.86" height="44.33"/><rect class="cls-4" x="45.47" y="111.74" width="43.86" height="44.33"/><polygon class="cls-5" points="124.52 44.94 93.5 76.28 124.52 107.62 155.53 76.28 124.52 44.94"/><rect class="cls-4" x="102.59" y="111.74" width="43.86" height="44.33"/></g></g></svg>

After

Width:  |  Height:  |  Size: 970 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 201 201"><defs><style>.cls-1{opacity:0;}.cls-2,.cls-3{fill:none;stroke:#092370;stroke-miterlimit:10;}.cls-3{stroke-width:0.83px;}.cls-4{fill:#dce6fe;}.cls-5{fill:#4f80f9;}</style></defs><title>12Python</title><g id="图层_2" data-name="图层 2"><g id="图层_1-2" data-name="图层 1"><g class="cls-1"><path class="cls-2" d="M100.5.5h0a100,100,0,0,1,100,100h0a100,100,0,0,1-100,100h0a100,100,0,0,1-100-100h0A100,100,0,0,1,100.5.5Z"/><rect class="cls-2" x="33.83" y="33.83" width="133.33" height="133.33"/><rect class="cls-3" x="44.93" y="44.93" width="111.13" height="111.13"/></g><rect class="cls-4" x="44.93" y="54.56" width="111.13" height="91.88" rx="0.87" ry="0.87"/><path class="cls-5" d="M121,81.2l6,.73c0,.52.1,1,.1,1.44q0,11.59,0,23.18c0,4.07-.91,7.82-3.81,10.86a16.52,16.52,0,0,1-12.59,4.65l-1.94-5.83c9.78-1.48,13.11-4,12.39-9.38-2.53.57-5,1.27-7.59,1.68-4.42.7-8.28-.88-10-4.1a8.84,8.84,0,0,1-1-3.78c-.11-5.33,0-10.66-.07-16a2.14,2.14,0,0,1,1.06-2.11c1.63-1,3.19-2.12,5-3.31,0,.52.08.9.08,1.28,0,5.49-.14,11,.12,16.45.21,4.58,2.73,6.14,7.16,4.94l.3-.11c4.79-1.54,4.79-1.54,4.78-6.56C121,90.64,121,86,121,81.2Z"/><path class="cls-5" d="M80.09,122.26c-2.14-1.41-4-2.57-5.74-3.83a1.71,1.71,0,0,1-.45-1.24q0-16.46,0-32.93a1.8,1.8,0,0,1,.57-1.33,23.79,23.79,0,0,1,9.46-4c4.73-.69,8.53.93,10.93,4.94,3.81,6.38,5.41,13.11,1.51,20.11-1.91,3.42-4.68,5.87-8.77,6.12a15.06,15.06,0,0,1-4.51-.66,18,18,0,0,1-3-1.39Zm-.34-27.38q0,1.6,0,3.19c0,4.54.56,5.24,5.07,6.36,3.57.89,6.14-.45,7.16-4a18.72,18.72,0,0,0-.36-11.91c-1-2.78-2.94-4-5.84-3.46a22.12,22.12,0,0,0-5.46,2.39c-.36.18-.53,1-.55,1.51C79.71,90.94,79.75,92.91,79.75,94.88Z"/></g></g></svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 201 201"><defs><style>.cls-1{opacity:0;}.cls-2,.cls-3{fill:none;stroke:#092370;stroke-miterlimit:10;}.cls-3{stroke-width:0.83px;}.cls-4{fill:#dce6fe;}.cls-5{fill:#4f80f9;}</style></defs><title>13测试报告</title><g id="图层_2" data-name="图层 2"><g id="图层_1-2" data-name="图层 1"><g class="cls-1"><path class="cls-2" d="M100.5.5h0a100,100,0,0,1,100,100h0a100,100,0,0,1-100,100h0a100,100,0,0,1-100-100h0A100,100,0,0,1,100.5.5Z"/><rect class="cls-2" x="33.83" y="33.83" width="133.33" height="133.33"/><rect class="cls-3" x="44.93" y="44.93" width="111.13" height="111.13"/></g><rect class="cls-4" x="44.93" y="54.56" width="111.13" height="91.88" rx="2" ry="2"/><path class="cls-5" d="M82.54,115.79,69.84,100.5a2,2,0,0,1,0-2.56L82.52,82.68a2,2,0,0,0-.25-2.81L81.22,79a2,2,0,0,0-2.83.25l-16.6,20,0,0,16.6,20a2,2,0,0,0,2.83.25l1-.89A2,2,0,0,0,82.54,115.79Z"/><path class="cls-5" d="M122.61,79.24a2,2,0,0,0-2.83-.25l-1,.89a2,2,0,0,0-.25,2.8l12.68,15.26a2,2,0,0,1,0,2.56l-12.7,15.29a2,2,0,0,0,.25,2.8l1,.89a2,2,0,0,0,2.83-.25l16.6-20,0,0Z"/><path class="cls-5" d="M109.12,79l-1.27-.47a2,2,0,0,0-2.58,1.19L90.69,119.58a2,2,0,0,0,1.18,2.56l1.27.47a2,2,0,0,0,2.58-1.19L110.3,81.55A2,2,0,0,0,109.12,79Z"/></g></g></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 201 201"><defs><style>.cls-1{opacity:0;}.cls-2,.cls-3{fill:none;stroke:#092370;stroke-miterlimit:10;}.cls-3{stroke-width:0.83px;}.cls-4{fill:#dce6fe;}.cls-5{fill:#4f80f9;}</style></defs><title>14描述统计</title><g id="图层_2" data-name="图层 2"><g id="图层_1-2" data-name="图层 1"><g class="cls-1"><path class="cls-2" d="M100.5.5h0a100,100,0,0,1,100,100h0a100,100,0,0,1-100,100h0a100,100,0,0,1-100-100h0A100,100,0,0,1,100.5.5Z"/><rect class="cls-2" x="33.83" y="33.83" width="133.33" height="133.33"/><rect class="cls-3" x="44.93" y="44.93" width="111.13" height="111.13"/></g><rect class="cls-4" x="44.93" y="54.56" width="111.13" height="91.88" rx="0.87" ry="0.87"/><rect class="cls-5" x="74.4" y="82.72" width="5.65" height="41.01" rx="2" ry="2"/><rect class="cls-5" x="121.45" y="86.31" width="5.15" height="37.42" rx="2" ry="2"/><rect class="cls-5" x="97.8" y="77.27" width="5.65" height="46.47" rx="2" ry="2"/></g></g></svg>

After

Width:  |  Height:  |  Size: 996 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 201 201"><defs><style>.cls-1{opacity:0;}.cls-2,.cls-3{fill:none;stroke:#092370;stroke-miterlimit:10;}.cls-3{stroke-width:0.83px;}.cls-4{fill:#facd51;}</style></defs><title>15清洗</title><g id="图层_2" data-name="图层 2"><g id="图层_1-2" data-name="图层 1"><g class="cls-1"><path class="cls-2" d="M100.5.5h0a100,100,0,0,1,100,100h0a100,100,0,0,1-100,100h0a100,100,0,0,1-100-100h0A100,100,0,0,1,100.5.5Z"/><rect class="cls-2" x="33.83" y="33.83" width="133.33" height="133.33"/><rect class="cls-3" x="44.93" y="44.93" width="111.13" height="111.13"/></g><path class="cls-4" d="M112.41,81.61V48a3,3,0,0,0-3-3H91.61a3,3,0,0,0-3,3V81.61a3,3,0,0,1-3,3H51.92a3,3,0,0,0-3,3v9.84a3,3,0,0,0,3,3h1.91a3,3,0,0,1,3,3V153a3,3,0,0,0,3,3H69.7a3,3,0,0,0,3-3V127.33a3,3,0,0,1,3-3h1.91a3,3,0,0,1,3,3V153a3,3,0,0,0,3,3h9.84a3,3,0,0,0,3-3V127.33a3,3,0,0,1,3-3h1.91a3,3,0,0,1,3,3V153a3,3,0,0,0,3,3h9.84a3,3,0,0,0,3-3V127.33a3,3,0,0,1,3-3h1.91a3,3,0,0,1,3,3V153a3,3,0,0,0,3,3h9.84a3,3,0,0,0,3-3V103.52a3,3,0,0,1,3-3h1.91a3,3,0,0,0,3-3V87.64a3,3,0,0,0-3-3H115.42A3,3,0,0,1,112.41,81.61Z"/></g></g></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 201 201"><defs><style>.cls-1{opacity:0;}.cls-2,.cls-3,.cls-6{fill:none;}.cls-2,.cls-3{stroke:#092370;stroke-miterlimit:10;}.cls-3{stroke-width:0.83px;}.cls-4{fill:#facd51;}.cls-5{fill:#fce5a7;}.cls-6{stroke:#facd51;stroke-linecap:round;stroke-linejoin:round;stroke-width:10.96px;}</style></defs><title>16连接</title><g id="图层_2" data-name="图层 2"><g id="图层_1-2" data-name="图层 1"><g class="cls-1"><path class="cls-2" d="M100.5.5h0a100,100,0,0,1,100,100h0a100,100,0,0,1-100,100h0a100,100,0,0,1-100-100h0A100,100,0,0,1,100.5.5Z"/><rect class="cls-2" x="33.83" y="33.83" width="133.33" height="133.33"/><rect class="cls-3" x="44.93" y="44.93" width="111.13" height="111.13"/></g><circle class="cls-4" cx="102.42" cy="61.04" r="15.33"/><circle class="cls-5" cx="60.26" cy="130.01" r="15.33"/><circle class="cls-5" cx="140.74" cy="130.01" r="15.33"/><path class="cls-6" d="M51.91,103.62A48.44,48.44,0,0,1,74.41,65.84"/><path class="cls-6" d="M126,147.92a48.51,48.51,0,0,1-50.56.53"/><path class="cls-6" d="M130,68.61a48.38,48.38,0,0,1,18.61,35.83"/></g></g></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 201 201"><defs><style>.cls-1{opacity:0;}.cls-2,.cls-3{fill:none;stroke:#092370;stroke-miterlimit:10;}.cls-3{stroke-width:0.83px;}.cls-4{fill:#fce5a7;}.cls-5{fill:#facd51;}</style></defs><title>17工作包</title><g id="图层_2" data-name="图层 2"><g id="图层_1-2" data-name="图层 1"><g class="cls-1"><path class="cls-2" d="M100.5.5h0a100,100,0,0,1,100,100h0a100,100,0,0,1-100,100h0a100,100,0,0,1-100-100h0A100,100,0,0,1,100.5.5Z"/><rect class="cls-2" x="33.83" y="33.83" width="133.33" height="133.33"/><rect class="cls-3" x="44.93" y="44.93" width="111.13" height="111.13"/></g><path class="cls-4" d="M156.07,73.41c0-10.19-4.54-17.36-13.43-17.36H59.75c-8.88,0-14.82,7.18-14.82,17.36v16H156.07Z"/><path class="cls-5" d="M44.94,89.39v41.52c0,10.19,5,14,13.89,14h82.88c8.88,0,14.35-3.86,14.35-14V89.39Z"/></g></g></svg>

After

Width:  |  Height:  |  Size: 878 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 201 201"><defs><style>.cls-1{opacity:0;}.cls-2,.cls-3{fill:none;stroke:#092370;stroke-miterlimit:10;}.cls-3{stroke-width:0.83px;}.cls-4{fill:#9198b3;}</style></defs><title>18存储</title><g id="图层_2" data-name="图层 2"><g id="图层_1-2" data-name="图层 1"><g class="cls-1"><path class="cls-2" d="M100.5.5h0a100,100,0,0,1,100,100h0a100,100,0,0,1-100,100h0a100,100,0,0,1-100-100h0A100,100,0,0,1,100.5.5Z"/><rect class="cls-2" x="33.83" y="33.83" width="133.33" height="133.33"/><rect class="cls-3" x="44.93" y="44.93" width="111.13" height="111.13"/></g><path class="cls-4" d="M119.72,76.67a3.48,3.48,0,0,0,3.47-3.47v-7a3.47,3.47,0,1,0-6.95,0v7A3.48,3.48,0,0,0,119.72,76.67Z"/><path class="cls-4" d="M140.61,44.94H60.39A15.47,15.47,0,0,0,44.94,60.39v80.23a15.47,15.47,0,0,0,15.45,15.45h80.23a15.47,15.47,0,0,0,15.45-15.45V60.39A15.47,15.47,0,0,0,140.61,44.94Zm-11.9,7.75V80a3.32,3.32,0,0,1-3.31,3.31H75.6A3.32,3.32,0,0,1,72.29,80V52.69Zm19.6,87.92a7.71,7.71,0,0,1-7.7,7.7H60.39a7.71,7.71,0,0,1-7.7-7.7V60.39a7.71,7.71,0,0,1,7.7-7.7h4.15V80A11.08,11.08,0,0,0,75.6,91H125.4A11.08,11.08,0,0,0,136.47,80V52.69h4.15a7.71,7.71,0,0,1,7.7,7.7Z"/></g></g></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 201 201"><defs><style>.cls-1{opacity:0;}.cls-2,.cls-3{fill:none;stroke:#092370;stroke-miterlimit:10;}.cls-3{stroke-width:0.83px;}.cls-4{fill:#9198b3;}</style></defs><title>19导出</title><g id="图层_2" data-name="图层 2"><g id="图层_1-2" data-name="图层 1"><g class="cls-1"><path class="cls-2" d="M100.5.5h0a100,100,0,0,1,100,100h0a100,100,0,0,1-100,100h0a100,100,0,0,1-100-100h0A100,100,0,0,1,100.5.5Z"/><rect class="cls-2" x="33.83" y="33.83" width="133.33" height="133.33"/><rect class="cls-3" x="44.93" y="44.93" width="111.13" height="111.13"/></g><path class="cls-4" d="M138.79,69.74c-.11-7-4.94-10.87-12.88-11-2.6,0-5.21,0-8,0,0-1.41.06-2.27,0-3.14-.54-6.67-5-10.5-12.45-10.53q-24.13-.1-48.26,0C49.71,45.1,45,49.17,45,55.72q-.12,35.46,0,70.92c0,6.28,4.67,10.47,11.68,11,1.22.08,2.44.15,4.13.25,0,2.9-.13,5.62,0,8.32a10.09,10.09,0,0,0,9.85,9.56c8.58.25,17.16.3,25.75.25h13.35a3.62,3.62,0,0,0,3.8-3.38v-.19a3.62,3.62,0,0,0-3.8-3.38H96.48q-10.74,0-21.47,0c-5.66,0-6.53-.81-6.53-5.87q0-35.83,0-71.66c0-5.15.74-5.82,6.51-5.83q24.54,0,49.09,0c6.25,0,6.89.58,6.9,6.26q0,17.92,0,35.83c0,2.38.92,4.43,3.88,4.4s4-1.94,4-4.37C138.85,95.12,139,82.43,138.79,69.74Zm-29-11h-4.37c-10.49,0-21,0-31.48,0q-13.11.08-13.13,11.8c0,18.54,0,37.08,0,55.62v3.94c-6.23,1.07-8-.14-8-5.17q0-33.78,0-67.57c0-4.58,1-5.48,6.09-5.48q22.46,0,44.91,0C109.37,51.88,110.4,52.95,109.75,58.72Z"/><path class="cls-4" d="M118.33,100.39c-6.14.05-12.28,0-18.41,0s-12.56,0-18.83,0c-2.65,0-4.52.91-4.71,3.23-.2,2.59,1.82,3.82,4.54,3.83q18.83.08,37.66,0c2.66,0,4.68-1.15,4.45-3.87C122.82,101.1,120.91,100.37,118.33,100.39Z"/><path class="cls-4" d="M91.4,121c-4,0-8,0-12,0-1.69,0-2.89.91-3,3.23-.13,2.59,1.16,3.82,2.9,3.83,8,.06,16,.07,24,0,1.7,0,3-1.15,2.84-3.87-.14-2.47-1.35-3.21-3-3.18C99.24,121.05,95.32,121,91.4,121Z"/><path class="cls-4" d="M81.36,86.57q18.41,0,36.83,0c2.59,0,4.89-.81,4.82-3.55s-2.24-3.41-4.93-3.4c-6.14,0-12.28,0-18.41,0s-12,0-18,0c-2.86,0-5.25.66-5.27,3.49C76.39,85.72,78.73,86.57,81.36,86.57Z"/><path class="cls-4" d="M137.31,128.39v3.7c-5.05,0-9.56,0-14.31,0-2.78,0-5.5.37-5.53,3.82s2.74,3.82,5.5,3.8c5.23,0,10.46,0,14.3,0l0,.15v4.39c0,2.64,2.44,4.3,4.39,3l13.4-9.09a2.19,2.19,0,0,0,0-3.62l-13.4-9.09C139.75,124.09,137.31,125.74,137.31,128.39Z"/></g></g></svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 201 201"><defs><style>.cls-1{fill:#d8f4e9;}.cls-2{fill:#3ec791;}.cls-3{opacity:0;}.cls-4,.cls-5{fill:none;stroke:#092370;stroke-miterlimit:10;}.cls-5{stroke-width:0.83px;}</style></defs><title>1.开始</title><g id="图层_2" data-name="图层 2"><g id="图层_1-2" data-name="图层 1"><rect class="cls-1" x="44.97" y="55.64" width="111.13" height="91.88" rx="0.87" ry="0.87"/><polygon class="cls-2" points="85.38 78 85.38 125.16 125.79 101.58 85.38 78"/><g class="cls-3"><path class="cls-4" d="M100.5.5h0a100,100,0,0,1,100,100h0a100,100,0,0,1-100,100h0a100,100,0,0,1-100-100h0A100,100,0,0,1,100.5.5Z"/><rect class="cls-4" x="33.83" y="33.83" width="133.33" height="133.33"/><rect class="cls-5" x="44.93" y="44.93" width="111.13" height="111.13"/></g></g></g></svg>

After

Width:  |  Height:  |  Size: 820 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 201 201"><defs><style>.cls-1{opacity:0;}.cls-2,.cls-3{fill:none;stroke:#092370;stroke-miterlimit:10;}.cls-3{stroke-width:0.83px;}.cls-4{fill:#9198b3;}</style></defs><title>20执行</title><g id="图层_2" data-name="图层 2"><g id="图层_1-2" data-name="图层 1"><g class="cls-1"><path class="cls-2" d="M100.5.5h0a100,100,0,0,1,100,100h0a100,100,0,0,1-100,100h0a100,100,0,0,1-100-100h0A100,100,0,0,1,100.5.5Z"/><rect class="cls-2" x="33.83" y="33.83" width="133.33" height="133.33"/><rect class="cls-3" x="44.93" y="44.93" width="111.13" height="111.13"/></g><path class="cls-4" d="M49.12,97.56q0-19.34,0-38.69C49.13,50.62,54.65,45,62.89,45Q91.45,44.9,120,45c8.07,0,13.73,5.57,13.83,13.64.12,9.07,0,18.13,0,27.2,0,3.1-1.42,4.78-3.83,4.76s-3.72-1.67-3.73-4.86c0-8.46,0-16.93,0-25.39,0-6.07-1.72-7.8-7.69-7.8H64.19c-5.75,0-7.6,1.85-7.6,7.61q0,37.78,0,75.56c0,5.81,1.74,7.53,7.57,7.53H83.5c.71,0,1.41,0,2.11,0,2.39.15,3.8,1.47,3.8,3.83a3.37,3.37,0,0,1-3.65,3.61c-8.56,0-17.14.28-25.68-.15-6.21-.31-10.88-6.09-10.92-12.77-.09-13.4,0-26.8,0-40.2Z"/><path class="cls-4" d="M151.88,129.77a26.42,26.42,0,1,1-26.34-26.61A26.44,26.44,0,0,1,151.88,129.77Zm-26.56,18.74a18.89,18.89,0,1,0,.13-37.78,18.89,18.89,0,0,0-.13,37.78Z"/><path class="cls-4" d="M91.26,63.9c6.84,0,13.68,0,20.53,0,3.23,0,4.78,1.24,4.75,3.7s-1.63,3.73-4.8,3.74q-20.22,0-40.45,0c-3.18,0-5.11-1.6-5-3.95s1.82-3.48,5-3.49Q81.3,63.89,91.26,63.9Z"/><path class="cls-4" d="M85.51,92.32c-4.84,0-9.67,0-14.51,0-2.57,0-4.35-1-4.66-3.68-.27-2.25,1.74-4,4.67-4q14.66-.07,29.32,0c2.47,0,4.41.86,4.6,3.69.16,2.46-1.52,3.91-4.61,3.94C95.38,92.36,90.44,92.32,85.51,92.32Z"/><path class="cls-4" d="M75.31,113.37c-1.91-.09-3.83-.09-5.72-.29a3.4,3.4,0,0,1-3.24-3.7A3.46,3.46,0,0,1,70,105.75c3.62-.08,7.24-.07,10.86,0a3.4,3.4,0,0,1,3.64,3.6,3.32,3.32,0,0,1-3.17,3.72C79.34,113.28,77.32,113.28,75.31,113.37Z"/><path class="cls-4" d="M121.35,129.65c0-1.91-.09-3.82,0-5.72.16-2.67,1.88-3.58,4.06-2.08,2.56,1.76,5,3.68,7.47,5.57,1.85,1.42,1.94,3,.05,4.44-2.46,1.9-4.94,3.79-7.51,5.54-2.22,1.52-3.84.65-4.1-2,0-.2,0-.4,0-.6q0-2.56,0-5.12Z"/></g></g></svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 201 201"><defs><style>.cls-1{opacity:0;}.cls-2,.cls-3{fill:none;stroke:#092370;stroke-miterlimit:10;}.cls-3{stroke-width:0.83px;}.cls-4{fill:#9198b3;}</style></defs><title>21封装包</title><g id="图层_2" data-name="图层 2"><g id="图层_1-2" data-name="图层 1"><g class="cls-1"><path class="cls-2" d="M100.5.5h0a100,100,0,0,1,100,100h0a100,100,0,0,1-100,100h0a100,100,0,0,1-100-100h0A100,100,0,0,1,100.5.5Z"/><rect class="cls-2" x="33.83" y="33.83" width="133.33" height="133.33"/><rect class="cls-3" x="44.93" y="44.93" width="111.13" height="111.13"/></g><path class="cls-4" d="M140.61,65H127.67c-1.18-11.15-10.37-19.86-21.51-19.86H95.7c-11.13,0-20.32,8.71-21.51,19.86H60.39A15.71,15.71,0,0,0,44.94,80.89V140a15.71,15.71,0,0,0,15.45,15.92h80.23A15.71,15.71,0,0,0,156.07,140V80.89A15.71,15.71,0,0,0,140.61,65ZM95.7,53.1h10.46A14,14,0,0,1,119.81,65H82A14,14,0,0,1,95.7,53.1ZM72.29,73h56.43V90.4a3.37,3.37,0,0,1-3.31,3.41H75.6a3.37,3.37,0,0,1-3.31-3.41Zm76,67a7.83,7.83,0,0,1-7.7,7.93H60.39a7.83,7.83,0,0,1-7.7-7.93V80.89A7.83,7.83,0,0,1,60.39,73h4.15V90.4A11.25,11.25,0,0,0,75.6,101.8H125.4a11.25,11.25,0,0,0,11.06-11.4V73h4.15a7.83,7.83,0,0,1,7.7,7.93Z"/></g></g></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 201 201"><defs><style>.cls-1{opacity:0;}.cls-2,.cls-3{fill:none;stroke:#092370;stroke-miterlimit:10;}.cls-3{stroke-width:0.83px;}.cls-4{fill:#ffdce0;}.cls-5{fill:#ff4f63;}</style></defs><title>2.结束</title><g id="图层_2" data-name="图层 2"><g id="图层_1-2" data-name="图层 1"><g class="cls-1"><path class="cls-2" d="M100.5.5h0a100,100,0,0,1,100,100h0a100,100,0,0,1-100,100h0a100,100,0,0,1-100-100h0A100,100,0,0,1,100.5.5Z"/><rect class="cls-2" x="33.83" y="33.83" width="133.33" height="133.33"/><rect class="cls-3" x="44.93" y="44.93" width="111.13" height="111.13"/></g><rect class="cls-4" x="44.93" y="54.56" width="111.13" height="91.88" rx="0.87" ry="0.87"/><ellipse class="cls-5" cx="100.5" cy="100.5" rx="23.15" ry="23.4"/></g></g></svg>

After

Width:  |  Height:  |  Size: 809 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 201 201"><defs><style>.cls-1{opacity:0;}.cls-2,.cls-3{fill:none;stroke:#092370;stroke-miterlimit:10;}.cls-3{stroke-width:0.83px;}.cls-4{fill:#4f80f9;}.cls-5{fill:#95b3fb;}</style></defs><title>3.横向分割</title><g id="图层_2" data-name="图层 2"><g id="图层_1-2" data-name="图层 1"><g class="cls-1"><path class="cls-2" d="M100.5.5h0a100,100,0,0,1,100,100h0a100,100,0,0,1-100,100h0a100,100,0,0,1-100-100h0A100,100,0,0,1,100.5.5Z"/><rect class="cls-2" x="33.83" y="33.83" width="133.33" height="133.33"/><rect class="cls-3" x="44.93" y="44.93" width="111.13" height="111.13"/></g><path class="cls-4" d="M44.93,54.2h65c.09,1.11.23,2,.23,2.91,0,28.84,0,57.68.06,86.53,0,2.2-.57,3-3.42,3-12.91,0-25.82.13-38.74.19-7.6,0-15.2,0-23.09,0Zm25.79,5.24v81.78H83.9V59.44ZM51,59.45v81.78H64V59.45Zm39.4,81.76h13.19V59.55H90.38Z"/><path class="cls-5" d="M117.34,72.61h29l.46-.67-9.16-9.34,4.65-3.87c4,4,8.8,8,12.58,12.8,1.38,1.75,1.63,6.27.34,7.91-3.89,4.94-8.79,9.08-13.33,13.57l-5-4.69,10.2-8.5-.63-1H117.34Z"/><path class="cls-5" d="M146.35,128.81h-29v-6h29l.5-.78-9.16-9.4,4.22-4.43c4.56,4.56,9.36,8.66,13.16,13.54,1.34,1.72,1.37,6.22,0,7.93-3.81,4.88-8.63,9-13.28,13.61L138,139.06l-.84-.78,10.22-8Z"/><rect class="cls-4" x="47.82" y="58.72" width="60.6" height="82.49"/></g></g></svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 201 201"><defs><style>.cls-1{opacity:0;}.cls-2,.cls-3{fill:none;stroke:#092370;stroke-miterlimit:10;}.cls-3{stroke-width:0.83px;}.cls-4{fill:#4f80f9;}.cls-5{fill:#95b3fb;}</style></defs><title>4.纵向分割</title><g id="图层_2" data-name="图层 2"><g id="图层_1-2" data-name="图层 1"><g class="cls-1"><path class="cls-2" d="M100.5.5h0a100,100,0,0,1,100,100h0a100,100,0,0,1-100,100h0a100,100,0,0,1-100-100h0A100,100,0,0,1,100.5.5Z"/><rect class="cls-2" x="33.83" y="33.83" width="133.33" height="133.33"/><rect class="cls-3" x="44.93" y="44.93" width="111.13" height="111.13"/></g><path class="cls-4" d="M146.8,44.94v65c-1.11.09-2,.23-2.91.23-28.84,0-57.68,0-86.53.06-2.2,0-3-.57-3-3.42,0-12.91-.13-25.82-.19-38.74,0-7.6,0-15.2,0-23.09Zm-5.24,25.79H59.78V83.91h81.78Zm0-19.74H59.77V64.05h81.78ZM59.79,90.38v13.19h81.66V90.38Z"/><path class="cls-5" d="M128.39,117.34v29l.67.46,9.34-9.16,3.87,4.65c-4,4-8,8.8-12.8,12.58-1.75,1.38-6.27,1.63-7.91.34-4.94-3.89-9.08-8.79-13.57-13.33l4.69-5,8.5,10.2,1-.63V117.34Z"/><path class="cls-5" d="M72.19,146.35v-29h6v29l.78.5,9.4-9.16,4.43,4.22c-4.56,4.56-8.66,9.36-13.54,13.16-1.72,1.34-6.22,1.37-7.93,0-4.88-3.81-9-8.63-13.61-13.28L61.94,138l.78-.84,8,10.22Z"/><rect class="cls-4" x="70.53" y="33.32" width="60.6" height="86.49" transform="translate(177.4 -24.26) rotate(90)"/></g></g></svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 201 201"><defs><style>.cls-1{opacity:0;}.cls-2,.cls-3{fill:none;stroke:#092370;stroke-miterlimit:10;}.cls-3{stroke-width:0.83px;}.cls-4{fill:#c5a9f1;}.cls-5{fill:#a375e9;}</style></defs><title>5文件数据</title><g id="图层_2" data-name="图层 2"><g id="图层_1-2" data-name="图层 1"><g class="cls-1"><path class="cls-2" d="M100.5.5h0a100,100,0,0,1,100,100h0a100,100,0,0,1-100,100h0a100,100,0,0,1-100-100h0A100,100,0,0,1,100.5.5Z"/><rect class="cls-2" x="33.83" y="33.83" width="133.33" height="133.33"/><rect class="cls-3" x="44.93" y="44.93" width="111.13" height="111.13"/></g><polygon class="cls-4" points="109.15 44.94 50.33 44.94 50.33 117.63 88.76 117.63 88.76 82.77 109.16 82.77 109.16 44.94 109.15 44.94"/><polygon class="cls-5" points="150.66 88.1 115.07 88.1 94.69 88.1 94.67 122.95 94.67 156.06 150.67 156.06 150.67 88.1 150.66 88.1"/></g></g></svg>

After

Width:  |  Height:  |  Size: 923 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 201 201"><defs><style>.cls-1{opacity:0;}.cls-2,.cls-3{fill:none;stroke:#092370;stroke-miterlimit:10;}.cls-3{stroke-width:0.83px;}.cls-4{fill:#a375e9;}.cls-5{fill:#fff;}</style></defs><title>6数据校验</title><g id="图层_2" data-name="图层 2"><g id="图层_1-2" data-name="图层 1"><g class="cls-1"><path class="cls-2" d="M100.5.5h0a100,100,0,0,1,100,100h0a100,100,0,0,1-100,100h0a100,100,0,0,1-100-100h0A100,100,0,0,1,100.5.5Z"/><rect class="cls-2" x="33.83" y="33.83" width="133.33" height="133.33"/><rect class="cls-3" x="44.93" y="44.93" width="111.13" height="111.13"/></g><path class="cls-4" d="M150.42,44.93H50.77a5.24,5.24,0,0,0-5.27,5.32V150.74a5.24,5.24,0,0,0,5.27,5.32h99.44a5.24,5.24,0,0,0,5.27-5.32V50.26A5,5,0,0,0,150.42,44.93Z"/><path class="cls-5" d="M136.29,77.79a5.36,5.36,0,0,0-7.54.44L99,111.73l-16.9-15a5.36,5.36,0,0,0-7.54.44h0a5.36,5.36,0,0,0,.44,7.54l20.83,18.53a5.36,5.36,0,0,0,6.75.28,5.29,5.29,0,0,0,1.05-.9l33.13-37.25A5.36,5.36,0,0,0,136.29,77.79Z"/></g></g></svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 201 201"><defs><style>.cls-1{opacity:0;}.cls-2,.cls-3{fill:none;stroke:#092370;stroke-miterlimit:10;}.cls-3{stroke-width:0.83px;}.cls-4{fill:#a375e9;}.cls-5{fill:#c5a9f1;}</style></defs><title>7单键查询</title><g id="图层_2" data-name="图层 2"><g id="图层_1-2" data-name="图层 1"><g class="cls-1"><path class="cls-2" d="M100.5.5h0a100,100,0,0,1,100,100h0a100,100,0,0,1-100,100h0a100,100,0,0,1-100-100h0A100,100,0,0,1,100.5.5Z"/><rect class="cls-2" x="33.83" y="33.83" width="133.33" height="133.33"/><rect class="cls-3" x="44.93" y="44.93" width="111.13" height="111.13"/></g><path class="cls-4" d="M105.32,125.61,85.67,145.47,56,115.49,75.66,95.63a5.34,5.34,0,0,0,0-7.49,5.21,5.21,0,0,0-7.42,0L48.59,108a10.68,10.68,0,0,0,0,15l29.66,30a10.41,10.41,0,0,0,14.83,0l19.65-19.86a5.34,5.34,0,0,0,0-7.49A5.21,5.21,0,0,0,105.32,125.61ZM152.41,78,122.75,48a10.41,10.41,0,0,0-14.83,0L88.26,67.9A5.34,5.34,0,0,0,86.91,73a5.27,5.27,0,0,0,3.71,3.75,5.21,5.21,0,0,0,5.07-1.37l19.65-19.86,29.66,30-19.65,19.86a5.34,5.34,0,0,0,0,7.49,5.21,5.21,0,0,0,7.42,0L152.41,93a10.68,10.68,0,0,0,0-15Z"/><path class="cls-5" d="M111.62,89.26a5.2,5.2,0,0,0-7.42,0l-14.83,15a5.34,5.34,0,0,0,0,7.49,5.21,5.21,0,0,0,7.42,0l14.83-15A5.34,5.34,0,0,0,111.62,89.26Z"/></g></g></svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 201 201"><defs><style>.cls-1{opacity:0;}.cls-2,.cls-3{fill:none;stroke:#092370;stroke-miterlimit:10;}.cls-3{stroke-width:0.83px;}.cls-4{fill:#c5a9f1;}.cls-5{fill:#a375e9;}</style></defs><title>8个人服务</title><g id="图层_2" data-name="图层 2"><g id="图层_1-2" data-name="图层 1"><g class="cls-1"><path class="cls-2" d="M100.5.5h0a100,100,0,0,1,100,100h0a100,100,0,0,1-100,100h0a100,100,0,0,1-100-100h0A100,100,0,0,1,100.5.5Z"/><rect class="cls-2" x="33.83" y="33.83" width="133.33" height="133.33"/><rect class="cls-3" x="44.93" y="44.93" width="111.13" height="111.13"/></g><circle class="cls-4" cx="100.5" cy="78.54" r="28.71"/><path class="cls-5" d="M100.5,106.1c-27.34,0-50.16,13.23-55.56,45.06H156.07C150.66,119.33,127.84,106.1,100.5,106.1Z"/></g></g></svg>

After

Width:  |  Height:  |  Size: 829 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 201 201"><defs><style>.cls-1{opacity:0;}.cls-2,.cls-3{fill:none;stroke:#092370;stroke-miterlimit:10;}.cls-3{stroke-width:0.83px;}.cls-4{fill:#c5a9f1;}.cls-5{fill:#a375e9;}</style></defs><title>9外部服务</title><g id="图层_2" data-name="图层 2"><g id="图层_1-2" data-name="图层 1"><g class="cls-1"><path class="cls-2" d="M100.5.5h0a100,100,0,0,1,100,100h0a100,100,0,0,1-100,100h0a100,100,0,0,1-100-100h0A100,100,0,0,1,100.5.5Z"/><rect class="cls-2" x="33.83" y="33.83" width="133.33" height="133.33"/><rect class="cls-3" x="44.93" y="44.93" width="111.13" height="111.13"/></g><path class="cls-4" d="M100.5,61C78.76,45.72,58.13,40.34,49.23,49.24S45.72,78.77,61,100.5A168.25,168.25,0,0,1,100.5,61Z"/><path class="cls-4" d="M121.9,121.9A163.41,163.41,0,0,1,100.5,140c21.74,15.28,42.37,20.66,51.27,11.76s3.51-29.53-11.77-51.26A163.45,163.45,0,0,1,121.9,121.9Z"/><path class="cls-5" d="M140,100.5c15.28-21.73,20.66-42.37,11.77-51.27S122.24,45.72,100.5,61a163.41,163.41,0,0,1,21.4,18.1A163.45,163.45,0,0,1,140,100.5Z"/><path class="cls-5" d="M61,100.5c-15.28,21.73-20.66,42.37-11.77,51.26S78.76,155.28,100.5,140a163.49,163.49,0,0,1-21.4-18.1A163.45,163.45,0,0,1,61,100.5Z"/><path class="cls-5" d="M140,100.5a163.45,163.45,0,0,0-18.1-21.4A163.41,163.41,0,0,0,100.5,61,168.25,168.25,0,0,0,61,100.5a163.45,163.45,0,0,0,18.1,21.4A163.49,163.49,0,0,0,100.5,140a163.41,163.41,0,0,0,21.4-18.1A163.45,163.45,0,0,0,140,100.5Zm-40.28,8a8,8,0,1,1,8-8A8,8,0,0,1,99.72,108.46Z"/></g></g></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1,40 @@
let dataA = {
name: '流程A',
nodeList: [
{
id: 'nodeA',
name: '流程A-节点A',
type: 'task',
left: '26px',
top: '161px',
ico: 'el-icon-user-solid'
},
{
id: 'nodeB',
name: '流程A-节点B',
type: 'task',
left: '340px',
top: '161px',
ico: 'el-icon-goods'
},
{
id: 'nodeC',
name: '流程A-节点C',
type: 'task',
left: '739px',
top: '161px',
ico: 'el-icon-present'
}
],
lineList: [{
from: 'nodeA',
to: 'nodeB'
}, {
from: 'nodeB',
to: 'nodeC'
}]
}
export function getDataA () {
return dataA
}

View File

@ -0,0 +1,61 @@
let dataB = {
name: '流程B',
nodeList: [
{
id: 'nodeA',
name: '节点A-不可拖拽',
type: 'task',
left: '18px',
top: '223px',
ico: 'el-icon-user-solid',
state: 'success',
viewOnly: true
},
{
id: 'nodeB',
type: 'task',
name: '流程B-节点B',
left: '351px',
top: '96px',
ico: 'el-icon-goods',
state: 'error'
},
{
id: 'nodeC',
name: '流程B-节点C',
type: 'task',
left: '354px',
top: '351px',
ico: 'el-icon-present',
state: 'warning'
}, {
id: 'nodeD',
name: '流程B-节点D',
type: 'task',
left: '723px',
top: '215px',
ico: 'el-icon-present',
state: 'running'
}
],
lineList: [{
from: 'nodeA',
to: 'nodeB',
label: '条件A'
}, {
from: 'nodeA',
to: 'nodeC',
label: '条件B'
}, {
from: 'nodeB',
to: 'nodeD'
}, {
from: 'nodeC',
to: 'nodeD'
}
]
}
export function getDataB () {
return dataB
}

View File

@ -0,0 +1,42 @@
let dataC = {
name: '流程C',
nodeList: [
{
id: 'nodeA',
name: '流程C-节点A',
type: 'task',
left: '400px',
top: '15px',
ico: 'el-icon-user-solid'
},
{
id: 'nodeB',
name: '流程C-节点B',
type: 'task',
left: '400px',
top: '200px',
ico: 'el-icon-goods'
},
{
id: 'nodeC',
name: '流程C-节点C',
type: 'task',
left: '400px',
top: '378px',
ico: 'el-icon-present'
}
],
lineList: [
{
from: 'nodeA',
to: 'nodeB'
}, {
from: 'nodeB',
to: 'nodeC'
}
]
}
export function getDataC () {
return dataC
}

View File

@ -0,0 +1,71 @@
var dataD = {
name: '流程D',
nodeList: [
{
id: 'nodeA',
name: '流程D-节点A',
type: 'task',
left: '18px',
top: '223px',
ico: 'el-icon-user-solid',
state: 'success'
},
{
id: 'nodeB',
type: 'task',
name: '流程D-节点B',
left: '351px',
top: '96px',
ico: 'el-icon-goods',
state: 'error'
},
{
id: 'nodeC',
name: '流程D-节点C',
type: 'task',
left: '354px',
top: '351px',
ico: 'el-icon-present',
state: 'warning'
}, {
id: 'nodeD',
name: '流程D-节点D',
type: 'task',
left: '723px',
top: '215px',
ico: 'el-icon-present',
state: 'running'
}
],
lineList: [{
from: 'nodeA',
to: 'nodeB',
label: '直线,自定义线样式,固定锚点',
connector: 'Straight',
anchors: ['Top', 'Bottom'],
paintStyle: {strokeWidth: 2, stroke: '#1879FF'}
}, {
from: 'nodeA',
to: 'nodeC',
label: '贝塞尔曲线,固定锚点',
connector: 'Bezier',
anchors: ['Bottom', 'Left']
}, {
from: 'nodeB',
to: 'nodeD',
label: '默认连线样式,动态锚点'
}, {
from: 'nodeC',
to: 'nodeD',
label: '默认连线样式,动态锚点'
}, {
from: 'nodeC',
to: 'nodeC',
label: '自连接'
}
]
}
export function getDataD() {
return dataD
}

View File

@ -0,0 +1,54 @@
var dataE = {
name: '流程E力导图',
nodeList: [
{
id: 'nodeA',
name: '流程D-节点A',
type: 'task',
ico: 'el-icon-user-solid',
state: 'success'
},
{
id: 'nodeB',
type: 'task',
name: '流程D-节点B',
ico: 'el-icon-goods',
state: 'error'
},
{
id: 'nodeC',
name: '流程D-节点C',
type: 'task',
ico: 'el-icon-present',
state: 'warning'
}, {
id: 'nodeD',
name: '流程D-节点D',
type: 'task',
ico: 'el-icon-present',
state: 'running'
}
],
lineList: [{
from: 'nodeA',
to: 'nodeB'
}, {
from: 'nodeA',
to: 'nodeC',
label: 'hello'
}, {
from: 'nodeB',
to: 'nodeD'
}, {
from: 'nodeC',
to: 'nodeD'
}, {
from: 'nodeC',
to: 'nodeC'
}
]
}
export function getDataE() {
return dataE
}

View File

@ -0,0 +1,182 @@
/**
* 感谢 https://github.com/chaangliu/ForceDirectedLayout/blob/master/javascript/force-directed.js
* A force directed graph layout implementation by liuchang on 2018/05/10.
*/
const CANVAS_WIDTH = 1000
const CANVAS_HEIGHT = 1000
let k
let mNodeList = []
let mEdgeList = []
let mDxMap = {}
let mDyMap = {}
let mNodeMap = {}
export function ForceDirected(data = {}) {
// generate nodes and edges
// for (let i = 0; i < 20; i++) {
// mNodeList.push(new Node(i))
// }
k = 0
mNodeList = []
mEdgeList = []
mDxMap = {}
mDyMap = {}
mNodeMap = {}
let nodeList = data.nodeList
for (let i = 0; i < nodeList.length; i++) {
let node = nodeList[i]
mNodeList.push(node)
}
// for (let i = 0; i < 20; i++) {
// let edgeCount = Math.random() * 8 + 1
// for (let j = 0; j < edgeCount; j++) {
// let targetId = Math.floor(Math.random() * 20)
// let edge = new Edge(i, targetId)
// mEdgeList.push(edge)
// }
// }
// line 转 edge
let lineList = data.lineList
for (let i = 0; i < lineList.length; i++) {
let line = lineList[i]
let edge = new Edge(line.from, line.to)
mEdgeList.push(edge)
}
if (mNodeList && mEdgeList) {
k = Math.sqrt(CANVAS_WIDTH * CANVAS_HEIGHT / mNodeList.length)
}
for (let i = 0; i < mNodeList.length; i++) {
let node = mNodeList[i]
if (node) {
mNodeMap[node.id] = node
}
}
// 随机生成坐标. Generate coordinates randomly.
let initialX, initialY, initialSize = 40.0
for (let i in mNodeList) {
initialX = CANVAS_WIDTH * 0.5
initialY = CANVAS_HEIGHT * 0.5
mNodeList[i].x = initialX + initialSize * (Math.random() - 0.5)
mNodeList[i].y = initialY + initialSize * (Math.random() - 0.5)
}
// 迭代200次. Iterate 200 times.
for (let i = 0; i < 200; i++) {
calculateRepulsive()
calculateTraction()
updateCoordinates()
}
// console.log(JSON.stringify(new Result(mNodeList, mEdgeList)))
// 坐标添加px
for (let i = 0; i < mNodeList.length; i++) {
let node = mNodeList[i]
node.left = node.x + 'px'
node.top = node.y + 'px'
node.x = undefined
node.y = undefined
}
data.nodeList = mNodeList
// console.log(data)
return data
}
function Node(id = null) {
this.id = id
this.x = 22
this.y = null
}
function Edge(source = null, target = null) {
this.source = source
this.target = target
}
/**
* 计算两个Node的斥力产生的单位位移
* Calculate the displacement generated by the repulsive force between two nodes.*
*/
function calculateRepulsive() {
let ejectFactor = 6
let distX, distY, dist
for (let i = 0; i < mNodeList.length; i++) {
mDxMap[mNodeList[i].id] = 0.0
mDyMap[mNodeList[i].id] = 0.0
for (let j = 0; j < mNodeList.length; j++) {
if (i !== j) {
distX = mNodeList[i].x - mNodeList[j].x
distY = mNodeList[i].y - mNodeList[j].y
dist = Math.sqrt(distX * distX + distY * distY)
}
if (dist < 30) {
ejectFactor = 5
}
if (dist > 0 && dist < 250) {
let id = mNodeList[i].id
mDxMap[id] = mDxMap[id] + distX / dist * k * k / dist * ejectFactor
mDyMap[id] = mDyMap[id] + distY / dist * k * k / dist * ejectFactor
}
}
}
}
/**
* 计算Edge的引力对两端Node产生的引力
* Calculate the traction force generated by the edge acted on the two nodes of its two ends.
*/
function calculateTraction() {
let condenseFactor = 3
let startNode, endNode
for (let e = 0; e < mEdgeList.length; e++) {
let eStartID = mEdgeList[e].source
let eEndID = mEdgeList[e].target
startNode = mNodeMap[eStartID]
endNode = mNodeMap[eEndID]
if (!startNode) {
console.log('Cannot find start node id: ' + eStartID + ', please check it out.')
return
}
if (!endNode) {
console.log('Cannot find end node id: ' + eEndID + ', please check it out.')
return
}
let distX, distY, dist
distX = startNode.x - endNode.x
distY = startNode.y - endNode.y
dist = Math.sqrt(distX * distX + distY * distY)
mDxMap[eStartID] = mDxMap[eStartID] - distX * dist / k * condenseFactor
mDyMap[eStartID] = mDyMap[eStartID] - distY * dist / k * condenseFactor
mDxMap[eEndID] = mDxMap[eEndID] + distX * dist / k * condenseFactor
mDyMap[eEndID] = mDyMap[eEndID] + distY * dist / k * condenseFactor
}
}
/**
* 更新坐标
* update the coordinates.
*/
function updateCoordinates() {
let maxt = 4, maxty = 3 // Additional coefficients.
for (let v = 0; v < mNodeList.length; v++) {
let node = mNodeList[v]
let dx = Math.floor(mDxMap[node.id])
let dy = Math.floor(mDyMap[node.id])
if (dx < -maxt) dx = -maxt
if (dx > maxt) dx = maxt
if (dy < -maxty) dy = -maxty
if (dy > maxty) dy = maxty
node.x = node.x + dx >= CANVAS_WIDTH || node.x + dx <= 0 ? node.x - dx : node.x + dx
node.y = node.y + dy >= CANVAS_HEIGHT || node.y + dy <= 0 ? node.y - dy : node.y + dy
}
}
function Result(nodes = null, links = null) {
this.nodes = nodes
this.links = links
}

View File

@ -0,0 +1,61 @@
<template>
<el-dialog
title="帮助"
:visible.sync="dialogVisible"
width="70%"
customClass="flowHelp"
>
<el-tabs tab-position="left">
<el-tab-pane label="如何新增">
<el-divider content-position="left">如何新增</el-divider>
<div>按住鼠标拖拽左侧组件到中间画布中松开鼠标即可</div>
</el-tab-pane>
<el-tab-pane label="如何删除">
<el-divider content-position="left">页面删除</el-divider>
<div>
鼠标点中需要删除的节点点击左上角的删除图标
</div>
<el-divider content-position="left">通过代码删除</el-divider>
<pre>this.deleteNode(nodeId)</pre>
</el-tab-pane>
<el-tab-pane label="如何移动">
<el-divider content-position="left">如何移动</el-divider>
<div>鼠标移动到节点中当鼠标变为可拖拽的图标时按下鼠标移动到新的位置松开鼠标</div>
</el-tab-pane>
<el-tab-pane label="如何连线">
<el-divider content-position="left">如何连线</el-divider>
<div>鼠标移动到节点中左侧的图标上当鼠标变为+时按下鼠标移动到另一个节点中松开鼠标</div>
</el-tab-pane>
<el-tab-pane label="如何添加条件">
<el-divider content-position="left">如何添加条件</el-divider>
<div>点击画布中的连线在页面右侧会出现一个表单输入新的条件点击保存</div>
</el-tab-pane>
<el-tab-pane label="如何进行后端交互存储">
<el-divider content-position="left">如何进行后端交互存储</el-divider>
<div>参考: https://gitee.com/xiaoka2017/easy-flow-sdk</div>
</el-tab-pane>
</el-tabs>
</el-dialog>
</template>
<script>
export default {
data() {
return {
dialogVisible: false
}
},
components: {},
methods: {
init() {
this.dialogVisible = true
}
}
}
</script>
<style>
.flowHelp {
height: 80%;
}
</style>

View File

@ -0,0 +1,225 @@
/*画布容器*/
#efContainer {
position: relative;
overflow: scroll;
flex: 1;
}
/*顶部工具栏*/
.ef-tooltar {
padding-left: 10px;
box-sizing: border-box;
height: 42px;
line-height: 42px;
z-index: 3;
border-bottom: 1px solid #DADCE0;
}
.jtk-overlay {
cursor: pointer;
color: #4A4A4A;
}
/*节点菜单*/
.ef-node-pmenu {
cursor: pointer;
height: 32px;
line-height: 32px;
width: 225px;
display: block;
font-weight: bold;
color: #4A4A4A;
padding-left: 5px;
}
.ef-node-pmenu:hover {
background-color: #E0E0E0;
}
.ef-node-menu-li {
color: #565758;
width: 150px;
border: 1px dashed #E0E3E7;
margin: 5px 0 5px 0;
padding: 5px;
border-radius: 5px;
padding-left: 8px;
}
.ef-node-menu-li:hover {
/* 设置移动样式*/
cursor: move;
background-color: #F0F7FF;
border: 1px dashed #1879FF;
border-left: 4px solid #1879FF;
padding-left: 5px;
}
.ef-node-menu-ul {
list-style: none;
padding-left: 20px
}
/*节点的最外层容器*/
.ef-node-container {
position: absolute;
display: flex;
width: 170px;
height: 32px;
border: 1px solid #E0E3E7;
border-radius: 5px;
background-color: #fff;
}
.ef-node-container:hover {
/* 设置移动样式*/
cursor: move;
background-color: #F0F7FF;
/*box-shadow: #1879FF 0px 0px 12px 0px;*/
background-color: #F0F7FF;
border: 1px dashed #1879FF;
}
/*节点激活样式*/
.ef-node-active {
background-color: #F0F7FF;
/*box-shadow: #1879FF 0px 0px 12px 0px;*/
background-color: #F0F7FF;
border: 1px solid #1879FF;
}
/*节点左侧的竖线*/
.ef-node-left {
width: 4px;
background-color: #1879FF;
border-radius: 4px 0 0 4px;
}
/*节点左侧的图标*/
.ef-node-left-ico {
line-height: 32px;
margin-left: 8px;
}
.ef-node-left-ico:hover {
/* 设置拖拽的样式 */
cursor: crosshair;
}
/*节点显示的文字*/
.ef-node-text {
color: #565758;
font-size: 12px;
line-height: 32px;
margin-left: 8px;
width: 100px;
/* 设置超出宽度文本显示方式*/
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
text-align: center;
}
/*节点右侧的图标*/
.ef-node-right-ico {
line-height: 32px;
position: absolute;
right: 5px;
color: #84CF65;
cursor: default;
}
/*节点的几种状态样式*/
.el-node-state-success {
line-height: 32px;
position: absolute;
right: 5px;
color: #84CF65;
cursor: default;
}
.el-node-state-error {
line-height: 32px;
position: absolute;
right: 5px;
color: #F56C6C;
cursor: default;
}
.el-node-state-warning {
line-height: 32px;
position: absolute;
right: 5px;
color: #E6A23C;
cursor: default;
}
.el-node-state-running {
line-height: 32px;
position: absolute;
right: 5px;
color: #84CF65;
cursor: default;
}
/*node-form*/
.ef-node-form-header {
height: 32px;
border-top: 1px solid #dce3e8;
border-bottom: 1px solid #dce3e8;
background: #F1F3F4;
color: #000;
line-height: 32px;
padding-left: 12px;
font-size: 14px;
}
.ef-node-form-body {
margin-top: 10px;
padding-right: 10px;
padding-bottom: 20px;
}
/* 连线中的label 样式*/
.jtk-overlay.flowLabel:not(.aLabel) {
padding: 4px 10px;
background-color: white;
color: #565758 !important;
border: 1px solid #E0E3E7;
border-radius: 5px;
}
/* label 为空的样式 */
.emptyFlowLabel {
}
.ef-dot {
background-color: #1879FF;
border-radius: 10px;
}
.ef-dot-hover {
background-color: red;
}
.ef-rectangle {
background-color: #1879FF;
}
.ef-rectangle-hover {
background-color: red;
}
.ef-img {
}
.ef-img-hover {
}
.ef-drop-hover{
border: 1px dashed #1879FF;
}

View File

@ -0,0 +1,55 @@
<template>
<el-dialog
title="流程数据信息"
:visible.sync="dialogVisible"
width="70%"
>
<el-alert
title="使用说明"
type="warning"
description="以下流程信息可以被存储起来,方便下一次流程加载"
show-icon
close-text="知道了"
>
</el-alert>
<br/>
<!--一个高亮显示的插件-->
<codemirror
:value="flowJsonData"
:options="options"
class="code"
></codemirror>
</el-dialog>
</template>
<script>
import 'codemirror/lib/codemirror.css';
import { codemirror } from 'vue-codemirror';
//codemirror/mode/javascript/javascript.js
require("codemirror/mode/javascript/javascript.js")
export default {
props: {
data: Object,
},
data() {
return {
dialogVisible: false,
flowJsonData: {},
options: {
mode: {name: "javascript", json: true},
lineNumbers: true
}
}
},
components: {
codemirror
},
methods: {
init() {
this.dialogVisible = true
this.flowJsonData = JSON.stringify(this.data, null, 4).toString()
}
}
}
</script>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,157 @@
export const easyFlowMixin = {
data() {
return {
jsplumbSetting: {
// 动态锚点、位置自适应
Anchors: ['Top', 'TopCenter', 'TopRight', 'TopLeft', 'Right', 'RightMiddle', 'Bottom', 'BottomCenter', 'BottomRight', 'BottomLeft', 'Left', 'LeftMiddle'],
// 容器ID
Container: 'efContainer',
// 连线的样式,直线或者曲线等,可选值: StateMachine、FlowchartBezier、Straight
Connector: ['Bezier', {curviness: 100}],
// Connector: ['Straight', {stub: 20, gap: 1}],
// Connector: ['Flowchart', {stub: 30, gap: 1, alwaysRespectStubs: false, midpoint: 0.5, cornerRadius: 10}],
// Connector: ['StateMachine', {margin: 5, curviness: 10, proximityLimit: 80}],
// 鼠标不能拖动删除线
ConnectionsDetachable: false,
// 删除线的时候节点不删除
DeleteEndpointsOnDetach: false,
/**
* 连线的两端端点类型圆形
* radius: 圆的半径越大圆越大
*/
// Endpoint: ['Dot', {radius: 5, cssClass: 'ef-dot', hoverClass: 'ef-dot-hover'}],
/**
* 连线的两端端点类型矩形
* height: 矩形的高
* width: 矩形的宽
*/
// Endpoint: ['Rectangle', {height: 20, width: 20, cssClass: 'ef-rectangle', hoverClass: 'ef-rectangle-hover'}],
/**
* 图像端点
*/
// Endpoint: ['Image', {src: 'https://www.easyicon.net/api/resizeApi.php?id=1181776&size=32', cssClass: 'ef-img', hoverClass: 'ef-img-hover'}],
/**
* 空白端点
*/
Endpoint: ['Blank', {Overlays: ''}],
// Endpoints: [['Dot', {radius: 5, cssClass: 'ef-dot', hoverClass: 'ef-dot-hover'}], ['Rectangle', {height: 20, width: 20, cssClass: 'ef-rectangle', hoverClass: 'ef-rectangle-hover'}]],
/**
* 连线的两端端点样式
* fill: 颜色值#12aabb为空不显示
* outlineWidth: 外边线宽度
*/
EndpointStyle: {fill: '#1879ffa1', outlineWidth: 1},
// 是否打开jsPlumb的内部日志记录
LogEnabled: true,
/**
* 连线的样式
*/
PaintStyle: {
// 线的颜色
stroke: '#E0E3E7',
// 线的粗细,值越大线越粗
strokeWidth: 1,
// 设置外边线的颜色,默认设置透明,这样别人就看不见了,点击线的时候可以不用精确点击,参考 https://blog.csdn.net/roymno2/article/details/72717101
outlineStroke: 'transparent',
// 线外边的宽,值越大,线的点击范围越大
outlineWidth: 10
},
DragOptions: {cursor: 'pointer', zIndex: 2000},
/**
* 叠加 参考 https://www.jianshu.com/p/d9e9918fd928
*/
Overlays: [
// 箭头叠加
['Arrow', {
width: 10, // 箭头尾部的宽度
length: 8, // 从箭头的尾部到头部的距离
location: 1, // 位置建议使用01之间
direction: 1, // 方向默认值为1表示向前可选-1表示向后
foldback: 0.623 // 折回也就是尾翼的角度默认0.623当为1时为正三角
}],
// ['Diamond', {
// events: {
// dblclick: function (diamondOverlay, originalEvent) {
// console.log('double click on diamond overlay for : ' + diamondOverlay.component)
// }
// }
// }],
['Label', {
label: '',
location: 0.1,
cssClass: 'aLabel'
}]
],
// 绘制图的模式 svg、canvas
RenderMode: 'svg',
// 鼠标滑过线的样式
HoverPaintStyle: {stroke: '#b0b2b5', strokeWidth: 1},
// 滑过锚点效果
// EndpointHoverStyle: {fill: 'red'}
Scope: 'jsPlumb_DefaultScope' // 范围具有相同scope的点才可连接
},
/**
* 连线参数
*/
jsplumbConnectOptions: {
isSource: true,
isTarget: true,
// 动态锚点、提供了4个方向 Continuous、AutoDefault
anchor: 'Continuous',
// 设置连线上面的label样式
labelStyle: {
cssClass: 'flowLabel'
},
// 修改了jsplumb 源码支持label 为空传入自定义style
emptyLabelStyle: {
cssClass: 'emptyFlowLabel'
}
},
/**
* 源点配置参数
*/
jsplumbSourceOptions: {
// 设置可以拖拽的类名只要鼠标移动到该类名上的DOM就可以拖拽连线
filter: '.flow-node-drag',
filterExclude: false,
anchor: 'Continuous',
// 是否允许自己连接自己
allowLoopback: true,
maxConnections: -1,
onMaxConnections: function (info, e) {
console.log(`超过了最大值连线: ${info.maxConnections}`)
}
},
// 参考 https://www.cnblogs.com/mq0036/p/7942139.html
jsplumbSourceOptions2: {
// 设置可以拖拽的类名只要鼠标移动到该类名上的DOM就可以拖拽连线
filter: '.flow-node-drag',
filterExclude: false,
// anchor: 'Continuous',
// 是否允许自己连接自己
allowLoopback: true,
connector: ['Flowchart', {curviness: 50}],
connectorStyle: {
// 线的颜色
stroke: 'red',
// 线的粗细,值越大线越粗
strokeWidth: 1,
// 设置外边线的颜色,默认设置透明,这样别人就看不见了,点击线的时候可以不用精确点击,参考 https://blog.csdn.net/roymno2/article/details/72717101
outlineStroke: 'transparent',
// 线外边的宽,值越大,线的点击范围越大
outlineWidth: 10
},
connectorHoverStyle: {stroke: 'red', strokeWidth: 2}
},
jsplumbTargetOptions: {
// 设置可以拖拽的类名只要鼠标移动到该类名上的DOM就可以拖拽连线
filter: '.flow-node-drag',
filterExclude: false,
// 是否允许自己连接自己
anchor: 'Continuous',
allowLoopback: true,
dropOptions: {hoverClass: 'ef-drop-hover'}
}
}
}
}

View File

@ -0,0 +1,79 @@
<template>
<div
ref="node"
:style="nodeContainerStyle"
@click="clickNode"
@mouseup="changeNodeSite"
:class="nodeContainerClass"
>
<!-- 最左侧的那条竖线 -->
<div class="ef-node-left"></div>
<!-- 节点类型的图标 -->
<div class="ef-node-left-ico flow-node-drag">
<i :class="nodeIcoClass"></i>
</div>
<!-- 节点名称 -->
<div class="ef-node-text" :show-overflow-tooltip="true">
{{node.name}}
</div>
<!-- 节点状态图标 -->
<div class="ef-node-right-ico">
<i class="el-icon-circle-check el-node-state-success" v-show="node.state === 'success'"></i>
<i class="el-icon-circle-close el-node-state-error" v-show="node.state === 'error'"></i>
<i class="el-icon-warning-outline el-node-state-warning" v-show="node.state === 'warning'"></i>
<i class="el-icon-loading el-node-state-running" v-show="node.state === 'running'"></i>
</div>
</div>
</template>
<script>
export default {
props: {
node: Object,
activeElement: Object
},
data() {
return {}
},
computed: {
nodeContainerClass() {
return {
'ef-node-container': true,
'ef-node-active': this.activeElement.type == 'node' ? this.activeElement.nodeId === this.node.id : false
}
},
//
nodeContainerStyle() {
return {
top: this.node.top,
left: this.node.left
}
},
nodeIcoClass() {
var nodeIcoClass = {}
nodeIcoClass[this.node.ico] = true
// class线viewOnly
nodeIcoClass['flow-node-drag'] = this.node.viewOnly ? false : true
return nodeIcoClass
}
},
methods: {
//
clickNode() {
this.$emit('clickNode', this.node.id)
},
//
changeNodeSite() {
//
if (this.node.left == this.$refs.node.style.left && this.node.top == this.$refs.node.style.top) {
return;
}
this.$emit('changeNodeSite', {
nodeId: this.node.id,
left: this.$refs.node.style.left,
top: this.$refs.node.style.top,
})
}
}
}
</script>

View File

@ -0,0 +1,134 @@
<template>
<div>
<div class="ef-node-form">
<div class="ef-node-form-header">
编辑
</div>
<div class="ef-node-form-body">
<el-form :model="node" ref="dataForm" label-width="80px" v-show="type === 'node'">
<el-form-item label="类型">
<el-input v-model="node.type" :disabled="true"></el-input>
</el-form-item>
<el-form-item label="名称">
<el-input v-model="node.name"></el-input>
</el-form-item>
<el-form-item label="left坐标">
<el-input v-model="node.left" :disabled="true"></el-input>
</el-form-item>
<el-form-item label="top坐标">
<el-input v-model="node.top" :disabled="true"></el-input>
</el-form-item>
<el-form-item label="ico图标">
<el-input v-model="node.ico"></el-input>
</el-form-item>
<el-form-item label="状态">
<el-select v-model="node.state" placeholder="请选择">
<el-option
v-for="item in stateList"
:key="item.state"
:label="item.label"
:value="item.state">
</el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button icon="el-icon-close">重置</el-button>
<el-button type="primary" icon="el-icon-check" @click="save"></el-button>
</el-form-item>
</el-form>
<el-form :model="line" ref="dataForm" label-width="80px" v-show="type === 'line'">
<el-form-item label="条件">
<el-input v-model="line.label"></el-input>
</el-form-item>
<el-form-item>
<el-button icon="el-icon-close">重置</el-button>
<el-button type="primary" icon="el-icon-check" @click="saveLine"></el-button>
</el-form-item>
</el-form>
</div>
<!-- <div class="el-node-form-tag"></div>-->
</div>
</div>
</template>
<script>
import { cloneDeep } from 'lodash'
export default {
data() {
return {
visible: true,
// node line
type: 'node',
node: {},
line: {},
data: {},
stateList: [{
state: 'success',
label: '成功'
}, {
state: 'warning',
label: '警告'
}, {
state: 'error',
label: '错误'
}, {
state: 'running',
label: '运行中'
}]
}
},
methods: {
/**
* 表单修改这里可以根据传入的ID进行业务信息获取
* @param data
* @param id
*/
nodeInit(data, id) {
this.type = 'node'
this.data = data
data.nodeList.filter((node) => {
if (node.id === id) {
this.node = cloneDeep(node)
}
})
},
lineInit(line) {
this.type = 'line'
this.line = line
},
// 线
saveLine() {
this.$emit('setLineLabel', this.line.from, this.line.to, this.line.label)
},
save() {
this.data.nodeList.filter((node) => {
if (node.id === this.node.id) {
node.name = this.node.name
node.left = this.node.left
node.top = this.node.top
node.ico = this.node.ico
node.state = this.node.state
this.$emit('repaintEverything')
}
})
}
}
}
</script>
<style>
.el-node-form-tag {
position: absolute;
top: 50%;
margin-left: -15px;
height: 40px;
width: 15px;
background-color: #fbfbfb;
border: 1px solid rgb(220, 227, 232);
border-right: none;
z-index: 0;
}
</style>

View File

@ -0,0 +1,142 @@
<template>
<div class="flow-menu" ref="tool">
<div v-for="menu in menuList" :key="menu.id">
<span class="ef-node-pmenu" @click="menu.open = !menu.open"><i :class="{'el-icon-caret-bottom': menu.open,'el-icon-caret-right': !menu.open}"></i>&nbsp;{{menu.name}}</span>
<ul v-show="menu.open" class="ef-node-menu-ul">
<draggable @end="end" @start="move" v-model="menu.children" :options="draggableOptions">
<li v-for="subMenu in menu.children" class="ef-node-menu-li" :key="subMenu.id" :type="subMenu.type">
<i :class="subMenu.ico"></i> {{subMenu.name}}
</li>
</draggable>
</ul>
</div>
</div>
</template>
<script>
import draggable from 'vuedraggable'
var mousePosition = {
left: -1,
top: -1
}
export default {
data() {
return {
activeNames: '1',
// draggable https://www.cnblogs.com/weixin186/p/10108679.html
draggableOptions: {
preventOnFilter: false,
sort: false,
disabled: false,
ghostClass: 'tt',
// 使H5
forceFallback: true,
//
// fallbackClass: 'flow-node-draggable'
},
// id
defaultOpeneds: ['1', '2'],
menuList: [
{
id: '1',
type: 'group',
name: '开始节点',
ico: 'el-icon-video-play',
open: true,
children: [
{
id: '11',
type: 'timer',
name: '数据接入',
ico: 'el-icon-time',
//
style: {}
}, {
id: '12',
type: 'task',
name: '接口调用',
ico: 'el-icon-odometer',
//
style: {}
}
]
},
{
id: '2',
type: 'group',
name: '结束节点',
ico: 'el-icon-video-pause',
open: true,
children: [
{
id: '21',
type: 'end',
name: '流程结束',
ico: 'el-icon-caret-right',
//
style: {}
}, {
id: '22',
type: 'over',
name: '数据清理',
ico: 'el-icon-shopping-cart-full',
//
style: {}
}
]
}
],
nodeMenu: {}
}
},
components: {
draggable
},
created() {
/**
* 以下是为了解决在火狐浏览器上推拽时弹出tab页到搜索问题
* @param event
*/
if (this.isFirefox()) {
document.body.ondrop = function (event) {
//
mousePosition.left = event.layerX
mousePosition.top = event.clientY - 50
event.preventDefault();
event.stopPropagation();
}
}
},
methods: {
//
getMenuByType(type) {
for (let i = 0; i < this.menuList.length; i++) {
let children = this.menuList[i].children;
for (let j = 0; j < children.length; j++) {
if (children[j].type === type) {
return children[j]
}
}
}
},
//
move(evt, a, b, c) {
var type = evt.item.attributes.type.nodeValue
this.nodeMenu = this.getMenuByType(type)
},
//
end(evt, e) {
this.$emit('addNode', evt, this.nodeMenu, mousePosition)
},
//
isFirefox() {
var userAgent = navigator.userAgent
if (userAgent.indexOf("Firefox") > -1) {
return true
}
return false
}
}
}
</script>

View File

@ -0,0 +1,546 @@
<template>
<div v-if="easyFlowVisible" style="height: calc(100vh);">
<el-row>
<!--顶部工具菜单-->
<el-col :span="24">
<div class="ef-tooltar">
<el-link type="primary" :underline="false">{{data.name}}</el-link>
<el-divider direction="vertical"></el-divider>
<el-button type="text" icon="el-icon-delete" size="large" @click="deleteElement" :disabled="!this.activeElement.type"></el-button>
<el-divider direction="vertical"></el-divider>
<el-button type="text" icon="el-icon-download" size="large" @click="downloadData"></el-button>
<el-divider direction="vertical"></el-divider>
<el-button type="text" icon="el-icon-plus" size="large" @click="zoomAdd"></el-button>
<el-divider direction="vertical"></el-divider>
<el-button type="text" icon="el-icon-minus" size="large" @click="zoomSub"></el-button>
<div style="float: right;margin-right: 5px">
<el-button type="info" plain round icon="el-icon-document" @click="dataInfo" size="mini">流程信息</el-button>
<el-button type="primary" plain round @click="dataReloadA" icon="el-icon-refresh" size="mini">切换流程A</el-button>
<el-button type="primary" plain round @click="dataReloadB" icon="el-icon-refresh" size="mini">切换流程B</el-button>
<el-button type="primary" plain round @click="dataReloadC" icon="el-icon-refresh" size="mini">切换流程C</el-button>
<el-button type="primary" plain round @click="dataReloadD" icon="el-icon-refresh" size="mini">自定义样式</el-button>
<el-button type="primary" plain round @click="dataReloadE" icon="el-icon-refresh" size="mini">力导图</el-button>
<el-button type="info" plain round icon="el-icon-document" @click="openHelp" size="mini">帮助</el-button>
</div>
</div>
</el-col>
</el-row>
<div style="display: flex;height: calc(100% - 47px);">
<div style="width: 230px;border-right: 1px solid #dce3e8;">
<node-menu @addNode="addNode" ref="nodeMenu"></node-menu>
</div>
<div id="efContainer" ref="efContainer" class="container" v-flowDrag>
<template v-for="node in data.nodeList">
<flow-node
:id="node.id"
:key="node.id"
:node="node"
:activeElement="activeElement"
@changeNodeSite="changeNodeSite"
@nodeRightMenu="nodeRightMenu"
@clickNode="clickNode"
>
</flow-node>
</template>
<!-- 给画布一个默认的宽度和高度 -->
<div style="position:absolute;top: 2000px;left: 2000px;">&nbsp;</div>
</div>
<!-- 右侧表单 -->
<div style="width: 300px;border-left: 1px solid #dce3e8;background-color: #FBFBFB">
<flow-node-form ref="nodeForm" @setLineLabel="setLineLabel" @repaintEverything="repaintEverything"></flow-node-form>
</div>
</div>
<!-- 流程数据详情 -->
<flow-info v-if="flowInfoVisible" ref="flowInfo" :data="data"></flow-info>
<flow-help v-if="flowHelpVisible" ref="flowHelp"></flow-help>
</div>
</template>
<script>
import draggable from 'vuedraggable'
// import { jsPlumb } from 'jsplumb'
// 使jsplumb
import './jsplumb'
import { easyFlowMixin } from '@/components/ef/mixins'
import flowNode from '@/components/ef/node'
import nodeMenu from '@/components/ef/node_menu'
import FlowInfo from '@/components/ef/info'
import FlowHelp from '@/components/ef/help'
import FlowNodeForm from '@/components/ef/node_form'
import lodash from 'lodash'
import { getDataA } from './data_A'
import { getDataB } from './data_B'
import { getDataC } from './data_C'
import { getDataD } from './data_D'
import { getDataE } from './data_E'
import { ForceDirected } from './force-directed'
export default {
data() {
return {
// jsPlumb
jsPlumb: null,
//
easyFlowVisible: true,
//
flowInfoVisible: false,
//
loadEasyFlowFinish: false,
flowHelpVisible: false,
//
data: {},
// 线
activeElement: {
// node line
type: undefined,
// ID
nodeId: undefined,
// 线ID
sourceId: undefined,
targetId: undefined
},
zoom: 0.5
}
},
//
mixins: [easyFlowMixin],
components: {
draggable, flowNode, nodeMenu, FlowInfo, FlowNodeForm, FlowHelp
},
directives: {
'flowDrag': {
bind(el, binding, vnode, oldNode) {
if (!binding) {
return
}
el.onmousedown = (e) => {
if (e.button == 2) {
//
return
}
//
let disX = e.clientX
let disY = e.clientY
el.style.cursor = 'move'
document.onmousemove = function (e) {
//
e.preventDefault()
const left = e.clientX - disX
disX = e.clientX
el.scrollLeft += -left
const top = e.clientY - disY
disY = e.clientY
el.scrollTop += -top
}
document.onmouseup = function (e) {
el.style.cursor = 'auto'
document.onmousemove = null
document.onmouseup = null
}
}
}
}
},
mounted() {
this.jsPlumb = jsPlumb.getInstance()
this.$nextTick(() => {
// A
this.dataReload(getDataB())
})
},
methods: {
//
getUUID() {
return Math.random().toString(36).substr(3, 10)
},
jsPlumbInit() {
this.jsPlumb.ready(() => {
//
this.jsPlumb.importDefaults(this.jsplumbSetting)
// 使jsPlumb
this.jsPlumb.setSuspendDrawing(false, true);
//
this.loadEasyFlow()
// 线, https://www.cnblogs.com/ysx215/p/7615677.html
this.jsPlumb.bind('click', (conn, originalEvent) => {
this.activeElement.type = 'line'
this.activeElement.sourceId = conn.sourceId
this.activeElement.targetId = conn.targetId
this.$refs.nodeForm.lineInit({
from: conn.sourceId,
to: conn.targetId,
label: conn.getLabel()
})
})
// 线
this.jsPlumb.bind("connection", (evt) => {
let from = evt.source.id
let to = evt.target.id
if (this.loadEasyFlowFinish) {
this.data.lineList.push({from: from, to: to})
}
})
// 线
this.jsPlumb.bind("connectionDetached", (evt) => {
this.deleteLine(evt.sourceId, evt.targetId)
})
// 线
this.jsPlumb.bind("connectionMoved", (evt) => {
this.changeLine(evt.originalSourceId, evt.originalTargetId)
})
// 线
this.jsPlumb.bind("contextmenu", (evt) => {
console.log('contextmenu', evt)
})
// 线
this.jsPlumb.bind("beforeDrop", (evt) => {
let from = evt.sourceId
let to = evt.targetId
if (from === to) {
this.$message.error('节点不支持连接自己')
return false
}
if (this.hasLine(from, to)) {
this.$message.error('该关系已存在,不允许重复创建')
return false
}
if (this.hashOppositeLine(from, to)) {
this.$message.error('不支持两个节点之间连线回环');
return false
}
this.$message.success('连接成功')
return true
})
// beforeDetach
this.jsPlumb.bind("beforeDetach", (evt) => {
console.log('beforeDetach', evt)
})
this.jsPlumb.setContainer(this.$refs.efContainer)
})
},
//
loadEasyFlow() {
//
for (var i = 0; i < this.data.nodeList.length; i++) {
let node = this.data.nodeList[i]
// 线
this.jsPlumb.makeSource(node.id, lodash.merge(this.jsplumbSourceOptions, {}))
// // 线
this.jsPlumb.makeTarget(node.id, this.jsplumbTargetOptions)
if (!node.viewOnly) {
this.jsPlumb.draggable(node.id, {
containment: 'parent',
stop: function (el) {
//
console.log('拖拽结束: ', el)
}
})
}
}
// 线
for (var i = 0; i < this.data.lineList.length; i++) {
let line = this.data.lineList[i]
var connParam = {
source: line.from,
target: line.to,
label: line.label ? line.label : '',
connector: line.connector ? line.connector : '',
anchors: line.anchors ? line.anchors : undefined,
paintStyle: line.paintStyle ? line.paintStyle : undefined,
}
this.jsPlumb.connect(connParam, this.jsplumbConnectOptions)
}
this.$nextTick(function () {
this.loadEasyFlowFinish = true
})
},
// 线
setLineLabel(from, to, label) {
var conn = this.jsPlumb.getConnections({
source: from,
target: to
})[0]
if (!label || label === '') {
conn.removeClass('flowLabel')
conn.addClass('emptyFlowLabel')
} else {
conn.addClass('flowLabel')
}
conn.setLabel({
label: label,
})
this.data.lineList.forEach(function (line) {
if (line.from == from && line.to == to) {
line.label = label
}
})
},
//
deleteElement() {
if (this.activeElement.type === 'node') {
this.deleteNode(this.activeElement.nodeId)
} else if (this.activeElement.type === 'line') {
this.$confirm('确定删除所点击的线吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
var conn = this.jsPlumb.getConnections({
source: this.activeElement.sourceId,
target: this.activeElement.targetId
})[0]
this.jsPlumb.deleteConnection(conn)
}).catch(() => {
})
}
},
// 线
deleteLine(from, to) {
this.data.lineList = this.data.lineList.filter(function (line) {
if (line.from == from && line.to == to) {
return false
}
return true
})
},
// 线
changeLine(oldFrom, oldTo) {
this.deleteLine(oldFrom, oldTo)
},
//
changeNodeSite(data) {
for (var i = 0; i < this.data.nodeList.length; i++) {
let node = this.data.nodeList[i]
if (node.id === data.nodeId) {
node.left = data.left
node.top = data.top
}
}
},
/**
* 拖拽结束后添加新的节点
* @param evt
* @param nodeMenu 被添加的节点对象
* @param mousePosition 鼠标拖拽结束的坐标
*/
addNode(evt, nodeMenu, mousePosition) {
var screenX = evt.originalEvent.clientX, screenY = evt.originalEvent.clientY
let efContainer = this.$refs.efContainer
var containerRect = efContainer.getBoundingClientRect()
var left = screenX, top = screenY
//
if (left < containerRect.x || left > containerRect.width + containerRect.x || top < containerRect.y || containerRect.y > containerRect.y + containerRect.height) {
this.$message.error("请把节点拖入到画布中")
return
}
left = left - containerRect.x + efContainer.scrollLeft
top = top - containerRect.y + efContainer.scrollTop
//
left -= 85
top -= 16
var nodeId = this.getUUID()
//
var origName = nodeMenu.name
var nodeName = origName
var index = 1
while (index < 10000) {
var repeat = false
for (var i = 0; i < this.data.nodeList.length; i++) {
let node = this.data.nodeList[i]
if (node.name === nodeName) {
nodeName = origName + index
repeat = true
}
}
if (repeat) {
index++
continue
}
break
}
var node = {
id: nodeId,
name: nodeName,
type: nodeMenu.type,
left: left + 'px',
top: top + 'px',
ico: nodeMenu.ico,
state: 'success'
}
/**
* 这里可以进行业务判断是否能够添加该节点
*/
this.data.nodeList.push(node)
this.$nextTick(function () {
this.jsPlumb.makeSource(nodeId, this.jsplumbSourceOptions)
this.jsPlumb.makeTarget(nodeId, this.jsplumbTargetOptions)
this.jsPlumb.draggable(nodeId, {
containment: 'parent',
stop: function (el) {
//
console.log('拖拽结束: ', el)
}
})
})
},
/**
* 删除节点
* @param nodeId 被删除节点的ID
*/
deleteNode(nodeId) {
this.$confirm('确定要删除节点' + nodeId + '?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
closeOnClickModal: false
}).then(() => {
/**
* 这里需要进行业务判断是否可以删除
*/
this.data.nodeList = this.data.nodeList.filter(function (node) {
if (node.id === nodeId) {
//
// node.show = false
return false
}
return true
})
this.$nextTick(function () {
this.jsPlumb.removeAllEndpoints(nodeId);
})
}).catch(() => {
})
return true
},
clickNode(nodeId) {
this.activeElement.type = 'node'
this.activeElement.nodeId = nodeId
this.$refs.nodeForm.nodeInit(this.data, nodeId)
},
// 线
hasLine(from, to) {
for (var i = 0; i < this.data.lineList.length; i++) {
var line = this.data.lineList[i]
if (line.from === from && line.to === to) {
return true
}
}
return false
},
// 线
hashOppositeLine(from, to) {
return this.hasLine(to, from)
},
nodeRightMenu(nodeId, evt) {
this.menu.show = true
this.menu.curNodeId = nodeId
this.menu.left = evt.x + 'px'
this.menu.top = evt.y + 'px'
},
repaintEverything() {
this.jsPlumb.repaint()
},
//
dataInfo() {
this.flowInfoVisible = true
this.$nextTick(function () {
this.$refs.flowInfo.init()
})
},
//
dataReload(data) {
this.easyFlowVisible = false
this.data.nodeList = []
this.data.lineList = []
this.$nextTick(() => {
data = lodash.cloneDeep(data)
this.easyFlowVisible = true
this.data = data
this.$nextTick(() => {
this.jsPlumb = jsPlumb.getInstance()
this.$nextTick(() => {
this.jsPlumbInit()
})
})
})
},
// dataA
dataReloadA() {
this.dataReload(getDataA())
},
// dataB
dataReloadB() {
this.dataReload(getDataB())
},
// dataC
dataReloadC() {
this.dataReload(getDataC())
},
// dataD
dataReloadD() {
this.dataReload(getDataD())
},
// dataE
dataReloadE() {
let dataE = getDataE()
let tempData = lodash.cloneDeep(dataE)
let data = ForceDirected(tempData)
this.dataReload(data)
this.$message({
message: '力导图每次产生的布局是不一样的',
type: 'warning'
});
},
zoomAdd() {
if (this.zoom >= 1) {
return
}
this.zoom = this.zoom + 0.1
this.$refs.efContainer.style.transform = `scale(${this.zoom})`
this.jsPlumb.setZoom(this.zoom)
},
zoomSub() {
if (this.zoom <= 0) {
return
}
this.zoom = this.zoom - 0.1
this.$refs.efContainer.style.transform = `scale(${this.zoom})`
this.jsPlumb.setZoom(this.zoom)
},
//
downloadData() {
this.$confirm('确定要下载该流程数据吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
closeOnClickModal: false
}).then(() => {
var datastr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(this.data, null, '\t'));
var downloadAnchorNode = document.createElement('a')
downloadAnchorNode.setAttribute("href", datastr);
downloadAnchorNode.setAttribute("download", 'data.json')
downloadAnchorNode.click();
downloadAnchorNode.remove();
this.$message.success("正在下载中,请稍后...")
}).catch(() => {
})
},
openHelp() {
this.flowHelpVisible = true
this.$nextTick(function () {
this.$refs.flowHelp.init()
})
}
}
}
</script>

View File

@ -0,0 +1,29 @@
// 是否具有该线
export function hasLine(data, from, to) {
for (let i = 0; i < data.lineList.length; i++) {
let line = data.lineList[i]
if (line.from === from && line.to === to) {
return true
}
}
return false
}
// 是否含有相反的线
export function hashOppositeLine(data, from, to) {
return hasLine(data, to, from)
}
// 获取连线
export function getConnector(jsp, from, to) {
let connection = jsp.getConnections({
source: from,
target: to
})[0]
return connection
}
// 获取唯一标识
export function uuid() {
return Math.random().toString(36).substr(3, 10)
}

View File

@ -6,7 +6,12 @@
<breadcrumb v-if="!topNav" id="breadcrumb-container" class="breadcrumb-container"/> <breadcrumb v-if="!topNav" id="breadcrumb-container" class="breadcrumb-container"/>
<top-nav v-if="topNav" id="topmenu-container" class="topmenu-container"/> <top-nav v-if="topNav" id="topmenu-container" class="topmenu-container"/>
<div class="right-menu"> <div class="right-menu">
<el-button @click="drawerTru" type="primary" style="margin: 10px 0;">
<i class="el-icon-s-comment"></i>
</el-button>
<template v-if="device!=='mobile'"> <template v-if="device!=='mobile'">
<search id="header-search" class="right-menu-item"/> <search id="header-search" class="right-menu-item"/>
<screenfull id="screenfull" class="right-menu-item hover-effect"/> <screenfull id="screenfull" class="right-menu-item hover-effect"/>
@ -34,7 +39,119 @@
</el-dropdown-item> </el-dropdown-item>
</el-dropdown-menu> </el-dropdown-menu>
</el-dropdown> </el-dropdown>
</div> </div>
<div>
<!-- <el-drawer-->
<!-- title="我是标题"-->
<!-- :visible.sync="drawer"-->
<!-- size="50%"-->
<!-- :with-header="false">-->
<!-- <el-radio-group v-model="type" @change="selectNotice">-->
<!-- <el-radio-button label="0" >全部</el-radio-button>-->
<!-- <el-radio-button label="1" >通知</el-radio-button>-->
<!-- <el-radio-button label="2" >公告</el-radio-button>-->
<!-- </el-radio-group>-->
<!-- <br>-->
<!-- <el-radio-group v-model="state" @change="selectNotice">-->
<!-- <el-radio-button label="0" >全部</el-radio-button>-->
<!-- <el-radio-button label="2">已读</el-radio-button>-->
<!-- <el-radio-button label="1">未读</el-radio-button>-->
<!-- </el-radio-group>-->
<!-- <el-descriptions class="margin-top" v-for="notice in notices" :column="2" border>-->
<!-- <template slot="extra">-->
<!-- <el-button type="primary" size="small" @click="lookNotice(notice)"></el-button>-->
<!-- </template>-->
<!-- <el-descriptions-item>-->
<!-- <template slot="label">-->
<!-- <i class="el-icon-user"></i>-->
<!-- 消息发布时间-->
<!-- </template>-->
<!-- {{ notice.noticeTitle }}-->
<!-- </el-descriptions-item>-->
<!-- <el-descriptions-item>-->
<!-- <template slot="label">-->
<!-- <i class="el-icon-mobile-phone"></i>-->
<!-- 消息发布人-->
<!-- </template>-->
<!-- {{notice.createBy}}-->
<!-- </el-descriptions-item>-->
<!-- <el-descriptions-item>-->
<!-- <template slot="label">-->
<!-- <i class="el-icon-location-outline"></i>-->
<!-- 消息类型-->
<!-- </template>-->
<!-- <el-tag size="small" v-if=" notice.noticeType == 1"></el-tag>-->
<!-- <el-tag size="warning" v-if=" notice.noticeType == 2"></el-tag>-->
<!-- </el-descriptions-item>-->
<!-- <el-descriptions-item>-->
<!-- <template slot="label">-->
<!-- <i class="el-icon-tickets"></i>-->
<!-- 当前状态-->
<!-- </template>-->
<!-- <el-tag size="small" v-if=" notice.state == 1"></el-tag>-->
<!-- <el-tag size="success" v-if=" notice.state == 2"></el-tag>-->
<!-- </el-descriptions-item>-->
<!-- </el-descriptions>-->
<!-- </el-drawer>-->
<el-dialog
:visible.sync="dialogVisible"
width="30%">
<el-descriptions class="margin-top" :column="2" border>
<el-descriptions-item>
<template slot="label">
<i class="el-icon-user"></i>
消息发布时间
</template>
{{ notice.noticeTitle }}
</el-descriptions-item>
<el-descriptions-item>
<template slot="label">
<i class="el-icon-mobile-phone"></i>
消息发布人
</template>
{{notice.createBy}}
</el-descriptions-item>
<el-descriptions-item>
<template slot="label">
<i class="el-icon-location-outline"></i>
消息类型
</template>
<el-tag size="small" v-if=" notice.noticeType == 1"></el-tag>
<el-tag size="warning" v-if=" notice.noticeType == 2"></el-tag>
</el-descriptions-item>
<el-descriptions-item>
<template slot="label">
<i class="el-icon-tickets"></i>
当前状态
</template>
<el-tag size="small" v-if=" notice.state == 1"></el-tag>
<el-tag size="success" v-if=" notice.state == 2"></el-tag>
</el-descriptions-item>
<el-descriptions-item>
<template slot="label">
<i class="el-icon-tickets"></i>
内容
</template>
<span v-html="notice.noticeContent"></span>
</el-descriptions-item>
</el-descriptions>
</el-dialog>
</div>
</div> </div>
</template> </template>
@ -46,8 +163,19 @@ import Hamburger from '@/components/Hamburger'
import Screenfull from '@/components/Screenfull' import Screenfull from '@/components/Screenfull'
import SizeSelect from '@/components/SizeSelect' import SizeSelect from '@/components/SizeSelect'
import Search from '@/components/HeaderSearch' import Search from '@/components/HeaderSearch'
import {findList, lookNotice} from "@/api/system/notice";
export default { export default {
data(){
return{
drawer:false,
type:0,
state:0,
notices:[],
dialogVisible:false,
notice:{}
}
},
components: { components: {
Breadcrumb, Breadcrumb,
TopNav, TopNav,
@ -63,6 +191,7 @@ export default {
'device' 'device'
]), ]),
setting: { setting: {
get() { get() {
return this.$store.state.settings.showSettings return this.$store.state.settings.showSettings
}, },
@ -79,7 +208,28 @@ export default {
} }
} }
}, },
created() {
},
methods: { methods: {
lookNotice(notice) {
this.dialogVisible = true
lookNotice(notice.id, notice.state).then(res => {
this.notice = res.data
})
this.findAll();
},
drawerTru() {
this.drawer = true
this.findAll()
},
findAll() {
findList({ state: this.state, noticeType: this.type }).then(res => {
this.notices = res.data;
})
},
selectNotice() {
this.findAll();
},
toggleSideBar() { toggleSideBar() {
this.$store.dispatch('app/toggleSideBar') this.$store.dispatch('app/toggleSideBar')
}, },
@ -136,7 +286,7 @@ export default {
.right-menu { .right-menu {
float: right; float: right;
height: 100%; height: 70%;
line-height: 50px; line-height: 50px;
&:focus { &:focus {

View File

@ -37,6 +37,9 @@ import DictTag from '@/components/DictTag'
import VueMeta from 'vue-meta' import VueMeta from 'vue-meta'
// 字典数据组件 // 字典数据组件
import DictData from '@/components/DictData' import DictData from '@/components/DictData'
import 'element-ui/lib/theme-chalk/index.css'
import '@/components/ef/index.css'
// 全局方法挂载 // 全局方法挂载
Vue.prototype.getDicts = getDicts Vue.prototype.getDicts = getDicts
@ -57,7 +60,6 @@ Vue.component('Editor', Editor)
Vue.component('FileUpload', FileUpload) Vue.component('FileUpload', FileUpload)
Vue.component('ImageUpload', ImageUpload) Vue.component('ImageUpload', ImageUpload)
Vue.component('ImagePreview', ImagePreview) Vue.component('ImagePreview', ImagePreview)
Vue.use(directive) Vue.use(directive)
Vue.use(plugins) Vue.use(plugins)
Vue.use(VueMeta) Vue.use(VueMeta)

View File

@ -40,6 +40,19 @@ export const constantRoutes = [
} }
] ]
}, },
{
path: '/easyFlow',// 这里的/serviceUse就是父级路由
component: Layout,
hidden: true,
children: [// 父级路由下面还有子路由
{
path: 'index/:id',// 这个index可以自己定义
component: () => import('@/views/task/task/easyFlow.vue'),
name: "easyFlow",
meta: { title: '设计', icon: 'dashboard', activeMenu: '/task/task' }
}
]
},
{ {
path: '/login', path: '/login',
component: () => import('@/views/login'), component: () => import('@/views/login'),
@ -86,7 +99,7 @@ export const constantRoutes = [
meta: {title: '个人中心', icon: 'user'} meta: {title: '个人中心', icon: 'user'}
} }
] ]
} },
] ]
// 动态路由,基于用户权限动态去加载 // 动态路由,基于用户权限动态去加载

View File

@ -0,0 +1,57 @@
<template>
<div>
<ef>
</ef>
</div>
</template>
<script>
//jsjsjson,
//import from ',
import ef from "@/components/ef/panel.vue"
export default {
name: "easyFlow",
//import使"
components: {
ef
},
props: {},
data() {
//"
return {
};
},
// data",
computed: {},
//data",
watch: {},
//",
methods: {},
// - 访this",
created() {
},
// - 访DOM",
mounted() {
},
beforeCreate() {
}, // - ",
beforeMount() {
}, // - ",
beforeUpdate() {
}, // - ",
updated() {
}, // - ",
beforeDestroy() {
}, // - ",
destroyed() {
}, // - ",
activated() {
} //keep-alive",
};
</script>
<style scoped>
</style>

View File

@ -139,6 +139,12 @@
type="text" type="text"
@click="executeTask(scope.row)">执行</el-button> @click="executeTask(scope.row)">执行</el-button>
<el-button
icon="el-icon-pear"
size="mini"
type="text"
@click="toDesign(scope.row)">任务设计</el-button>
<el-button <el-button
icon="el-icon-delete" icon="el-icon-delete"
size="mini" size="mini"
@ -187,30 +193,30 @@
<!-- 添加任务详情设计--> <!-- 添加任务详情设计-->
<el-dialog title="添加表" :visible.sync="taskInputAdd"> <el-dialog title="添加表" :visible.sync="taskInputAdd">
<el-form label-width="80px" :model="taskInput" ref="queryForm" :inline="true" class="demo-form-inline" size="small"> <el-form label-width="80px" :model="tableInfo" ref="queryForm" :inline="true" class="demo-form-inline" size="small">
<el-form-item label="任务id"> <el-form-item label="任务id">
<el-input v-model="taskInput.taskId"></el-input> <el-input v-model="tableInfo.id"></el-input>
</el-form-item> </el-form-item>
<el-form-item label="数据库id"> <!-- <el-form-item label="数据库id">-->
<el-input v-model="taskInput.databaseId"></el-input> <!-- <el-input v-model="tableInfo.databaseId"></el-input>-->
</el-form-item> <!-- </el-form-item>-->
<el-form-item label="数据表"> <el-form-item label="数据表">
<el-select @change="changeTableName(taskInput.tableName)" v-model="taskInput.tableName" placeholder="请选择等级"> <el-select @change="changeTableName(tableInfo.tableName)" v-model="tableInfo.tableName" placeholder="请选择等级">
<el-option label="请选择" value="0"></el-option> <el-option label="请选择" value="0"></el-option>
<span v-for="table in taskInfoList"> <span v-for="table in tableList">
<el-option :label=table.tableName :value=table.id :key=table.id></el-option> <el-option :label=table.tableName :value=table.id :key=table.id></el-option>
</span> </span>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="表别名"> <el-form-item label="表别名">
<el-input v-model="taskInput.tableAsName"></el-input> <el-input v-model="tableInfo.tableRemark"></el-input>
</el-form-item> </el-form-item>
</el-form> </el-form>
<div slot="footer" class="dialog-footer"> <div slot="footer" class="dialog-footer">
<el-button @click="taskInputAdd = false"> </el-button> <el-button @click="taskInputAdd = false"> </el-button>
<el-button type="primary" @click="addTaskInput(taskInput)"></el-button> <el-button type="primary" @click="addTaskInput(tableInfo.id)"></el-button>
</div> </div>
@ -237,25 +243,7 @@
width="180"> width="180">
<template slot-scope="scope"> <template slot-scope="scope">
<i class="el-icon-time"></i> <i class="el-icon-time"></i>
<span style="margin-left: 10px">{{ scope.row.id }}</span> <span style="margin-left: 10px">{{ scope.row.columnName }}</span>
</template>
</el-table-column>
<el-table-column
label="类型/长度"
width="180">
<template slot-scope="scope">
<i class="el-icon-time"></i>
<span style="margin-left: 10px">{{ scope.row.name }}</span>
</template>
</el-table-column>
<el-table-column
label="非空"
width="180">
<template slot-scope="scope">
<i class="el-icon-time"></i>
<span style="margin-left: 10px">{{ scope.row.name }}</span>
</template> </template>
</el-table-column> </el-table-column>
@ -264,28 +252,91 @@
width="180"> width="180">
<template slot-scope="scope"> <template slot-scope="scope">
<i class="el-icon-time"></i> <i class="el-icon-time"></i>
<span style="margin-left: 10px">{{ scope.row.name }}</span> <span style="margin-left: 10px">{{ scope.row.columnRemark }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
label="处理规则" label="是否主键"
width="180"> width="180">
<template slot-scope="scope"> <template slot-scope="scope">
<span style="margin-left: 10px" v-if="scope.row.weigh ==1 "></span> <i class="el-icon-time"></i>
<span style="margin-left: 10px" v-if="scope.row.weigh ==2 ">aa</span> <span style="margin-left: 10px">{{ scope.row.isPrimary }}</span>
<span style="margin-left: 10px" v-if="scope.row.weigh ==3 "></span>
<span style="margin-left: 10px" v-if="scope.row.weigh ==4 "></span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
label="表别名" label="字段类型"
width="180"> width="180">
<template slot-scope="scope"> <template slot-scope="scope">
<el-input v-model="scope.row.fieldAsEngineId"></el-input> <i class="el-icon-time"></i>
<span style="margin-left: 10px">{{ scope.row.columnType }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column
label="字段长度"
width="180">
<template slot-scope="scope">
<i class="el-icon-time"></i>
<span style="margin-left: 10px">{{ scope.row.columnLength }}</span>
</template>
</el-table-column>
<el-table-column
label="小数"
width="180">
<template slot-scope="scope">
<i class="el-icon-time"></i>
<span style="margin-left: 10px">{{ scope.row.columnDecimals }}</span>
</template>
</el-table-column>
<el-table-column
label="非空"
width="180">
<template slot-scope="scope">
<i class="el-icon-time"></i>
<span style="margin-left: 10px">{{ scope.row.isNull }}</span>
</template>
</el-table-column>
<el-table-column
label="默认值"
width="180">
<template slot-scope="scope">
<i class="el-icon-time"></i>
<span style="margin-left: 10px">{{ scope.row.defaultValue }}</span>
</template>
</el-table-column>
<el-table-column
label="是否字典"
width="180">
<template slot-scope="scope">
<i class="el-icon-time"></i>
<span style="margin-left: 10px">{{ scope.row.isDictionary }}</span>
</template>
</el-table-column>
<!-- <el-table-column-->
<!-- label="处理规则"-->
<!-- width="180">-->
<!-- <template slot-scope="scope">-->
<!-- <span style="margin-left: 10px" v-if="scope.row.weigh ==1 "></span>-->
<!-- <span style="margin-left: 10px" v-if="scope.row.weigh ==2 ">aa</span>-->
<!-- <span style="margin-left: 10px" v-if="scope.row.weigh ==3 "></span>-->
<!-- <span style="margin-left: 10px" v-if="scope.row.weigh ==4 "></span>-->
<!-- </template>-->
<!-- </el-table-column>-->
<!-- <el-table-column-->
<!-- label="表别名"-->
<!-- width="180">-->
<!-- <template slot-scope="scope">-->
<!-- <el-input v-model="scope.row.fieldAsEngineId"></el-input>-->
<!-- </template>-->
<!-- </el-table-column>-->
</el-table> </el-table>
@ -312,12 +363,8 @@ import {insertAdd} from "@/api/etl/switch";
import {getInfo} from "@/api/etl/switch"; import {getInfo} from "@/api/etl/switch";
import { import {
addTask, addTask,
deleteById, deleteByTaskId, findByTableId, findStructureList,
deleteByTaskId, selectTaskList, tableInfoList
findByInputId,
selectTaskList,
taskInputList,
updateById
} from '@/api/task/task' } from '@/api/task/task'
export default { export default {
@ -339,9 +386,8 @@ export default {
taskAddReq:{}, taskAddReq:{},
taskInputReq:{}, taskInputReq:{},
taskList:[], taskList:[],
taskInfoList:[],
taskInput:{},
tableList:[], tableList:[],
tableInfo:{},
structureList:[], structureList:[],
}; };
}, },
@ -351,38 +397,43 @@ export default {
watch: {}, watch: {},
//", //",
methods: { methods: {
//
toDesign(row){
this.$router.push({path:'/easyFlow'});
},
// //
changeTableName(row){ changeTableName(row){
alert(row) findByTableId(row).then(res=>{
findByInputId(row).then(res=>{ this.tableInfo = res.data;
this.taskInput = res.data;
}) })
}, },
// //
findByInputId(taskInfo){ findStructureList(tableId){
findByInputId(taskInfo.id).then(res=>{ findStructureList(tableId).then(res=>{
this.structureList = res.data; this.structureList = res.data;
}) })
}, },
// //
taskInputList(){ tableInfoList(){
taskInputList().then(res=>{ tableInfoList().then(res=>{
this.taskInfoList = res.data; this.tableList = res.data;
}); });
}, },
executeTask(){ executeTask(){
this.taskInputAdd = true; this.taskInputAdd = true;
this.taskInputList(); this.tableInfoList();
}, },
addTaskInput(taskInfo){ addTaskInput(taskInfo){
this.taskInputAdd = false; this.taskInputAdd = false;
this.findByInputId(taskInfo); this.findStructureList(taskInfo);
this.taskInputFieldAdd = true; this.taskInputFieldAdd = true;
}, },

View File

@ -37,7 +37,7 @@ module.exports = {
proxy: { proxy: {
// detail: https://cli.vuejs.org/config/#devserver-proxy // detail: https://cli.vuejs.org/config/#devserver-proxy
[process.env.VUE_APP_BASE_API]: { [process.env.VUE_APP_BASE_API]: {
target: `http://172.13.1.1/prod-api`, target: `http://172.13.1.1/prod-api/`,
// target: `http://127.0.0.1/8080`, `http://172.13.1.1/prod-api`, // target: `http://127.0.0.1/8080`, `http://172.13.1.1/prod-api`,
changeOrigin: true, changeOrigin: true,
pathRewrite: { pathRewrite: {