From fa88c82524447e1e978637ff7f7dc7a3af20b956 Mon Sep 17 00:00:00 2001
From: hanbaoshan <hanbaoshan@aiotlink.com>
Date: 星期三, 29 七月 2020 10:25:42 +0800
Subject: [PATCH] 添加系统设置
---
src/components/serfDiagram/vue-d3-network/assets/node.svg | 13
src/pages/algorithmManage/index/mixins.ts | 0
src/pages/settings/index/App.vue | 166 +
src/pages/desktop/index/components/ToolsEntry.vue | 40
src/pages/desktop/index/components/DFrame.vue | 1
src/components/serfDiagram/vue-d3-network/assets/css/fonts/vue-d3-icons.eot | 0
src/pages/settings/components/LogManagement.vue | 190 +
src/pages/desktop/index/mock/userData.json | 8
src/components/serfDiagram/index.vue | 288 ++
src/components/serfDiagram/vue-d3-network/components/canvasRenderer.vue | 452 +++
src/pages/settings/components/AuthorityManagement.vue | 265 ++
src/components/serfDiagram/vue-d3-network/lib/js/canvasStyles.js | 56
src/components/subComponents/FileUpload/index.vue | 16
src/pages/desktop/index/components/Tools.vue | 7
src/components/serfDiagram/vue-d3-network/assets/css/fonts/vue-d3-icons.woff | 0
src/components/serfDiagram/vue-d3-network/lib/styl/node-style.styl | 6
src/components/serfDiagram/vue-d3-network/assets/css/icons.css | 95
src/components/serfDiagram/vue-d3-network/assets/css/fonts/vue-d3-icons.ttf | 0
src/components/serfDiagram/vue-d3-network/lib/js/stylePicker.js | 78
src/components/serfDiagram/vue-d3-network/assets/css/fonts/vue-d3-icons.svg | 28
src/components/serfDiagram/icons.js | 16
src/components/serfDiagram/vue-d3-network/lib/js/svgExport.js | 143 +
src/pages/settings/components/RadioSet.vue | 189 +
src/pages/settings/components/SystemMaintenance.vue | 514 ++++
src/components/serfDiagram/vue-d3-network/components/svgRenderer.vue | 207 +
src/components/serfDiagram/vue-d3-network/lib/js/saveImage.js | 28
src/pages/settings/components/ClusterManagement.vue | 620 +++++
src/pages/algorithmManage/index/App.vue | 1648 ++++++++++++++
src/pages/settings/index/main.ts | 11
src/components/serfDiagram/vue-d3-network/index.vue | 504 ++++
package.json | 5
src/pages/settings/components/BasicSetting.vue | 1307 +++++++++++
src/components/serfDiagram/vue-d3-network/assets/github.svg | 1
src/components/serfDiagram/vue-d3-network/lib/styl/vars.styl | 21
src/assets/gif/green.gif | 0
35 files changed, 6,881 insertions(+), 42 deletions(-)
diff --git a/package.json b/package.json
index 68f1fee..d3e822c 100644
--- a/package.json
+++ b/package.json
@@ -10,11 +10,16 @@
"dependencies": {
"@hscmap/vue-window": "^2.4.2",
"axios": "^0.19.2",
+ "d3-force": "^2.0.1",
"element-ui": "^2.4.6",
"less-loader": "^6.2.0",
+ "pug": "^3.0.0",
+ "pug-plain-loader": "^1.0.0",
"qs": "^6.9.4",
"simple-uploader.js": "^0.5.4",
"spark-md5": "^3.0.1",
+ "stylus": "^0.54.8",
+ "stylus-loader": "^3.0.2",
"vue": "^2.6.11",
"vue-awesome-swiper": "^3.1.3",
"vue-qrcode-component": "^2.1.1",
diff --git a/src/assets/gif/green.gif b/src/assets/gif/green.gif
new file mode 100644
index 0000000..a5e4077
--- /dev/null
+++ b/src/assets/gif/green.gif
Binary files differ
diff --git a/src/components/serfDiagram/icons.js b/src/components/serfDiagram/icons.js
new file mode 100644
index 0000000..c774809
--- /dev/null
+++ b/src/components/serfDiagram/icons.js
@@ -0,0 +1,16 @@
+const nodeIcon = {
+ master:
+ '<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="36" height="36" viewBox="0 0 36 36"><path stroke="null" id="svg_1" d="m2.94198,33.37473l-0.05707,0c-0.05707,-0.73562 0.39952,-2.29565 1.55369,-4.50252a17.173,17.173 0 0 1 -1.56637,-2.38443c-2.39712,4.12837 -3.21518,7.40062 -1.85174,8.76406a2.6381,2.6381 0 0 0 1.90247,0.63416c1.68052,0 4.06495,-0.9005 6.84257,-2.53663a16.72275,16.72275 0 0 1 -2.39078,-1.57271c-2.65078,1.45856 -4.0269,1.59808 -4.43276,1.59808zm29.98299,-30.07177l0.05707,0c0.05707,0.73562 -0.39952,2.29565 -1.55369,4.50252a17.173,17.173 0 0 1 1.56637,2.38443c2.39712,-4.12837 3.21518,-7.40062 1.85174,-8.76406a2.6381,2.6381 0 0 0 -1.90247,-0.63416c-1.68052,0 -4.06495,0.9005 -6.84257,2.53663a16.72275,16.72275 0 0 1 2.39078,1.57271c2.65078,-1.45856 4.0269,-1.59808 4.43276,-1.59808z"/> <path stroke="null" id="svg_2" d="m17.95567,2.57535a15.46011,15.46011 0 1 0 15.46011,15.46011a15.46011,15.46011 0 0 0 -15.46011,-15.46011zm4.29447,19.75458a68.13899,68.13899 0 0 1 -8.21676,7.06012a11.76686,11.76686 0 0 1 -2.37628,-1.14519a63.10014,63.10014 0 0 0 8.97259,-7.53537a62.6707,62.6707 0 0 0 7.55827,-8.97259a12.09897,12.09897 0 0 1 1.14519,2.36482a67.62938,67.62938 0 0 1 -7.08302,8.22821z"/></svg>',
+ db:
+ '<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="26" height="36" viewBox="0 0 26 36"><path stroke="null" id="svg_1" d="m12.92858,32.09526c-7.13873,0 -12.92858,-1.93175 -12.92858,-4.30953c0,-1.3004 0,-2.72254 0,-4.30953c0,-0.37493 0.18746,-0.73046 0.45681,-1.07738c1.44154,1.85633 6.45352,3.23215 12.47177,3.23215s11.03023,-1.37582 12.47177,-3.23215c0.26935,0.34692 0.45681,0.70245 0.45681,1.07738c0,1.24761 0,2.57171 0,4.30953c0,2.37778 -5.79093,4.30953 -12.92858,4.30953zm0,-8.61905c-7.13873,0 -12.92858,-1.93175 -12.92858,-4.30953c0,-1.30148 0,-2.72147 0,-4.30953c0,-0.2284 0.08619,-0.45035 0.20255,-0.67013l0,0c0.06572,-0.1379 0.15191,-0.27365 0.25426,-0.40725c1.44154,1.85525 6.45352,3.23215 12.47177,3.23215s11.03023,-1.37689 12.47177,-3.23215c0.10343,0.1336 0.18962,0.26935 0.25426,0.40725l0,0c0.11528,0.21979 0.20255,0.44173 0.20255,0.67013c0,1.24761 0,2.57063 0,4.30953c0,2.37778 -5.79093,4.30953 -12.92858,4.30953zm0,-8.61905c-7.13873,0 -12.92858,-1.93067 -12.92858,-4.30953c0,-0.68091 0,-1.4006 0,-2.15476c0,-0.68521 0,-1.39629 0,-2.15476c0,-2.37886 5.78985,-4.30953 12.92858,-4.30953s12.92858,1.93067 12.92858,4.30953c0,0.67229 0,1.38551 0,2.15476c0,0.65936 0,1.35535 0,2.15476c0,2.37886 -5.79093,4.30953 -12.92858,4.30953zm0,-10.77382c-4.75987,0 -8.61905,0.96318 -8.61905,2.15476s3.85918,2.15476 8.61905,2.15476s8.61905,-0.96318 8.61905,-2.15476s-3.85918,-2.15476 -8.61905,-2.15476z"/></svg>',
+ dbserver:
+ '<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="30" height="36" viewBox="0 0 30 36"><path stroke="null" id="svg_1" d="m13.43636,35.89747l4.41887,0l11.04719,0l4.41887,0l-19.88494,0l0.00001,0zm-11.04719,-22.35074l8.65437,0l12.70427,0l0.73574,0l2.20944,0l0,-13.41044l-26.51326,0l0,35.76118l11.04719,0l0,-2.23507l-8.83776,0l0,-2.23508l0,-17.8806l0.00001,0.00001zm0,-11.17536l22.09439,0l0,4.47014l-22.09439,0l0,-4.47014z"/> <path d="m29.57845,15.69168c0,0.60082 -3.23941,1.08788 -7.23544,1.08788m7.23544,-1.08788l0,0c0,0.60082 -3.23941,1.08788 -7.23544,1.08788c-3.99602,0 -7.23543,-0.48706 -7.23543,-1.08788m0,0l0,0c0,-0.60082 3.23941,-1.08788 7.23543,-1.08788c3.99602,0 7.23544,0.48706 7.23544,1.08788l0,4.35153c0,0.60082 -3.23941,1.08788 -7.23544,1.08788c-3.99602,0 -7.23543,-0.48706 -7.23543,-1.08788l0,-4.35153z" id="svg_2"/> <path d="m29.57476,23.23011c0,0.60082 -3.23941,1.08788 -7.23543,1.08788m7.23543,-1.08788l0,0c0,0.60082 -3.23941,1.08788 -7.23543,1.08788c-3.99602,0 -7.23543,-0.48706 -7.23543,-1.08788m0,0l0,0c0,-0.60082 3.23941,-1.08788 7.23543,-1.08788c3.99602,0 7.23543,0.48706 7.23543,1.08788l0,4.35153c0,0.60082 -3.23941,1.08788 -7.23543,1.08788c-3.99602,0 -7.23543,-0.48706 -7.23543,-1.08788l0,-4.35153z" id="svg_3" stroke="null"/> <path d="m29.5729,30.51667c0,0.60082 -3.23941,1.08788 -7.23543,1.08788m7.23543,-1.08788l0,0c0,0.60082 -3.23941,1.08788 -7.23543,1.08788c-3.99602,0 -7.23543,-0.48706 -7.23543,-1.08788m0,0l0,0c0,-0.60082 3.23941,-1.08788 7.23543,-1.08788c3.99602,0 7.23543,0.48706 7.23543,1.08788l0,4.35153c0,0.60082 -3.23941,1.08788 -7.23543,1.08788c-3.99602,0 -7.23543,-0.48706 -7.23543,-1.08788l0,-4.35153z" id="svg_4"/></svg>',
+ server:
+ '<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="26" height="36" viewBox="0 0 26 36"><path stroke="null" id="svg_1" d="m-0.13764,0.92824l0,34.34228l25.75671,0l0,-34.34228l-25.75671,0zm23.61032,27.9031l-21.42568,0.03825l-0.03825,-15.063l21.46393,0l0,15.02475zm0,-21.46392l-21.46393,0l0,-4.29279l21.46393,0l0,4.29279zm-2.14639,12.87835l-2.1464,0l0,-2.14639l2.1464,0l0,2.14639z"/></svg>',
+ pc:
+ '<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><path stroke="null" id="svg_1" d="m28.01904,24.6202l-8.07171,0l0,3.57741l1.78675,0c0.32522,-0.01175 0.63477,0.15673 0.79933,0.43885c0.16849,0.28212 0.16849,0.63085 0,0.91297c-0.16849,0.28212 -0.47412,0.45061 -0.79933,0.43885l-10.72832,0c-0.49371,0 -0.89337,-0.39967 -0.89337,-0.89337s0.39967,-0.89337 0.89337,-0.89337l1.78675,0l0,-3.57741l-8.96508,0c-1.97483,0 -3.57741,-1.60259 -3.57741,-3.57741l0,-16.0964c0,-1.97483 1.60259,-3.5735 3.57741,-3.5735l24.19554,0c1.97483,0 3.5735,1.59867 3.57741,3.5735l0,16.09248c-0.00392,1.97483 -1.60651,3.57741 -3.58133,3.57741zm-25.98229,-5.36416l0,1.79067c0,0.98741 0.79933,1.78675 1.78675,1.78675l24.19554,0c0.98741,0 1.79067,-0.80325 1.79067,-1.78675l0,-1.79067l-27.77295,0zm0,0"/></svg>',
+ pad:
+ '<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="38" viewBox="0 0 32 38"><path d="m28.84877,0.63462l-25.95664,0c-1.19162,0 -2.17601,0.98438 -2.17601,2.17601l0,32.82142c0,1.19162 0.98438,2.17601 2.17601,2.17601l25.95664,0c1.19162,0 2.17601,-0.98438 2.17601,-2.17601l0,-32.82142c0.0259,-1.19162 -0.95848,-2.17601 -2.17601,-2.17601zm-12.97832,33.62447c-0.67353,0 -1.21753,-0.544 -1.21753,-1.21753s0.544,-1.21753 1.21753,-1.21753s1.21753,0.544 1.21753,1.21753s-0.544,1.21753 -1.21753,1.21753z"/></svg>'
+}
+
+export default nodeIcon
diff --git a/src/components/serfDiagram/index.vue b/src/components/serfDiagram/index.vue
new file mode 100644
index 0000000..0e87121
--- /dev/null
+++ b/src/components/serfDiagram/index.vue
@@ -0,0 +1,288 @@
+<template lang='pug'>
+ .net
+ .arrow_box(:style="toolTipStyle")
+ p {{toolTipAddr}}
+ d3-network(
+ ref='net'
+ :net-nodes="nodes"
+ :net-links="links"
+ :options="options"
+ :selection="{nodes: nodeSelected, links: linksSelected}"
+ @drag-start='dragStart'
+ @node-click='nodeClick'
+ @node-hover='nodeHover'
+ @node-out='nodeOut'
+ )
+</template>
+
+<script>
+import D3Network from "./vue-d3-network";
+import RoleIcon from "./icons.js";
+
+export default {
+ name: "SerfDiagram",
+ components: {
+ D3Network
+ },
+ props: {
+ agent: String,
+ members: Array
+ },
+ data() {
+ return {
+ nodeSize: 20,
+ fontSize: 20,
+ canvas: false,
+ toolTipStyle: {
+ display: "none",
+ height: "30px",
+ width: "120px"
+ }
+ };
+ },
+ computed: {
+ nodes() {
+ let n = new Array();
+ this.members.forEach((v, i) => {
+ n.push({
+ id: i,
+ name: v.nodeName,
+ svgSym: RoleIcon[v.role],
+ _color:
+ this.agent === v.nodeName
+ ? "red"
+ : v.role === "master"
+ ? "orange"
+ : ""
+ });
+ });
+
+ return n;
+ },
+ links() {
+ let arr = new Array();
+ let dup = new Array(); // Deduplicate to ensure that two nodes have only one line
+ const count = this.members.length;
+
+ switch (count) {
+ case 0:
+ case 1:
+ break;
+ case 2:
+ arr = [{ sid: 0, tid: 1 }];
+ break;
+ case 3:
+ arr = [{ sid: 0, tid: 1 }, { sid: 1, tid: 2 }, { sid: 0, tid: 2 }];
+ break;
+ default:
+ for (let i = 0; i < count; i++) {
+ let loop = Math.round(Math.random() * 5 + 2); // At least 2 times
+ for (let j = 0; j < loop; j++) {
+ let target = Math.round(Math.random() * (count - 1));
+ if (target === i) {
+ // is me? skip
+ continue;
+ }
+
+ if (!dup["d" + target + i]) {
+ arr.push({ sid: i, tid: target });
+ dup["d" + i + target] = 1;
+ }
+ }
+ }
+ }
+
+ return arr;
+ },
+ options() {
+ return {
+ force: 3000,
+ nodeSize: this.nodeSize,
+ fontSize: this.fontSize,
+ nodeLabels: true,
+ canvas: this.canvas,
+ linkWidth: 0,
+ size: {
+ w: 745,
+ h: 426
+ }
+ };
+ }
+ },
+ created() {
+ this.reset();
+ },
+ methods: {
+ nodeHover(event, node) {
+ console.log(node);
+ node._opacity = 1;
+ node._size = 28;
+ let width = document.body.clientWidth;
+ this.toolTipStyle.display = "block";
+ this.toolTipStyle.top = node.y - 10 + "px";
+ this.toolTipStyle.left = node.x + width / 2 - 30 + "px";
+
+ this.toolTipNode = this.members[node.id].nodeName;
+ this.toolTipAddr = this.members[node.id].Address;
+ },
+ nodeOut(event, node) {
+ node._opacity = node.opacity;
+ node._size = node.size;
+ this.toolTipStyle.display = "none";
+ },
+ dragStart(event) {
+ if (event) {
+ this.movement = event.timeStamp;
+ }
+ },
+ nodeClick(event, node) {
+ // if (this.nodeSelected[node.id]) {
+ // this.unSelectNode(node.id)
+ // // is not nodeSelected
+ // } else {
+ // this.selectNode(node)
+
+ // }
+ // this.selectNodesLinks()
+ // this.$set(this.nodes, node.index, node)
+
+ if (event.timeStamp - this.movement < 200) {
+ this.$emit("selected-node", event, this.members[node.id]);
+ }
+ },
+ reset() {
+ this.nodeSelected = {};
+ this.linksSelected = {};
+ (this.toolTipNode = ""), (this.toolTipAddr = ""), (this.movement = 0);
+ },
+ unSelectNode(nodeId) {
+ if (this.nodeSelected[nodeId]) {
+ delete this.nodeSelected[nodeId];
+ }
+ this.selectNodesLinks();
+ },
+ unSelectLink(linkId) {
+ if (this.linksSelected[linkId]) {
+ delete this.linksSelected[linkId];
+ }
+ },
+ selectNode(node) {
+ this.nodeSelected[node.id] = node;
+ },
+ selectLink(link) {
+ this.$set(this.linksSelected, link.id, link);
+ },
+ selectNodesLinks() {
+ for (let link of this.links) {
+ // node is nodeSelected
+ if (this.nodeSelected[link.sid] || this.nodeSelected[link.tid]) {
+ this.selectLink(link);
+ } else {
+ this.unSelectLink(link.id);
+ }
+ }
+ }
+ }
+};
+</script>
+
+<style>
+.net {
+ height: 100%;
+ margin: 0;
+}
+
+.node {
+ /* stroke: rgba(18, 120, 98, 0.7); */
+ stroke: rgba(76, 78, 78, 0.7);
+ stroke-width: 3px;
+ -webkit-transition: fill 0.5s ease;
+ transition: fill 0.5s ease;
+ /* fill: #dcfaf3; */
+ fill: #e3e4e4;
+}
+
+.node.selected {
+ stroke: #caa455;
+}
+
+.node.pinned {
+ stroke: rgba(190, 56, 93, 0.6);
+}
+
+.link {
+ stroke: rgba(18, 120, 98, 0.3);
+}
+
+.link,
+.node {
+ stroke-linecap: round;
+}
+
+.link:hover,
+.node:hover {
+ stroke: #df8108;
+ stroke-width: 1px;
+ cursor: pointer;
+}
+
+.link.selected {
+ stroke: rgba(202, 164, 85, 0.6);
+}
+
+.curve {
+ fill: none;
+}
+
+.link-label,
+.node-label {
+ /* fill: #127862; */
+ fill: rgba(76, 78, 78, 0.7);
+}
+
+.link-label {
+ -webkit-transform: translateY(-0.5em);
+ transform: translateY(-0.5em);
+ text-anchor: middle;
+}
+
+.arrow_box {
+ position: absolute;
+ background: #fff;
+ /* border: 1px solid #127862; */
+ border: 1px solid rgba(76, 78, 78, 0.7);
+ font-size: 11px;
+ padding-left: 5px;
+}
+
+.arrow_box p {
+ height: 30px;
+ line-height: 30px;
+ width: 100px;
+ overflow: hidden;
+}
+.arrow_box:after,
+.arrow_box:before {
+ right: 100%;
+ top: 50%;
+ border: solid transparent;
+ content: " ";
+ height: 0;
+ width: 0;
+ position: absolute;
+ pointer-events: none;
+}
+
+.arrow_box:after {
+ border-color: rgba(136, 183, 213, 0);
+ border-right-color: #fff;
+ border-width: 5px;
+ margin-top: -5px;
+}
+.arrow_box:before {
+ border-color: rgba(194, 225, 245, 0);
+ border-right-color: #323333;
+ border-width: 6px;
+ margin-top: -6px;
+}
+</style>
diff --git a/src/components/serfDiagram/vue-d3-network/assets/css/fonts/vue-d3-icons.eot b/src/components/serfDiagram/vue-d3-network/assets/css/fonts/vue-d3-icons.eot
new file mode 100644
index 0000000..aa85672
--- /dev/null
+++ b/src/components/serfDiagram/vue-d3-network/assets/css/fonts/vue-d3-icons.eot
Binary files differ
diff --git a/src/components/serfDiagram/vue-d3-network/assets/css/fonts/vue-d3-icons.svg b/src/components/serfDiagram/vue-d3-network/assets/css/fonts/vue-d3-icons.svg
new file mode 100644
index 0000000..62f4915
--- /dev/null
+++ b/src/components/serfDiagram/vue-d3-network/assets/css/fonts/vue-d3-icons.svg
@@ -0,0 +1,28 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
+<svg xmlns="http://www.w3.org/2000/svg">
+<metadata>Generated by IcoMoon</metadata>
+<defs>
+<font id="vue-d3-icons" horiz-adv-x="1024">
+<font-face units-per-em="1024" ascent="960" descent="-64" />
+<missing-glyph horiz-adv-x="1024" />
+<glyph unicode=" " horiz-adv-x="512" d="" />
+<glyph unicode="" glyph-name="pointer, mouse" d="M531.291 380.328l148.709-345.66-112.001-55.999-130.087 354.984-205.913-186.984v727.999l559.999-448.001-260.707-46.339z" />
+<glyph unicode="" glyph-name="move, drag" d="M575.488 749.195v-258.016h256v128l192.512-192.512-192.512-192.48v130.976h-256v-258.016h128.992l-192.48-192.48-192.512 192.48h128v258.016h-256v-129.984l-191.488 191.488 191.488 191.488v-126.976h256v258.016h-124.992l189.504 189.472 189.504-189.472h-126.016z" />
+<glyph unicode="" glyph-name="pin2" horiz-adv-x="519" d="M196 234.667l64-320 64 320c-20-2-43-3-64-3s-44 1-64 3zM450 533.667c-33 17-62 59-62 85v64c0 22 12 39 23 52 15 13 24 29 24 45 0 53-61 95-175 95s-175-42-175-95c0-16 9-32 24-45 11-13 23-30 23-52v-64c0-26-29-68-62-85-38-19-70-54-70-88 0-74 101-148 260-148s260 73 260 148c0 33-31 68-70 88z" />
+<glyph unicode="" glyph-name="repo-forked" horiz-adv-x="768" d="M720.048 762.715c0 62.135-49.881 112.016-112.016 112.016s-112.016-49.881-112.016-112.016c0-41.132 22.754-77.885 56.008-97.139v-92.764l-168.024-185.525-168.024 185.525v92.764c33.254 19.252 56.008 55.134 56.008 97.139 0 62.135-49.881 112.016-112.016 112.016s-112.016-49.881-112.016-112.016c0-41.132 22.754-77.885 56.008-97.139v-136.518l224.032-246.783v-95.389c-33.254-19.252-56.008-55.134-56.008-97.139 0-62.135 49.881-112.016 112.016-112.016s112.016 49.881 112.016 112.016c0 41.132-22.754 77.885-56.008 97.139v95.389l224.032 246.783v136.518c33.254 19.252 56.008 55.134 56.008 97.139zM159.968 817.846c29.755 0 54.257-24.503 54.257-54.257s-24.503-54.257-54.257-54.257-54.257 24.503-54.257 54.257 24.503 54.257 54.257 54.257zM384 38.113c-29.755 0-54.257 24.503-54.257 54.257s24.503 54.257 54.257 54.257 54.257-24.503 54.257-54.257-24.503-54.257-54.257-54.257zM608.032 817.846c29.755 0 54.257-24.503 54.257-54.257s-24.503-54.257-54.257-54.257-54.257 24.503-54.257 54.257 24.503 54.257 54.257 54.257z" />
+<glyph unicode="" glyph-name="reload-alt, refresh, reset, arrow" d="M576 170.667c141.248 0 256 114.752 256 256s-114.752 256-256 256-256-114.752-256-256v-128l128.64-0.736-192.64-192.384-192 192.384h128v128.736c0 212 172 384 384 384s384-172 384-384-172-384-384-384v128z" />
+<glyph unicode="" glyph-name="cubes" horiz-adv-x="1243" d="M365.714 6.096l219.429 109.714v179.429l-219.429-93.714v-195.429zM329.143 265.524l230.857 98.857-230.857 98.857-230.857-98.857zM950.857 6.096l219.429 109.714v179.429l-219.429-93.714v-195.429zM914.286 265.524l230.857 98.857-230.857 98.857-230.857-98.857zM658.286 432.953l219.429 94.286v152l-219.429-93.714v-152.571zM621.714 649.524l252 108-252 108-252-108zM1243.429 353.524v-237.714c0-27.429-15.429-53.143-40.571-65.143l-256-128c-10.286-5.714-21.143-8-32.571-8s-22.286 2.286-32.571 8l-256 128c-1.714 0.571-2.857 1.143-4 2.286-1.143-1.143-2.286-1.714-4-2.286l-256-128c-10.286-5.714-21.143-8-32.571-8s-22.286 2.286-32.571 8l-256 128c-25.143 12-40.571 37.714-40.571 65.143v237.714c0 29.143 17.714 55.429 44.571 67.429l248 106.286v228.571c0 29.143 17.714 55.429 44.571 67.429l256 109.714c9.143 4 18.857 5.714 28.571 5.714s19.429-1.714 28.571-5.714l256-109.714c26.857-12 44.571-38.286 44.571-67.429v-228.571l248-106.286c27.429-12 44.571-38.286 44.571-67.429z" />
+<glyph unicode="" glyph-name="cube" horiz-adv-x="951" d="M512 7.81l365.714 199.429v363.429l-365.714-133.143v-429.714zM475.429 502.096l398.857 145.143-398.857 145.143-398.857-145.143zM950.857 646.096v-438.857c0-26.857-14.857-51.429-38.286-64l-402.286-219.429c-10.857-6.286-22.857-9.143-34.857-9.143s-24 2.857-34.857 9.143l-402.286 219.429c-23.429 12.571-38.286 37.143-38.286 64v438.857c0 30.857 19.429 58.286 48 68.571l402.286 146.286c8 2.857 16.571 4.571 25.143 4.571s17.143-1.714 25.143-4.571l402.286-146.286c28.571-10.286 48-37.714 48-68.571z" />
+<glyph unicode="" glyph-name="pin" d="M713.771 756.438c-16.597 16.683-43.563 16.768-60.331 0.171-4.437-4.437-7.509-9.685-9.6-15.147-35.499-74.069-74.581-115.84-123.904-140.501-55.339-27.307-118.869-46.293-221.269-46.293-5.547 0-11.093-1.067-16.299-3.243-10.453-4.352-18.731-12.672-23.083-23.083-4.309-10.411-4.309-22.187 0-32.597 2.176-5.248 5.291-9.984 9.259-13.909l138.368-138.368-193.579-258.133 258.133 193.579 138.325-138.325c3.925-4.011 8.661-7.083 13.909-9.259 5.205-2.176 10.752-3.328 16.299-3.328s11.093 1.152 16.299 3.328c10.453 4.352 18.773 12.587 23.083 23.083 2.176 5.163 3.285 10.752 3.285 16.256 0 102.4 18.944 165.931 46.208 220.416 24.619 49.323 66.389 88.405 140.501 123.904 5.504 2.091 10.709 5.163 15.104 9.6 16.597 16.768 16.512 43.733-0.171 60.331l-170.539 171.52z" />
+<glyph unicode="" glyph-name="menu" d="M128 682.667h768v-86h-768v86zM128 384.667v84h768v-84h-768zM128 170.667v86h768v-86h-768z" />
+<glyph unicode="" glyph-name="camera" d="M512 212.667c118 0 214 96 214 214s-96 214-214 214-214-96-214-214 96-214 214-214zM384 852.667h256l78-84h136c46 0 84-40 84-86v-512c0-46-38-86-84-86h-684c-46 0-84 40-84 86v512c0 46 38 86 84 86h136zM376 426.667c0 76 60 136 136 136s136-60 136-136-60-136-136-136-136 60-136 136z" />
+<glyph unicode="" glyph-name="delete_forever" d="M662 768.667h148v-86h-596v86h148l44 42h212zM360 432.667l92-92-90-90 60-60 90 90 90-90 60 60-90 90 90 92-60 60-90-92-90 92zM256 128.667v512h512v-512c0-46-40-86-86-86h-340c-46 0-86 40-86 86z" />
+<glyph unicode="" glyph-name="delete" d="M810 768.667v-86h-596v86h148l44 42h212l44-42h148zM256 128.667v512h512v-512c0-46-40-86-86-86h-340c-46 0-86 40-86 86z" />
+<glyph unicode="" glyph-name="settings" d="M512 276.667c82 0 150 68 150 150s-68 150-150 150-150-68-150-150 68-150 150-150zM830 384.667l90-70c8-6 10-18 4-28l-86-148c-6-10-16-12-26-8l-106 42c-22-16-46-32-72-42l-16-112c-2-10-10-18-20-18h-172c-10 0-18 8-20 18l-16 112c-26 10-50 24-72 42l-106-42c-10-4-20-2-26 8l-86 148c-6 10-4 22 4 28l90 70c-2 14-2 28-2 42s0 28 2 42l-90 70c-8 6-10 18-4 28l86 148c6 10 16 12 26 8l106-42c22 16 46 32 72 42l16 112c2 10 10 18 20 18h172c10 0 18-8 20-18l16-112c26-10 50-24 72-42l106 42c10 4 20 2 26-8l86-148c6-10 4-22-4-28l-90-70c2-14 2-28 2-42s0-28-2-42z" />
+<glyph unicode="" glyph-name="equalizerh" d="M448 810.667v16c0 26.4-21.6 48-48 48h-160c-26.4 0-48-21.6-48-48v-16h-192v-128h192v-16c0-26.4 21.6-48 48-48h160c26.4 0 48 21.6 48 48v16h576v128h-576zM256 682.667v128h128v-128h-128zM832 506.667c0 26.4-21.6 48-48 48h-160c-26.4 0-48-21.6-48-48v-16h-576v-128h576v-16c0-26.4 21.6-48 48-48h160c26.4 0 48 21.6 48 48v16h192v128h-192v16zM640 362.667v128h128v-128h-128zM448 186.667c0 26.4-21.6 48-48 48h-160c-26.4 0-48-21.6-48-48v-16h-192v-128h192v-16c0-26.4 21.6-48 48-48h160c26.4 0 48 21.6 48 48v16h576v128h-576v16zM256 42.667v128h128v-128h-128z" />
+<glyph unicode="" glyph-name="equalizerv" d="M896 490.667h16c26.4 0 48 21.6 48 48v160c0 26.4-21.6 48-48 48h-16v192h-128v-192h-16c-26.4 0-48-21.6-48-48v-160c0-26.4 21.6-48 48-48h16v-576h128v576zM768 682.667h128v-128h-128v128zM592 106.667c26.4 0 48 21.6 48 48v160c0 26.4-21.6 48-48 48h-16v576h-128v-576h-16c-26.4 0-48-21.6-48-48v-160c0-26.4 21.6-48 48-48h16v-192h128v192h16zM448 298.667h128v-128h-128v128zM272 490.667c26.4 0 48 21.6 48 48v160c0 26.4-21.6 48-48 48h-16v192h-128v-192h-16c-26.4 0-48-21.6-48-48v-160c0-26.4 21.6-48 48-48h16v-576h128v576h16zM128 682.667h128v-128h-128v128z" />
+<glyph unicode="" glyph-name="github" d="M512.008 926.025c-282.738 0-512.008-229.218-512.008-511.998 0-226.214 146.704-418.132 350.136-485.836 25.586-4.738 34.992 11.11 34.992 24.632 0 12.204-0.48 52.542-0.696 95.324-142.448-30.976-172.504 60.41-172.504 60.41-23.282 59.176-56.848 74.916-56.848 74.916-46.452 31.778 3.51 31.124 3.51 31.124 51.4-3.61 78.476-52.766 78.476-52.766 45.672-78.27 119.776-55.64 149.004-42.558 4.588 33.086 17.852 55.68 32.506 68.464-113.73 12.942-233.276 56.85-233.276 253.032 0 55.898 20.004 101.574 52.76 137.428-5.316 12.9-22.854 64.972 4.952 135.5 0 0 43.006 13.752 140.84-52.49 40.836 11.348 84.636 17.036 128.154 17.234 43.502-0.198 87.336-5.886 128.256-17.234 97.734 66.244 140.656 52.49 140.656 52.49 27.872-70.528 10.35-122.6 5.036-135.5 32.82-35.856 52.694-81.532 52.694-137.428 0-196.654-119.778-239.95-233.79-252.624 18.364-15.89 34.724-47.046 34.724-94.812 0-68.508-0.596-123.644-0.596-140.508 0-13.628 9.222-29.594 35.172-24.566 203.322 67.776 349.842 259.626 349.842 485.768 0 282.78-229.234 511.998-511.992 511.998z" />
+<glyph unicode="" glyph-name="git-merge" horiz-adv-x="768" d="M615.62 484.571c-43.089 0-80.185-23.806-100.089-58.724-5.202 0.368-10.291 0.82-15.721 0.82-118.58 0-231.11 90.336-272.164 202.158 24.683 21.233 40.544 52.335 40.544 87.366 0 63.926-51.882 115.81-115.81 115.81s-115.81-51.882-115.81-115.81c0-42.722 23.382-79.676 57.904-99.779v-379.519c-34.522-20.074-57.904-57-57.904-99.75 0-63.899 51.882-115.81 115.81-115.81s115.81 51.911 115.81 115.81c0 42.75-23.382 79.676-57.904 99.75v208.349c76.142-80.551 181.291-134.385 289.524-134.385 5.767 0 10.517 0.396 15.721 0.565 20.017-34.777 57.113-58.471 100.089-58.471 63.899 0 115.81 51.911 115.81 115.81 0 63.926-51.911 115.81-115.81 115.81zM152.38 79.239c-31.949 0-57.904 25.899-57.904 57.904 0 31.949 25.956 57.904 57.904 57.904 32.034 0 57.904-25.956 57.904-57.904 0-32.006-25.87-57.904-57.904-57.904zM152.38 658.287c-31.949 0-57.904 25.87-57.904 57.904s25.956 57.904 57.904 57.904c32.034 0 57.904-25.87 57.904-57.904s-25.87-57.904-57.904-57.904zM615.62 310.857c-31.949 0-57.904 25.899-57.904 57.904 0 32.034 25.956 57.904 57.904 57.904 32.006 0 57.904-25.87 57.904-57.904 0-32.006-25.899-57.904-57.904-57.904z" />
+<glyph unicode="" glyph-name="pulse" horiz-adv-x="896" d="M736 426.729l-172.812 166.344-140.782-198.406-70.406 441.594-199.562-409.532h-152.438v-128.062h230.406l57.594 115.188 57.594-345.562 230.406 326.374 102.375-96h217.625v128.062h-160z" />
+</font></defs></svg>
\ No newline at end of file
diff --git a/src/components/serfDiagram/vue-d3-network/assets/css/fonts/vue-d3-icons.ttf b/src/components/serfDiagram/vue-d3-network/assets/css/fonts/vue-d3-icons.ttf
new file mode 100644
index 0000000..1c2b915
--- /dev/null
+++ b/src/components/serfDiagram/vue-d3-network/assets/css/fonts/vue-d3-icons.ttf
Binary files differ
diff --git a/src/components/serfDiagram/vue-d3-network/assets/css/fonts/vue-d3-icons.woff b/src/components/serfDiagram/vue-d3-network/assets/css/fonts/vue-d3-icons.woff
new file mode 100644
index 0000000..8db129b
--- /dev/null
+++ b/src/components/serfDiagram/vue-d3-network/assets/css/fonts/vue-d3-icons.woff
Binary files differ
diff --git a/src/components/serfDiagram/vue-d3-network/assets/css/icons.css b/src/components/serfDiagram/vue-d3-network/assets/css/icons.css
new file mode 100644
index 0000000..f43041c
--- /dev/null
+++ b/src/components/serfDiagram/vue-d3-network/assets/css/icons.css
@@ -0,0 +1,95 @@
+@font-face {
+ font-family: 'vue-d3-icons';
+ src: url('fonts/vue-d3-icons.eot?oa3tyj');
+ src: url('fonts/vue-d3-icons.eot?oa3tyj#iefix') format('embedded-opentype'),
+ url('fonts/vue-d3-icons.ttf?oa3tyj') format('truetype'),
+ url('fonts/vue-d3-icons.woff?oa3tyj') format('woff'),
+ url('fonts/vue-d3-icons.svg?oa3tyj#vue-d3-icons') format('svg');
+ font-weight: normal;
+ font-style: normal;
+}
+
+[class^="icon-"], [class*=" icon-"] {
+ /* use !important to prevent issues with browser extensions that change fonts */
+ font-family: 'vue-d3-icons' !important;
+ speak: none;
+ font-style: normal;
+ font-weight: normal;
+ font-variant: normal;
+ text-transform: none;
+ line-height: 1;
+
+ /* Better Font Rendering =========== */
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+}
+
+.icon-reload-alt:before {
+ content: "\e904";
+}
+.icon-refresh:before {
+ content: "\e904";
+}
+.icon-reset:before {
+ content: "\e904";
+}
+.icon-arrow:before {
+ content: "\e904";
+}
+.icon-git-merge:before {
+ content: "\f023";
+}
+.icon-pulse:before {
+ content: "\f085";
+}
+.icon-pointer:before {
+ content: "\e900";
+}
+.icon-mouse:before {
+ content: "\e900";
+}
+.icon-move:before {
+ content: "\e901";
+}
+.icon-drag:before {
+ content: "\e901";
+}
+.icon-cubes:before {
+ content: "\e907";
+}
+.icon-cube:before {
+ content: "\e908";
+}
+.icon-pin:before {
+ content: "\e909";
+}
+.icon-menu:before {
+ content: "\e90a";
+}
+.icon-camera:before {
+ content: "\e90b";
+}
+.icon-delete_forever:before {
+ content: "\e90c";
+}
+.icon-delete:before {
+ content: "\e90d";
+}
+.icon-settings:before {
+ content: "\e90e";
+}
+.icon-pin2:before {
+ content: "\e902";
+}
+.icon-repo-forked:before {
+ content: "\e903";
+}
+.icon-equalizerh:before {
+ content: "\e992";
+}
+.icon-equalizerv:before {
+ content: "\e993";
+}
+.icon-github:before {
+ content: "\eab0";
+}
diff --git a/src/components/serfDiagram/vue-d3-network/assets/github.svg b/src/components/serfDiagram/vue-d3-network/assets/github.svg
new file mode 100644
index 0000000..158038f
--- /dev/null
+++ b/src/components/serfDiagram/vue-d3-network/assets/github.svg
@@ -0,0 +1 @@
+<svg height="128" class="octicon octicon-mark-github" viewBox="0 0 16 16" version="1.1" width="128" aria-hidden="true"><path fill-rule="evenodd" d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z"></path></svg>
\ No newline at end of file
diff --git a/src/components/serfDiagram/vue-d3-network/assets/node.svg b/src/components/serfDiagram/vue-d3-network/assets/node.svg
new file mode 100644
index 0000000..b6de4ff
--- /dev/null
+++ b/src/components/serfDiagram/vue-d3-network/assets/node.svg
@@ -0,0 +1,13 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 33.866666 33.866668">
+ <g id="fill" style="opacity:1;" transform="matrix(0.2575943,0,0,0.23849115,-9.1120023,-50.435759)">
+ <path id="path8251-2-6-5-9-2" d="m 156.78907,230.06236 a 54.165703,13.707579 0 0 1 -54.1657,13.70758 54.165703,13.707579 0 0 1 -54.165706,-13.70758 54.165703,13.707579 0 0 1 54.165706,-13.70758 54.165703,13.707579 0 0 1 54.1657,13.70758 z M 48.404512,229.55428 v 0.2202 c 0.01214,-0.0734 0.02647,-0.14685 0.04327,-0.2202 z m 108.290078,0 c 0.0147,0.083 0.0269,0.16638 0.0356,0.24943 2.4e-4,7.57053 -24.25098,13.70738 -54.16604,13.70738 -29.849952,-7.9e-4 -54.071017,-6.11278 -54.159668,-13.6668 v 31.89855 a 54.184263,15.828606 0 0 1 -0.183897,-1.1851 v 37.13064 a 54.184263,15.828607 0 0 0 -0.0057,0.0269 54.184263,15.828607 0 0 0 0.0057,0.0388 v 0.45411 h 0.04136 v 36.24689 a 54.184263,15.828607 0 0 0 -0.0057,0.0269 54.184263,15.828607 0 0 0 0.0057,0.0388 v 0.45411 h 0.05536 a 54.184263,15.828607 0 0 0 54.124675,15.33644 54.184263,15.828607 0 0 0 54.09986,-15.33644 h 0.0891 v -37.98873 h -0.0414 a 54.184263,15.828606 0 0 1 0.035,0.28702 54.184263,15.828606 0 0 1 -0.035,0.20408 v -0.4911 -34.41793 c 0.0186,-0.0385 0.0395,-0.0767 0.0573,-0.11517 0.18386,-10.752 0.0891,-21.98037 0.0891,-32.89866 z M 48.220615,260.2188 v 0.25123 a 54.184263,15.828606 0 0 1 0.04327,-0.25123 z"/>
+ </g>
+ <g transform="matrix(0.31703209,0,0,0.2753999,-15.226615,0.59173245)">
+ <path id="bottom" d="m 58.574418,71.818443 v 0.21756 a 44.004366,13.707578 0 0 1 0.03481,-0.21756 z m 87.975532,5.3e-4 a 44.004366,13.707578 0 0 1 0.0281,0.24857 44.004366,13.707578 0 0 1 -44.00433,13.70766 44.004366,13.707578 0 0 1 -43.999312,-13.66323 v 32.155137 a 44.004366,13.707579 0 0 0 -0.0045,0.0233 44.004366,13.707579 0 0 0 0.0045,0.0336 v 0.39325 h 0.04496 a 44.004366,13.707579 0 0 0 43.955642,13.28134 44.004366,13.707579 0 0 0 43.93593,-13.28136 h 0.0726 V 71.818963 Z" style="opacity:0.2;fill:black"/>
+ <path id="mid" d="m 58.540832,39.978483 v 0.21756 a 44.004366,13.707578 0 0 1 0.03481,-0.21756 z m 87.975528,5.3e-4 a 44.004366,13.707578 0 0 1 0.0281,0.24857 44.004366,13.707578 0 0 1 -44.00432,13.70769 44.004366,13.707578 0 0 1 -43.99931,-13.66326 v 32.15514 a 44.004366,13.707579 0 0 0 -0.0045,0.0233 44.004366,13.707579 0 0 0 0.0045,0.0336 v 0.39325 h 0.04487 a 44.004366,13.707579 0 0 0 43.95565,13.28136 44.004366,13.707579 0 0 0 43.93592,-13.28136 h 0.0726 v -32.8983 z" style="opacity:0.3;fill:black"/>
+ <g transform="matrix(0.81212445,0,0,0.86600028,19.379501,-185.37111)">
+ <path id="top" d="m 182.94531,867.60742 v 0.83203 c 0.0459,-0.27745 0.10057,-0.5548 0.16407,-0.83203 z m 409.28711,0 c 0.0555,0.31369 0.0998,0.62751 0.13281,0.94141 9.1e-4,28.61302 -91.65592,51.80858 -204.7207,51.80859 -112.81873,-0.003 -204.36415,-23.10367 -204.69922,-51.6543 v 121.54493 c -0.006,0.0293 -0.0118,0.0586 -0.0176,0.0879 0.006,0.0417 0.0115,0.0833 0.0176,0.125 v 1.48633 h 0.20899 c 9.08883,25.83352 97.38326,56.20372 207.91946,56.22112 110.50057,-0.03 187.36844,-26.7045 200.97702,-56.22112 0.69493,-40.63748 0.33789,-83.07388 0.33789,-124.33986 z" style="opacity:0.4;fill:black" transform="scale(0.26458333)"/>
+ <ellipse id="cap" cx="102.62337" cy="230.06236" rx="54.165703" ry="13.707579" style="opacity:0.5;fill:black"/>
+ </g>
+ </g>
+</svg>
diff --git a/src/components/serfDiagram/vue-d3-network/components/canvasRenderer.vue b/src/components/serfDiagram/vue-d3-network/components/canvasRenderer.vue
new file mode 100644
index 0000000..58342ad
--- /dev/null
+++ b/src/components/serfDiagram/vue-d3-network/components/canvasRenderer.vue
@@ -0,0 +1,452 @@
+<template lang="pug">
+ canvas(id='canvas' ref='canvas'
+ :width='size.w'
+ :height='size.h'
+ :style='canvasStyle'
+ @mouseup.prevent='canvasClick'
+ @mousedown.prevent='canvasClick'
+ @touchstart.prevent='canvasClick'
+ @touchend.passive='canvasClick'
+ v-render-canvas='{links, nodes}'
+ )
+</template>
+<script>
+import canvasStyles from '../lib/js/canvasStyles.js'
+import stylePicker from '../lib/js/stylePicker.js'
+import svgExport from '../lib/js/svgExport.js'
+export default {
+ name: 'canvas-renderer',
+ props: [
+ 'size',
+ 'offset',
+ 'padding',
+ 'nodes',
+ 'selected',
+ 'linksSelected',
+ 'links',
+ 'nodeSize',
+ 'fontSize',
+ 'strLinks',
+ 'linkWidth',
+ 'nodeLabels',
+ 'labelOffset',
+ 'canvasStyles',
+ 'nodeSym',
+ 'noNodes'
+ ],
+ data () {
+ return {
+ hitCanvas: null,
+ shapes: {},
+ drag: null,
+ stylesReady: false,
+ CssStyles: true, // load style from css props
+ // canvas styles
+ styles: canvasStyles,
+ sprites: {}
+ }
+ },
+ computed: {
+ nodeSvg () {
+ return this.nodeSym
+ },
+ canvasStyle () {
+ let left = this.padding.x + 'px'
+ let top = this.padding.y + 'px'
+ return { left, top }
+ }
+ },
+ directives: {
+ renderCanvas (canvas, data, vnode) {
+ let nodes = data.value.nodes
+ let links = data.value.links
+ vnode.context.draw(nodes, links, canvas)
+ }
+ },
+ created () {
+ if (this.canvasStyles) {
+ for (let o in this.canvasStyles) {
+ this.styles[o] = this.canvasStyles[o]
+ }
+ }
+ },
+ mounted () {
+ let vm = this
+ this.$nextTick(() => {
+ vm.hitCanvas.width = vm.size.w
+ vm.hitCanvas.height = vm.size.h
+ })
+ },
+ watch: {
+ nodeSize () {
+ this.resetSprites()
+ },
+ canvasStyles () {
+ this.resetSprites()
+ }
+ },
+ methods: {
+ // canvas to png
+ canvasScreenShot (cb, bgColor) {
+ let graph = this.$refs.canvas
+ let canvas = document.createElement('canvas')
+ canvas.width = graph.width
+ canvas.height = graph.height
+ // background color
+ let background = this.styles.background
+ if (bgColor) background = this.getCssColor(bgColor)
+ let ctx = canvas.getContext('2d')
+ ctx = this.setCtx(ctx, background)
+ ctx.fillRect(0, 0, canvas.width, canvas.height)
+ ctx.drawImage(graph, 0, 0)
+ let img = canvas.toDataURL('image/png')
+ if (img) cb(null, img)
+ else cb(new Error('error generating canvas image'))
+ },
+ // emits events as 'action'
+ emit (e, args) {
+ this.$emit('action', e, args)
+ },
+ // creates 'virtual' canvas to catch mouse interaction
+ canvasInit () {
+ let hitCanvas = document.createElement('canvas')
+ hitCanvas.width = this.size.w
+ hitCanvas.height = this.size.h
+ hitCanvas.top = this.offset.y
+ hitCanvas.left = this.offset.x
+ hitCanvas.id = 'hit-canvas'
+ this.hitCanvas = hitCanvas
+ this.resetSprites()
+ },
+ resetSprites () {
+ this.sprites = {}
+ let sprites = ['node', 'nodeSelected', 'nodePinned', 'nodeSelectedPinned']
+ for (let sp of sprites) {
+ this.sprites[sp] = this.nodeSprite(this.styles[sp])
+ }
+ },
+ // canvas click handler
+ canvasClick (event) {
+ let hitCtx = this.hitCanvas.getContext('2d')
+ let e = (event.touches) ? event.touches[0] || event.changedTouches[0] : event
+ let scrollTop = document.body.scrollTop
+ let scrollLeft = document.body.scrollLeft
+ let x = e.clientX + scrollLeft - this.padding.x
+ let y = e.clientY + scrollTop - this.padding.y
+
+ let pixel = hitCtx.getImageData(x, y, 1, 1).data
+ let color = `rgb(${pixel[0]},${pixel[1]},${pixel[2]})`
+ let shape = this.shapes[color]
+ if (shape) {
+ let col = shape.type + 's'
+ let item = this[col][shape.index]
+ if (item) {
+ if (event.type === 'mouseup' || event.type === 'touchend') {
+ if (this.drag) {
+ this.drag = null
+ this.emit('dragEnd')
+ }
+ this.emit(shape.type + 'Click', [event, item])
+ } else if (event.type === 'mousedown' || event.type === 'touchstart') {
+ this.drag = item
+ this.emit('dragStart', [event, item.index])
+ }
+ }
+ }
+ },
+ // draw circ node to canvas
+ drawNode (ctx, node) {
+ ctx.beginPath()
+ ctx.arc(node.x, node.y, this.nodeSize / 2, 0, 2 * Math.PI, false)
+ let fillStyle = ctx.fillStyle
+ let strokeStyle = ctx.strokeStyle
+ if (node._color) ctx.fillStyle = node._color
+ if (node._borderColor) ctx.strokeStyle = node._borderColor
+ ctx.fill()
+ ctx.stroke()
+ ctx.closePath()
+ ctx.fillStyle = fillStyle
+ ctx.strokeStyle = strokeStyle
+ },
+ // draw link to canvas
+ drawLink (ctx, link) {
+ ctx.beginPath()
+ ctx.moveTo(link.source.x, link.source.y)
+ ctx.lineTo(link.target.x, link.target.y)
+ ctx.lineWidth = this.linkWidth
+ ctx.strokeStyle = (link._color) ? link._color : link.color
+ ctx.stroke()
+ },
+ // draw text to canvas
+ drawText (item, ctx, style, key) {
+ ctx = this.setCtx(ctx, style)
+ if (this.fontSize) ctx.font = this.fontSize + 'px ' + style.fontFamily
+ let text = (key) ? item[key] : item.name
+ // let x = (item.size) ? item.x + item.size : item.x
+ // let y = (item.size) ? item.y + (item.size / 2) : item.y
+ let x = item.x + this.labelOffset.x
+ let y = item.y + this.labelOffset.y
+ ctx.fillText(text, x, y)
+ },
+ // render canvas
+ draw (nodes, links, canvas) {
+ if (!this.hitCanvas) this.canvasInit()
+ let ctx = canvas.getContext('2d')
+ let hitCtx = this.hitCanvas.getContext('2d')
+ if (!this.stylesReady && this.CssStyles) {
+ this.getCssStyles()
+ this.resetSprites()
+ }
+ // clean canvas
+ ctx.clearRect(0, 0, this.size.w, this.size.h)
+
+ // draw links
+ ctx = this.setCtx(ctx, this.styles.link)
+ for (let link of links) {
+ if (!this.linksSelected[link.id]) {
+ this.drawLink(ctx, link)
+ }
+ this.mapShape(link, 'link', this.drawLink, hitCtx)
+ }
+
+ // draw selected links
+ ctx = this.setCtx(ctx, this.styles.linkSelected)
+ for (let lid in this.linksSelected) {
+ let link = this.linksSelected[lid]
+
+ if (this.isOnView(link.source) && this.isOnView(link.target)) {
+ this.drawLink(ctx, link)
+ }
+ }
+
+ // draw nodes
+ ctx = this.setCtx(ctx, this.styles.node)
+ for (let node of nodes) {
+ if (this.isOnView(node)) {
+ if (!this.noNodes) {
+ let sprite = this.getNodeSprite(node)
+ ctx.drawImage(sprite, node.x - sprite.width / 2, node.y - sprite.height / 2)
+ // map node shape
+ this.mapShape(node, 'node', this.drawNode, hitCtx)
+ }
+ // draw node labels
+ if (this.nodeLabels) {
+ node.size = this.nodeSize
+ this.drawText(node, ctx, this.labelStyle(node))
+ // ctx = this.setCtx(ctx, this.styles.node)
+ }
+ }
+ }
+ // draw selected nodes
+ ctx = this.setCtx(ctx, this.styles.nodeSelected)
+ for (let nid in this.selected) {
+ let node = this.selected[nid]
+ if (this.isOnView(node)) {
+ // this.drawNode(node, ctx)
+ // let sprite = this.sprites.nodeSelected
+ let sprite = this.getNodeSprite(node)
+ ctx.drawImage(sprite, node.x - sprite.width / 2, node.y - sprite.height / 2)
+ }
+ }
+ },
+ getNodeSprite (node) {
+ let name = this.nodeSpriteName(node)
+ let sprite = this.sprites[name]
+ if (!sprite) { // set style and create sprite
+ let style = this.loadNodeStyle(node)
+ sprite = this.nodeSprite(style)
+ this.sprites[name] = sprite
+ }
+ return sprite
+ },
+ nodeSpriteName (node) {
+ let name = 'node'
+ if (this.selected[node.id]) name += 'Selected'
+ if (node.pinned) name += 'Pinned'
+ if (node._cssClass) name += '-' + node._cssClass
+ if (node._color) name += '-' + stylePicker.compColor(node._color)
+ return name
+ },
+ nodeSprite (style) {
+ let size = this.nodeSize + this.styles.node.lineWidth
+ let canvasSize = (this.nodeSvg) ? size : size * 2
+ let canvas = this.spriteCanvas(canvasSize)
+ let ctx = canvas.getContext('2d')
+ if (this.nodeSvg) {
+ let attrs = { width: size, height: size, class: style._cssClass || '', style: style._cssStyle || '' }
+ let url = svgExport.svgDataToUrl(this.nodeSvg, attrs)
+ if (url) {
+ let img = new Image()
+ img.onload = () => {
+ ctx.drawImage(img, 0, 0)
+ URL.revokeObjectURL(url)
+ }
+ img.onerror = (error) => {
+ // eslint-disable-next-line
+ console.log('error creating node image', error)
+ }
+ img.src = url
+ }
+ } else {
+ ctx = this.setCtx(ctx, style)
+ this.drawNode(ctx, { x: size, y: size })
+ }
+ return canvas
+ },
+ spriteCanvas (size) {
+ let canvas = document.createElement('canvas')
+ canvas.width = size
+ canvas.height = size
+ return canvas
+ },
+ isOnView (obj) {
+ return (obj.x > 0 && obj.y > 0 && obj.x < this.size.w && obj.y < this.size.h)
+ },
+ // index shapes by random colors
+ mapShape (shape, type, drawFunc, hitCtx) {
+ // search unique color index
+ if (!shape.colorIndex) shape.colorIndex = this.newColorIndex()
+ let nShape = Object.assign({}, shape)
+ nShape.color = shape.colorIndex.rgb
+ nShape.borderColor = shape.colorIndex.rgb
+ nShape.type = type
+ // uncoment to debug
+ // hitCtx = this.$refs.canvas.getContext('2d') // to debug
+ let sprite = this.sprites[type] // the color is not important
+ if (sprite) {
+ sprite = this.cloneCanvas(sprite)
+ sprite = this.fillCanvas(sprite, shape.colorIndex)
+ hitCtx.drawImage(sprite, shape.x - sprite.width / 2, shape.y - sprite.height / 2)
+ } else {
+ drawFunc(hitCtx, nShape)
+ }
+ this.shapes[shape.colorIndex.rgb] = nShape
+ },
+ fillCanvas (canvas, color) {
+ let ctx = canvas.getContext('2d')
+ let imgData = ctx.getImageData(0, 0, canvas.width, canvas.height)
+ let pixels = canvas.width * canvas.height * 4
+ for (let p = 3; p <= pixels; p += 4) {
+ if (imgData.data[p] > 0) { // a
+ imgData.data[p] = 255 // sers alpha max to prevent transparency match
+ imgData.data[p - 3] = color.r // r
+ imgData.data[p - 2] = color.g // g
+ imgData.data[p - 1] = color.b // b
+ }
+ }
+ ctx.putImageData(imgData, 0, 0)
+ return canvas
+ },
+ // generates color intex to shapes
+ newColorIndex () {
+ while (true) {
+ let color = this.randomColor()
+ if (!this.shapes[color.rgb]) return color
+ }
+ },
+ // generates random color
+ randomColor () {
+ const r = Math.round(Math.random() * 255)
+ const g = Math.round(Math.random() * 255)
+ const b = Math.round(Math.random() * 255)
+ return { r, g, b, rgb: `rgb(${r},${g},${b})` }
+ },
+ // sets canvas context style
+ setCtx (ctx, conf) {
+ for (let p in conf) {
+ ctx[p] = conf[p]
+ }
+ return ctx
+ },
+ cloneCanvas (canvas) {
+ let newCanvas = document.createElement('canvas')
+ let ctx = newCanvas.getContext('2d')
+ newCanvas.width = canvas.width
+ newCanvas.height = canvas.height
+ ctx.drawImage(canvas, 0, 0)
+ return newCanvas
+ },
+ Sprite (name, cb) {
+ if (!this.sprites[name]) {
+ this.sprites[name] = cb()
+ }
+ return this.sprites[name]
+ },
+ // sets canvas properties form css properies
+ getCssStyles () {
+ let svg = stylePicker.create('svg', 'css-picker')
+ for (let styleName in this.styles) {
+ let style = this.styles[styleName] || {}
+ style = stylePicker.fillStyle(style, svg)
+ }
+ document.body.removeChild(svg)
+ this.stylesReady = true
+ },
+ loadNodeStyle (node) {
+ let styleName = 'node'
+ let selected = this.selected[node.id]
+ if (selected) styleName = 'nodeSelected'
+ if (node.pinned) styleName = 'nodePinned'
+ if (selected && node.pinned) styleName = 'nodeSelectedPinned'
+ // merge styles and update
+ if (node._cssClass) {
+ let name = styleName + '-' + node._cssClass
+ if (!this.styles[name]) {
+ let cStyle = Object.assign({}, this.styles[styleName] || {})
+ cStyle._cssClass = cStyle._cssClass || ''
+ cStyle._cssClass += ' ' + node._cssClass
+ this.updateStyle(name, cStyle)
+ }
+ styleName = name
+ }
+ let style = Object.assign({}, this.styles[styleName] || this.updateStyle(styleName))
+ if (node._color) {
+ style.fillStyle = node._color
+ style._cssStyle = 'fill:' + node._color
+ }
+ if (node._cssClass) {
+ style._cssClass += ' ' + node._cssClass
+ }
+ return style
+ },
+ updateStyle (styleName, style) {
+ style = style || this.styles[styleName] || {}
+ let svg = stylePicker.create('svg', 'css-picker')
+ style = stylePicker.fillStyle(style, svg)
+ this.styles[styleName] = style
+ document.body.removeChild(svg)
+ return style
+ },
+ getCssColor (color) {
+ let el = stylePicker.create('div', 'color-picker')
+ let id = el.id
+ el.setAttribute('style', 'background-color:' + color)
+ let style = stylePicker.mapStyle(id, { fillStyle: 'background-color' }, [])
+ document.body.removeChild(el)
+ return style
+ },
+ labelStyle (node) {
+ let style = this.styles.labels
+ let labelClass = node._labelClass
+ if (labelClass) {
+ let styleName = 'labels-' + labelClass
+ let labelStyle = this.styles[styleName]
+ if (!labelStyle) {
+ labelStyle = Object.assign({}, style)
+ labelStyle._cssClass += ' ' + labelClass
+ labelStyle = this.updateStyle(styleName, labelStyle)
+ }
+ style = labelStyle
+ }
+ return style
+ }
+ }
+}
+</script>
+<style lang="scss">
+ canvas{
+ position:absolute;
+ top:0;
+ left:0;
+ }
+</style>
diff --git a/src/components/serfDiagram/vue-d3-network/components/svgRenderer.vue b/src/components/serfDiagram/vue-d3-network/components/svgRenderer.vue
new file mode 100644
index 0000000..ce5f8f3
--- /dev/null
+++ b/src/components/serfDiagram/vue-d3-network/components/svgRenderer.vue
@@ -0,0 +1,207 @@
+<template lang="pug">
+ svg(
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink= "http://www.w3.org/1999/xlink"
+ ref="svg"
+ :width="size.w"
+ :height="size.h"
+ class="net-svg"
+ @mouseup='emit("dragEnd",[$event])'
+ @touchend.passive='emit("dragEnd",[$event])'
+ @touchstart.passive=''
+ )
+
+ //-> links
+ g.links#l-links
+ path(v-for="link in links"
+ :d="linkPath(link)"
+ :id="link.id"
+ @click='emit("linkClick",[$event,link])'
+ @touchstart.passive='emit("linkClick",[$event,link])'
+ v-bind='linkAttrs(link)'
+ :class='linkClass(link.id)'
+ :style='linkStyle(link)'
+ )
+
+ //- -> nodes
+ g.nodes#l-nodes(v-if='!noNodes')
+ template(v-for='(node,key) in nodes')
+ svg(v-if='svgIcon(node)'
+ :key='key'
+ :viewBox='svgIcon(node).attrs.viewBox'
+ :width='getNodeSize(node, "width")'
+ :height='getNodeSize(node, "height")'
+ @click='emit("nodeClick",[$event,node])'
+ @mouseover='emit("nodeHover",[$event,node])'
+ @mouseout='emit("nodeOut",[$event,node])'
+ @touchend.passive='emit("nodeClick",[$event,node])'
+ @mousedown.prevent='emit("dragStart",[$event,key])'
+ @touchstart.prevent='emit("dragStart",[$event,key])'
+ :x='node.x - getNodeSize(node, "width") / 2'
+ :y='node.y - getNodeSize(node, "height") / 2'
+ :style='nodeStyle(node)'
+ :title="node.name"
+ :class='nodeClass(node,["node-svg"])'
+ v-html='svgIcon(node).data'
+ v-bind='node._svgAttrs'
+ )
+
+ //- default circle nodes
+ circle(v-else
+ :key='key'
+ :r="getNodeSize(node) / 2"
+ @click='emit("nodeClick",[$event,node])'
+ @mouseover='emit("nodeHover",[$event,node])'
+ @mouseout='emit("nodeOut",[$event,node])'
+ @touchend.passive='emit("nodeClick",[$event,node])'
+ @mousedown.prevent='emit("dragStart",[$event,key])'
+ @touchstart.prevent='emit("dragStart",[$event,key])'
+ :cx="node.x"
+ :cy="node.y"
+ :style='nodeStyle(node)'
+ :title="node.name"
+ :class="nodeClass(node)"
+ v-bind='node._svgAttrs'
+ )
+
+ //-> Links Labels
+ g.labels#link-labels(v-if='linkLabels')
+ text.link-label(v-for="link in links" :font-size="fontSize" )
+ textPath(v-bind:xlink:href="'#' + link.id" startOffset= "50%") {{ link.name }}
+
+ //- -> Node Labels
+ g.labels#node-labels( v-if="nodeLabels")
+ text.node-label(v-for="node in nodes"
+ :x='node.x + (getNodeSize(node) / 2) + (node._size / 2)'
+ :y='node.y + labelOffset.y'
+ :font-size="node._size"
+ :class='(node._labelClass) ? node._labelClass : ""'
+ :style='{opacity:node._opacity}'
+ :stroke-width='node._size / 8'
+ ) {{ node.name }}
+</template>
+<script>
+import svgExport from "../lib/js/svgExport.js";
+
+export default {
+ name: "svg-renderer",
+ props: [
+ "size",
+ "nodes",
+ "noNodes",
+ "selected",
+ "linksSelected",
+ "links",
+ "nodeSize",
+ "padding",
+ "fontSize",
+ "strLinks",
+ "linkWidth",
+ "nodeLabels",
+ "linkLabels",
+ "labelOffset",
+ "nodeSym"
+ ],
+
+ computed: {
+ nodeSvg() {
+ if (this.nodeSym) {
+ return svgExport.toObject(this.nodeSym);
+ }
+ return null;
+ }
+ },
+ methods: {
+ getNodeSize(node, side) {
+ let size = node._size || this.nodeSize;
+ if (side) size = node["_" + side] || size;
+ return size;
+ },
+ svgIcon(node) {
+ return node.svgObj || this.nodeSvg;
+ },
+ emit(e, args) {
+ this.$emit("action", e, args);
+ },
+ svgScreenShot(cb, toSvg, background, allCss) {
+ let svg = svgExport.export(this.$refs.svg, allCss);
+ if (!toSvg) {
+ if (!background) background = this.searchBackground();
+ let canvas = svgExport.makeCanvas(this.size.w, this.size.h, background);
+ svgExport.svgToImg(svg, canvas, (err, img) => {
+ if (err) cb(err);
+ else cb(null, img);
+ });
+ } else {
+ cb(null, svgExport.save(svg));
+ }
+ },
+ linkClass(linkId) {
+ let cssClass = ["link"];
+ if (this.linksSelected.hasOwnProperty(linkId)) {
+ cssClass.push("selected");
+ }
+ if (!this.strLinks) {
+ cssClass.push("curve");
+ }
+ return cssClass;
+ },
+ linkPath(link) {
+ let d = {
+ M: [link.source.x | 0, link.source.y | 0],
+ X: [link.target.x | 0, link.target.y | 0]
+ };
+ if (this.strLinks) {
+ return "M " + d.M.join(" ") + " L" + d.X.join(" ");
+ } else {
+ d.Q = [link.source.x, link.target.y];
+ return "M " + d.M + " Q " + d.Q.join(" ") + " " + d.X;
+ }
+ },
+ nodeStyle(node) {
+ return (
+ (node._color ? "fill: " + node._color : "") +
+ ";opacity:" +
+ node._opacity
+ );
+ },
+ linkStyle(link) {
+ let style = {};
+ if (link._color) style.stroke = link._color;
+ return style;
+ },
+ nodeClass(node, classes = []) {
+ let cssClass = node._cssClass ? node._cssClass : [];
+ if (!Array.isArray(cssClass)) cssClass = [cssClass];
+ cssClass.push("node");
+ classes.forEach(c => cssClass.push(c));
+ if (this.selected[node.id]) cssClass.push("selected");
+ if (node.fx || node.fy) cssClass.push("pinned");
+ return cssClass;
+ },
+ searchBackground() {
+ let vm = this;
+ while (vm.$parent) {
+ let style = window.getComputedStyle(vm.$el);
+ let background = style.getPropertyValue("background-color");
+ let rgb = background.replace(/[^\d,]/g, "").split(",");
+ let sum = rgb.reduce((a, b) => parseInt(a) + parseInt(b), 0);
+ if (sum > 0) return background;
+ vm = vm.$parent;
+ }
+ return "white";
+ },
+ spriteSymbol() {
+ let svg = this.nodeSym;
+ if (svg) {
+ return svgExport.toSymbol(svg);
+ }
+ },
+ linkAttrs(link) {
+ let attrs = link._svgAttrs || {};
+ attrs["stroke-width"] = attrs["stroke-width"] || this.linkWidth;
+ return attrs;
+ }
+ }
+};
+</script>
diff --git a/src/components/serfDiagram/vue-d3-network/index.vue b/src/components/serfDiagram/vue-d3-network/index.vue
new file mode 100644
index 0000000..6b7ff4e
--- /dev/null
+++ b/src/components/serfDiagram/vue-d3-network/index.vue
@@ -0,0 +1,504 @@
+<script>
+import * as forceSimulation from "d3-force";
+import svgRenderer from "./components/svgRenderer.vue";
+import canvasRenderer from "./components/canvasRenderer.vue";
+import saveImage from "./lib/js/saveImage.js";
+import svgExport from "./lib/js/svgExport.js";
+const d3 = Object.assign({}, forceSimulation);
+
+export default {
+ name: "d3-network",
+ components: {
+ canvasRenderer,
+ svgRenderer
+ },
+ props: {
+ netNodes: {
+ type: Array
+ },
+ netLinks: {
+ type: Array
+ },
+ options: {
+ type: Object
+ },
+ nodeSym: {
+ type: String
+ },
+ nodeCb: {
+ type: Function
+ },
+ linkCb: {
+ type: Function
+ },
+ simCb: {
+ type: Function
+ },
+ customForces: {
+ type: Object
+ },
+ selection: {
+ type: Object,
+ default: () => {
+ return {
+ nodes: {},
+ links: {}
+ };
+ }
+ }
+ },
+ data() {
+ return {
+ canvas: false,
+ nodes: [],
+ links: [],
+ size: {
+ w: 500,
+ h: 420
+ },
+ offset: {
+ x: 0,
+ y: 0
+ },
+ clientOffset: {
+ x: 0,
+ y: 0
+ },
+ force: 500,
+ forces: {
+ Center: false,
+ X: 0.5,
+ Y: 0.5,
+ ManyBody: true,
+ Link: true
+ },
+ noNodes: false,
+ strLinks: true,
+ fontSize: 10,
+ dragging: false,
+ linkWidth: 1,
+ nodeLabels: false,
+ linkLabels: false,
+ nodeSize: 5,
+ mouseOfst: {
+ x: 0,
+ y: 0
+ },
+ padding: {
+ x: 0,
+ y: 0
+ },
+ simulation: null,
+ nodeSvg: null,
+ resizeListener: true
+ };
+ },
+ render(createElement) {
+ let ref = "svg";
+ let props = {};
+ let renderer = "svg-renderer";
+ let bindProps = [
+ "size",
+ "nodes",
+ "links",
+ "selected",
+ "linksSelected",
+ "strLinks",
+ "linkWidth",
+ "nodeLabels",
+ "linkLabels",
+ "fontSize",
+ "labelOffset",
+ "offset",
+ "padding",
+ "nodeSize",
+ "noNodes"
+ ];
+
+ for (let prop of bindProps) {
+ props[prop] = this[prop];
+ }
+ props.nodeSym = this.nodeSvg;
+
+ if (this.canvas) {
+ renderer = "canvas-renderer";
+ ref = "canvas";
+ props.canvasStyles = this.options.canvasStyles;
+ }
+
+ return createElement(
+ "div",
+ {
+ attrs: { class: "net" },
+ on: { mousemove: this.move, "&touchmove": this.move }
+ },
+ [
+ createElement(renderer, {
+ props,
+ ref,
+ on: { action: this.methodCall }
+ })
+ ]
+ );
+ },
+ created() {
+ this.updateOptions(this.options);
+ this.buildNodes(this.netNodes);
+ this.links = this.buildLinks(this.netLinks);
+ this.updateNodeSvg();
+ },
+ mounted() {
+ this.$nextTick(() => {
+ this.onResize();
+ this.animate();
+ });
+ if (this.resizeListener) window.addEventListener("resize", this.onResize);
+ },
+ beforeDestroy() {
+ if (this.resizeListener)
+ window.removeEventListener("resize", this.onResize);
+ },
+ computed: {
+ selected() {
+ return this.selection.nodes;
+ },
+ linksSelected() {
+ return this.selection.links;
+ },
+ center() {
+ return {
+ x: this.size.w / 2 + this.size.w / 200 + this.offset.x,
+ y: this.size.h / 2 + this.size.h / 200 + this.offset.y
+ };
+ },
+ labelOffset() {
+ return {
+ x: this.nodeSize / 2 + this.fontSize / 2,
+ y: this.fontSize / 2
+ };
+ }
+ },
+ watch: {
+ netNodes(newValue) {
+ this.buildNodes(newValue);
+ this.reset();
+ },
+ netLinks(newValue, oldValue) {
+ this.links = this.buildLinks(newValue);
+ this.reset();
+ },
+ nodeSym() {
+ this.updateNodeSvg();
+ },
+ options(newValue, oldValue) {
+ this.updateOptions(newValue);
+ if (oldValue.size && newValue.size) {
+ if (
+ oldValue.size.w !== newValue.size.w ||
+ oldValue.size.h !== newValue.size.h
+ ) {
+ this.onResize();
+ }
+ }
+ this.animate();
+ }
+ },
+ methods: {
+ updateNodeSvg() {
+ let svg = null;
+ if (this.nodeSym) {
+ svg = svgExport.svgElFromString(this.nodeSym);
+ }
+ this.nodeSvg = svg;
+ },
+ methodCall(action, args) {
+ let method = this[action];
+ if (method && typeof method === "function") {
+ if (args) method(...args);
+ else method();
+ }
+ },
+ onResize() {
+ let size = this.options.size;
+ if (!size || !size.w) this.size.w = this.$el.clientWidth;
+ if (!size || !size.h) this.size.h = this.$el.clientHeight;
+ this.padding.x = 0;
+ this.padding.y = 0;
+ // serach offsets of parents
+ let vm = this;
+ while (vm.$parent) {
+ this.padding.x += vm.$el.offsetLeft || 0;
+ this.padding.y += vm.$el.offsetTop || 0;
+ vm = vm.$parent;
+ }
+ this.animate();
+ },
+ // -- Data
+ updateOptions(options) {
+ for (let op in options) {
+ if (this.hasOwnProperty(op)) {
+ this[op] = options[op];
+ }
+ }
+ },
+ buildNodes(nodes) {
+ let vm = this;
+ this.nodes = nodes.map((node, index) => {
+ // node formatter option
+ node = this.itemCb(this.nodeCb, node);
+ // index as default node id
+ if (!node.id && node.id !== 0) vm.$set(node, "id", index);
+ // initialize node coords
+ if (!node.x) vm.$set(node, "x", 0);
+ if (!node.y) vm.$set(node, "y", 0);
+ // node default name, allow string 0 as name
+ if (!node.name && node.name !== "0")
+ vm.$set(node, "name", "node " + node.id);
+ if (node.svgSym) {
+ node.svgIcon = svgExport.svgElFromString(node.svgSym);
+ if (!this.canvas && node.svgIcon && !node.svgObj)
+ node.svgObj = svgExport.toObject(node.svgIcon);
+ }
+
+ if (!node._size) {
+ vm.$set(
+ node,
+ "_size",
+ parseInt(Math.random() * (30 - 15 + 1) + 10, 10)
+ );
+ vm.$set(node, "size", node._size);
+ }
+
+ if (!node.opacity) {
+ vm.$set(node, "_opacity", node._size / 30);
+ vm.$set(node, "opacity", node._opacity);
+ }
+
+ return node;
+ });
+ },
+
+ buildLinks(links) {
+ let vm = this;
+ return links.concat().map((link, index) => {
+ // link formatter option
+ link = this.itemCb(this.linkCb, link);
+ // source and target for d3
+ link.source = link.sid;
+ link.target = link.tid;
+ if (!link.id) vm.$set(link, "id", "link-" + index);
+ return link;
+ });
+ },
+ itemCb(cb, item) {
+ if (cb && typeof cb === "function") item = cb(item);
+ return item;
+ },
+ // -- Animation
+ simulate(nodes, links) {
+ let forces = this.forces;
+ let sim = d3
+ .forceSimulation()
+ .stop()
+ .alpha(0.5)
+ // .alphaMin(0.05)
+ .nodes(nodes);
+
+ if (forces.Center !== false)
+ sim.force("center", d3.forceCenter(this.center.x, this.center.y));
+ if (forces.X !== false) {
+ sim.force("X", d3.forceX(this.center.x).strength(forces.X));
+ }
+ if (forces.Y !== false) {
+ sim.force("Y", d3.forceY(this.center.y).strength(forces.Y));
+ }
+ if (forces.ManyBody !== false) {
+ sim.force("charge", d3.forceManyBody().strength(-this.force));
+ }
+ if (forces.Link !== false) {
+ sim.force(
+ "link",
+ d3.forceLink(links).id(function(d) {
+ return d.id;
+ })
+ );
+ }
+ sim = this.setCustomForces(sim);
+ sim = this.itemCb(this.simCb, sim);
+ return sim;
+ },
+ setCustomForces(sim) {
+ let forces = this.customForces;
+ if (forces) {
+ for (let f in forces) {
+ let d3Func = this.getD3Func("force" + f);
+ if (d3Func) {
+ let args = forces[f];
+ sim.force("custom" + f, d3Func(...args));
+ }
+ }
+ }
+ return sim;
+ },
+ getD3Func(name) {
+ let func = d3[name];
+ if (func && typeof func === "function") return func;
+ return null;
+ },
+ animate() {
+ if (this.simulation) this.simulation.stop();
+ if (this.forces.Link !== false)
+ this.simulation = this.simulate(this.nodes, this.links);
+ else this.simulation = this.simulate(this.nodes);
+ this.simulation.restart();
+ },
+ reset() {
+ this.animate();
+ this.nodes = this.simulation.nodes();
+ if (this.forces.links) this.links = this.simulation.force("link").links();
+ },
+ // -- Mouse Interaction
+ move(event) {
+ let pos = this.clientPos(event);
+ if (this.dragging !== false) {
+ if (this.nodes[this.dragging]) {
+ this.simulation.restart();
+ this.simulation.alpha(0.5);
+ this.nodes[this.dragging].fx = pos.x - this.mouseOfst.x;
+ this.nodes[this.dragging].fy = pos.y - this.mouseOfst.y;
+ }
+ }
+ },
+ clientPos(event) {
+ let x = event.touches ? event.touches[0].clientX : event.clientX;
+ let y = event.touches ? event.touches[0].clientY : event.clientY;
+ x = x || 0;
+ y = y || 0;
+ return { x, y };
+ },
+ dragStart(event, nodeKey) {
+ this.dragging = nodeKey === false ? false : nodeKey;
+ this.setMouseOffset(event, this.nodes[nodeKey]);
+ if (this.dragging === false) {
+ this.simulation.alpha(0.1);
+ this.simulation.restart();
+ this.setMouseOffset();
+ }
+ this.$emit("drag-start", event, nodeKey);
+ },
+ dragEnd(event) {
+ let node = this.nodes[this.dragging];
+ if (node && !node.pinned) {
+ // unfix node position
+ node.fx = null;
+ node.fy = null;
+ }
+ this.dragStart(false);
+ this.$emit("drag-end", event);
+ },
+ // -- Render helpers
+ nodeClick(event, node) {
+ this.$emit("node-click", event, node);
+ },
+ nodeHover(event, node) {
+ this.$emit("node-hover", event, node);
+ },
+ nodeOut(event, node) {
+ this.$emit("node-out", event, node);
+ },
+ linkClick(event, link) {
+ this.$emit("link-click", event, link);
+ },
+ setMouseOffset(event, node) {
+ let x = 0;
+ let y = 0;
+ if (event && node) {
+ let pos = this.clientPos(event);
+ x = pos.x ? pos.x - node.x : node.x;
+ y = pos.y ? pos.y - node.y : node.y;
+ }
+ this.mouseOfst = { x, y };
+ },
+ screenShot(name, bgColor, toSVG, svgAllCss) {
+ let exportFunc;
+ let args = [];
+ if (this.canvas) {
+ toSVG = false;
+ exportFunc = this.$refs.canvas.canvasScreenShot;
+ args = [bgColor];
+ } else {
+ exportFunc = this.$refs.svg.svgScreenShot;
+ args = [toSVG, bgColor, svgAllCss];
+ }
+ if (toSVG) name = name || "export.svg";
+
+ exportFunc((err, url) => {
+ if (!err) {
+ if (!toSVG) saveImage.save(url, name);
+ else saveImage.download(url, name);
+ }
+ this.$emit("screen-shot", err);
+ }, ...args);
+ }
+ }
+};
+</script>
+
+<style lang="stylus">
+@import 'lib/styl/vars.styl';
+
+.net {
+ height: 100%;
+ margin: 0;
+}
+
+.net-svg {
+ // fill: white // background color to export as image
+}
+
+.node {
+ stroke: alpha($dark, 0.7);
+ stroke-width: 3px;
+ transition: fill 0.5s ease;
+ fill: $white;
+}
+
+.node.selected {
+ stroke: $color2;
+}
+
+.node.pinned {
+ stroke: alpha($warn, 0.6);
+}
+
+.link {
+ stroke: alpha($dark, 0.3);
+}
+
+.node, .link {
+ stroke-linecap: round;
+
+ &:hover {
+ stroke: $warn;
+ stroke-width: 5px;
+ }
+}
+
+.link.selected {
+ stroke: alpha($color2, 0.6);
+}
+
+.curve {
+ fill: none;
+}
+
+.node-label {
+ fill: $dark;
+}
+
+.link-label {
+ fill: $dark;
+ transform: translate(0, -0.5em);
+ text-anchor: middle;
+}
+</style>
diff --git a/src/components/serfDiagram/vue-d3-network/lib/js/canvasStyles.js b/src/components/serfDiagram/vue-d3-network/lib/js/canvasStyles.js
new file mode 100644
index 0000000..fb181f1
--- /dev/null
+++ b/src/components/serfDiagram/vue-d3-network/lib/js/canvasStyles.js
@@ -0,0 +1,56 @@
+/**
+ * This styles are used to 'map' svg-css styles to canvas elements
+ * creating svg elements and getting computed styles properties from them
+ *
+ * Object keys as style names.
+ * Property '_cssClass', Required, String, css class to pick style
+ * Property '_svgElement', Optional, String type of svg element,
+ * Property '_svgAttrs', Optional,Object, svg element attributes
+ * see supported elements in stylePicker -> canvasPicker()
+ * or add property _svgAttrs to use any svg element
+ *
+ */
+export default {
+ background: {
+ _cssClass: 'net-svg',
+ fillStyle: 'white'
+ },
+ node: {
+ _cssClass: 'node', // name of the class to pick properties
+ fillStyle: 'green',
+ strokeStyle: 'orange',
+ lineWidth: 2
+ },
+ link: {
+ _cssClass: 'link',
+ strokeStyle: 'blue',
+ lineWidth: 1
+ },
+ labels: {
+ _cssClass: 'node-label',
+ _svgElement: 'text', // svg element to pick properties
+ fillStyle: 'black',
+ fontFamily: 'Arial'
+ },
+ nodeSelected: {
+ _cssClass: 'node selected',
+ fillStyle: 'red',
+ strokeStyle: 'orange',
+ lineWidth: 2
+ },
+ linkSelected: {
+ _cssClass: 'link selected',
+ strokeStyle: 'green',
+ lineWidth: 2
+ },
+ nodePinned: {
+ _cssClass: 'node pinned',
+ fillStyle: 'green',
+ strokeStyle: 'red'
+ },
+ nodeSelectedPinned: {
+ _cssClass: 'node selected pinned',
+ fillStyle: 'green',
+ strokeStyle: 'red'
+ }
+}
diff --git a/src/components/serfDiagram/vue-d3-network/lib/js/saveImage.js b/src/components/serfDiagram/vue-d3-network/lib/js/saveImage.js
new file mode 100644
index 0000000..a51e968
--- /dev/null
+++ b/src/components/serfDiagram/vue-d3-network/lib/js/saveImage.js
@@ -0,0 +1,28 @@
+export default {
+ save (img, name) {
+ if (img) {
+ img = this.dataURIToBlob(img, (blob) => {
+ let url = URL.createObjectURL(blob)
+ this.download(url, name)
+ })
+ }
+ },
+ dataURIToBlob (dataURI, cb) {
+ let binStr = atob(dataURI.split(',')[1])
+ let len = binStr.length
+ let arr = new Uint8Array(len)
+ for (var i = 0; i < len; i++) {
+ arr[i] = binStr.charCodeAt(i)
+ }
+ cb(new Blob([arr]))
+ },
+ download (url, name) {
+ name = name || ''
+ let link = document.createElement('a')
+ link.setAttribute('href', url)
+ link.setAttribute('download', name)
+ let el = document.body.appendChild(link)
+ link.click()
+ document.body.removeChild(el)
+ }
+}
diff --git a/src/components/serfDiagram/vue-d3-network/lib/js/stylePicker.js b/src/components/serfDiagram/vue-d3-network/lib/js/stylePicker.js
new file mode 100644
index 0000000..6b68f38
--- /dev/null
+++ b/src/components/serfDiagram/vue-d3-network/lib/js/stylePicker.js
@@ -0,0 +1,78 @@
+export default {
+ randomId () {
+ return Math.random().toString(36).substring(7)
+ },
+
+ // gets canvas style from css properties
+ fillStyle (style, svg) {
+ let pseudo = null
+ let id = 'picker-' + this.randomId()
+ let el = this.canvasPicker(style, id)
+ // to replace 'px'
+ svg.appendChild(el)
+ let props = {
+ fillStyle: 'fill',
+ strokeStyle: 'stroke',
+ lineWidth: 'stroke-width',
+ fontFamily: 'font-family'
+ }
+ style = this.mapStyle(id, props, style, pseudo)
+ svg.removeChild(el)
+ return style
+ },
+ mapStyle (id, props, style, pseudo, numberValues) {
+ let cStyle = window.getComputedStyle(document.getElementById(id), pseudo)
+ numberValues = numberValues || ['lineWidth']
+ for (let p in props) {
+ let value = cStyle.getPropertyValue(props[p])
+ if (numberValues.indexOf(p) > -1) value = parseInt(value, 10)
+ if (value) {
+ style[p] = value
+ }
+ }
+ return style
+ },
+ // creates svg elements to pick css properties
+ canvasPicker (style, id) {
+ let attrs = style._svgAttrs || {}
+ let element = style._svgElement || 'circle'
+ if (!style._svgAttrs) {
+ switch (element) {
+ case 'text':
+ attrs = { x: 10, y: 10, fontSize: 20 }
+ break
+ case 'circle':
+ attrs = { cx: 10, cy: 10, r: 10 }
+ break
+ }
+ }
+ attrs.class = style._cssClass
+ attrs.id = id
+ return this.svgCreate(element, attrs)
+ },
+ compColor (color) {
+ let el = document.createElement('div')
+ el.style.backgroundColor = color
+ document.body.appendChild(el)
+ let nColor = window.getComputedStyle(el, null).getPropertyValue('background-color')
+ document.body.removeChild(el)
+ return nColor
+ },
+ // creates svg element
+ svgCreate (element, attrs) {
+ let el = document.createElementNS('http://www.w3.org/2000/svg', element)
+ for (let a in attrs) {
+ el.setAttributeNS(null, a, attrs[a])
+ }
+ return el
+ },
+ create (element, idPref, appendTo) {
+ appendTo = appendTo || 'body'
+ let el = document.createElement(element)
+ let id = idPref || ''
+ id += this.randomId()
+ el.setAttribute('id', id)
+ document[appendTo].appendChild(el)
+ return el
+ }
+}
diff --git a/src/components/serfDiagram/vue-d3-network/lib/js/svgExport.js b/src/components/serfDiagram/vue-d3-network/lib/js/svgExport.js
new file mode 100644
index 0000000..9ed7c58
--- /dev/null
+++ b/src/components/serfDiagram/vue-d3-network/lib/js/svgExport.js
@@ -0,0 +1,143 @@
+export default {
+ NS: 'http://www.w3.org/2000/svg',
+ // svgOrg: svg element
+ // allCss : true includes all svg css styles, false includes only matched styles
+ export (svgOrg, allCss) {
+ let svg = null
+ if (this.isSvgData(svgOrg)) {
+ svg = svgOrg.cloneNode(true)
+ let childs = svgOrg.parentNode.querySelectorAll('*')
+ let cssStyle = {}
+ let rules = this.getcssRules()
+
+ for (let child of childs) {
+ let elRules = rules
+ if (!allCss) {
+ elRules = rules.filter((rule) => {
+ return child.matches(rule.selectorText)
+ })
+ }
+ for (let rule of elRules) {
+ cssStyle[rule.selectorText] = rule.cssText
+ }
+ }
+ let css = Object.values(cssStyle).join('\n')
+ if (css) {
+ let style = document.createElementNS(this.NS, 'style')
+ style.type = 'text/css'
+ svg.insertBefore(style, svg.childNodes[0])
+ style.innerHTML = css
+ svg.appendChild(style)
+ }
+ }
+ return svg
+ },
+
+ makeCanvas (width, height, background) {
+ let canvas = document.createElement('canvas')
+ canvas.width = width
+ canvas.height = height
+ let ctx = canvas.getContext('2d')
+ ctx.fillStyle = background || 'white'
+ ctx.fillRect(0, 0, canvas.width, canvas.height)
+ return canvas
+ },
+
+ serialize (svg) {
+ return (new XMLSerializer()).serializeToString(svg)
+ },
+
+ svgToImg (svg, canvas, cb) {
+ let xml = this.serialize(svg)
+ let img = new Image()
+ let ctx = canvas.getContext('2d')
+ img.onload = function () {
+ ctx.drawImage(this, 0, 0)
+ let png = canvas.toDataURL('image/png')
+ cb(null, png, ctx)
+ }
+ img.onerror = function (err) {
+ cb(err)
+ }
+ img.src = 'data:image/svg+xml;base64,' + btoa(unescape(encodeURIComponent(xml)))
+ },
+
+ save (svg) {
+ return 'data:image/svg+xml;charset=utf-8,' + encodeURIComponent(this.serialize(svg))
+ },
+
+ getcssRules () {
+ let rules = []
+ for (let styles of document.styleSheets) {
+ let styleRules = this.readRules(styles)
+ for (let rule of styleRules) {
+ if (rule && rule.cssText) {
+ rules.push(rule)
+ }
+ }
+ }
+ return rules
+ },
+
+ readRules (styles) {
+ try {
+ if (!styles.cssRules) return styles.rules || []
+ } catch (e) {
+ // Firefox returns Security Error if stylesheet originates from different domain
+ if (e.name !== 'SecurityError') throw e
+ return []
+ }
+ return styles.cssRules
+ },
+
+ toDom (svgData) {
+ let div = document.createElement('div')
+ div.innerHTML = svgData
+ return div.firstChild || null
+ },
+
+ toObject (svg) {
+ if (svg) {
+ let attrs = {}
+ if (svg.attributes) {
+ for (let i = svg.attributes.length; i >= 0; i--) {
+ let a = svg.attributes[i]
+ if (a) attrs[a.name] = a.value
+ }
+ }
+ let data = svg.innerHTML
+ if (data) return { attrs, data }
+ }
+ return null
+ },
+
+ svgElFromString (svgData) {
+ let svgEl = this.toDom(svgData)
+ if (!this.isSvgData(svgEl)) return
+ svgEl.setAttribute('xmlns', 'http://www.w3.org/2000/svg')
+ return svgEl
+ },
+
+ svgDataToUrl (svgData, attrs) {
+ if (typeof (attrs) === 'object') {
+ for (let a in attrs) {
+ let attribute = (attrs[a]) ? (attrs[a]) : ''
+ svgData.setAttribute(a, attribute)
+ }
+ }
+ let svg = this.export(svgData)
+ if (svg) return this.svgToUrl(this.serialize(svg))
+ return null
+ },
+
+ isSvgData (svgData) {
+ if (!svgData.firstChild) return false
+ return (svgData.firstChild.parentNode.nodeName === 'svg')
+ },
+
+ svgToUrl (svg) {
+ let xml = new Blob([svg], { type: 'image/svg+xml' })
+ let url = URL.createObjectURL(xml)
+ return url
+ }
+}
diff --git a/src/components/serfDiagram/vue-d3-network/lib/styl/node-style.styl b/src/components/serfDiagram/vue-d3-network/lib/styl/node-style.styl
new file mode 100644
index 0000000..da31e19
--- /dev/null
+++ b/src/components/serfDiagram/vue-d3-network/lib/styl/node-style.styl
@@ -0,0 +1,6 @@
+@import 'vars.styl'
+.node #fill
+ fill $mid
+.node.selected
+ #fill
+ fill lighten($color2,40%)
\ No newline at end of file
diff --git a/src/components/serfDiagram/vue-d3-network/lib/styl/vars.styl b/src/components/serfDiagram/vue-d3-network/lib/styl/vars.styl
new file mode 100644
index 0000000..42a23e2
--- /dev/null
+++ b/src/components/serfDiagram/vue-d3-network/lib/styl/vars.styl
@@ -0,0 +1,21 @@
+$color2 = #caa455
+$color = #1aad8d
+// $color2 = #E3A826
+$white = lightness($color, 92%)
+$dark = lightness($color, 27%)
+$darkness = #225057
+$bg = saturation(lightness($color,25%),30%)
+//$bg = saturation(lightness($color,30%),20%)
+$bg = saturation(lightness($color,80%),15%)
+$bg-plus = saturation(lightness($color,75%),30%)
+$warn = #be385d
+$light = #f5fffc
+$mid = lightness($color, 55%)
+
+$border = $color solid 2px
+$txt-sh = 1px 1px 1px rgba(0,0,0,.5)
+$box-sh = 1px 1px 2px rgba(0,0,0,0.7)
+$sh = 1px 1px 2px rgba(0,0,0,0.5)
+$hard-sh = 2px 2px 4px rgba(0,0,0,.8)
+
+$sym-close = "鉁�"
\ No newline at end of file
diff --git a/src/components/subComponents/FileUpload/index.vue b/src/components/subComponents/FileUpload/index.vue
index 97c4562..b5ff901 100644
--- a/src/components/subComponents/FileUpload/index.vue
+++ b/src/components/subComponents/FileUpload/index.vue
@@ -149,14 +149,14 @@
},
computeMD5Success(md5, file) {
// 灏嗚嚜瀹氫箟鍙傛暟鐩存帴鍔犺浇uploader瀹炰緥鐨刼pts涓�
- if (this.$route.path.indexOf("VideoManage") >= 0) {
- Object.assign(this.uploader.opts, {
- query: {
- stackId: this.DataStackPool.selectedDir.id
- // ...this.params,
- }
- })
- }
+ // if (this.$route.path.indexOf("VideoManage") >= 0) {
+ // Object.assign(this.uploader.opts, {
+ // query: {
+ // stackId: this.DataStackPool.selectedDir.id
+ // // ...this.params,
+ // }
+ // })
+ // }
file.uniqueIdentifier = md5;
file.resume();
this.statusText.paused = "鏆傚仠涓�";
diff --git a/src/pages/algorithmManage/index/App.vue b/src/pages/algorithmManage/index/App.vue
index 34488d2..c2966a5 100644
--- a/src/pages/algorithmManage/index/App.vue
+++ b/src/pages/algorithmManage/index/App.vue
@@ -63,9 +63,10 @@
<div class="list-complete-item-handle">
<!-- <span :class="`iconfont ${item.icon}`" style="font-size:3rem;"></span> -->
<div class="svg-wrap">
- <svg class="icon" aria-hidden="true" style="font-size:7rem;">
+ <!-- <svg class="icon" aria-hidden="true" style="font-size:7rem;">
<use :xlink:href="`#${item.icon}`" />
- </svg>
+ </svg> -->
+ <img class="baseImg" :src="`data:image/png;base64,${item.iconBlob}`" alt="">
</div>
<div class="alg-name">
<div style="padding:0px 10px 0px 10px;">
@@ -729,16 +730,38 @@
installSdk
} from "./api";
import FileUploader from "@/components/subComponents/FileUpload/index";
-
+import TaskManage from "@/Pool/TaskMange";
+import VideoManageData from "@/Pool/VideoManageData";
export default {
name: "algorithmManage",
props: {},
components: {
FileUploader
},
-
+ computed: {
+ notInstalledList() {
+ return this.TaskMange.list1.filter(sdk => {
+ return sdk.installed === false;
+ });
+ },
+ installedList() {
+ return this.TaskMange.list1.filter(sdk => {
+ debugger
+ return sdk.installed === true;
+ });
+ },
+ ungradeList() {
+ // 鍗囩骇澶勭悊浼氬鑷撮噸澶嶇殑key,闇�瑕佷慨鏀�
+ return [];
+ return this.TaskMange.list1.filter(sdk => {
+ return sdk.isUpgrade === true;
+ });
+ }
+ },
data() {
return {
+ TaskMange: new TaskManage,
+ VideoManageData: new VideoManageData,
activeName: "myAlgorithm",
patchUpdateStatus: "",
dragging: false,
@@ -804,8 +827,818 @@
installPercentage: 0
}
},
- methods: {},
- mounted() {}
+ watch: {
+ list2: {
+ handler(newVal, oldVal) {
+ // window.console.log(newVal, oldVal, '鐩戝惉list2')
+ if (newVal !== oldVal) {
+ // window.console.log(newVal, '鐩戝惉list2')
+ newVal.map((i, index) => {
+ i.child.map(j => {
+ this.$set(j, "parentId", i.id);
+ });
+ });
+ }
+ },
+ deep: true
+ }
+ },
+ directives: {
+ focus: {
+ inserted: function(el) {
+ el.querySelector("input").focus();
+ }
+ }
+ },
+ mounted() {
+ this.findAllSdk();
+ this.findByType();
+ this.getBaseList();
+ this.findAll();
+ this.getUser();
+ // this.TaskMange.findAllSdk();
+ // this.TaskMange.findByType();
+ this.VideoManageData.init();
+ },
+ methods: {
+ installFormat(percentage) {
+ return percentage === 100 ? '瀹夎鎴愬姛' : `${percentage}%`;
+ },
+ actived() {
+ //this.activeCode
+ this.actStep++
+ },
+ getCodeDetail() {},
+ checkMyAlgorith() {
+ this.actDrawerShow = false;
+ this.activeName = "myAlgorithm";
+ },
+ onFileUpload(file) {
+ //this.patchUpdateStatus = `<span style="color:green">涓婁紶鎴愬姛, 鐐瑰嚮鍗囩骇鎸夐挳寮�濮嬪畨瑁�</span>`;
+ this.patchFile = { ...file };
+ this.fileAdded = true;
+ const h = this.$createElement;
+ // this.$msgbox({
+ // title: '绠楁硶淇℃伅',
+ // message: h('div', null, [
+ // h('span', null, '绠楁硶鍚嶇О锛� '),
+ // h('i', { style: 'color: teal' }, file.filename)
+ // ]),
+ // showCancelButton: true,
+ // confirmButtonText: '纭畾',
+ // cancelButtonText: '鍙栨秷',
+ // beforeClose: (action, instance, done) => {
+ // if (action === 'confirm') {
+ // instance.confirmButtonLoading = true;
+ // instance.confirmButtonText = '鎵ц涓�...';
+ // setTimeout(() => {
+ // done();
+ // setTimeout(() => {
+ // instance.confirmButtonLoading = false;
+ // }, 300);
+ // }, 3000);
+ // } else {
+ // done();
+ // }
+ // }
+ // }).then(action => {
+ // this.$message({
+ // type: 'info',
+ // message: 'action: ' + action
+ // });
+ // });
+
+ this.$confirm('','绠楁硶淇℃伅',{
+ message: `<div class="installInfo">
+ <div><span>绠楁硶鍚嶇О锛�</span><span>${file.filename}</span></div>
+ <div><span>瀹夎鐗堟湰锛�</span><span></span></div>
+ <div><span>鏇存柊鍐呭锛�</span><span></span></div>
+ <p>纭畾瀹夎姝ょ畻娉曪紵</p>
+ </div>`,
+ confirmButtonText: '瀹夎',
+ cancelButtonText: '鍙栨秷',
+ dangerouslyUseHTMLString: true,
+ type: ''
+ }).then(() => {
+ this.isInstall = true;
+ //瀹夎
+ installSdk(file).then(res => {
+ if(res.success){
+ debugger
+ this.isInstall = false;
+ //this.$refs['progressBar'].style.width = 100%
+ //this.installPercentage = 100%
+ this.$message({
+ type: 'success',
+ message: '瀹夎鎴愬姛,灏嗚烦杞嚦鎴戠殑绠楁硶涓煡鐪�'
+ });
+ setTimeout(()=>{
+ this.findAllSdk();
+ this.activeName = 'myAlgorithm';
+ },3000)
+ }
+ });
+ }).catch(() => {
+ console.log('鍙栨秷瀹夎')
+ })
+
+ },
+
+ onFileAdded(f) {
+ debugger;
+ this.patchUpdateStatus = "";
+ },
+ // 鏍¢獙杈撳叆鐨勬槸鍚︽槸鏁板瓧
+ valiNum(value) {
+ if (value) {
+ let re = /[^\-?\d.]*$/;
+ if (!re.test(value)) {
+ // this.$toast({
+ // type: "warning",
+ // message: "璇疯緭鍏ユ暟瀛楋紒"
+ // });
+ this.$notify({
+ title: "鎻愮ず",
+ message: "璇疯緭鍏ユ暟瀛楋紒",
+ type: "warning"
+ });
+ }
+ }
+ },
+ // 宸﹁竟鎷栧姩妯″潡寰楁嫋鍔ㄧ粨鏉熷悗鐨勮Е鍙戝嚱鏁�
+ endLeft(env) {
+ this.dragging = false;
+ let taskId = env.to.id;
+ let sdkId = this.TaskMange.list1[env.oldIndex].id;
+ if (!taskId.length || !sdkId.length) {
+ return;
+ }
+ // 鑾峰彇鍒拌浠诲姟鎵�鍦ㄧ殑鍏冪礌
+ let task = this.TaskMange.list2.find(i => {
+ return i.id === taskId;
+ });
+ let arr = task.child.filter(i => {
+ return i.id === sdkId;
+ });
+ // window.console.log(task, "鎷栬繘鏉ョ殑浠诲姟淇℃伅", sdkId, arr);
+ if (arr && arr.length >= 2) {
+ // this.$toast({
+ // type: "warning",
+ // message: "璇ョ畻娉曞凡瀛樺湪锛�"
+ // });
+ this.$notify({
+ title: "鎻愮ず",
+ message: "璇ョ畻娉曞凡瀛樺湪锛�",
+ type: "warning"
+ });
+ task.child.splice(env.newIndex, 1);
+ return true;
+ }
+ let list = task.child.map((i, index) => {
+ let obj = {};
+ obj.sdkId = i.id;
+ obj.sort = index + 1;
+ return obj;
+ });
+ let json = {
+ taskId: taskId,
+ sdks: list
+ };
+ this.addTaskSdk(json);
+ },
+ // 鍙宠竟鎷栧姩妯″潡寮�濮嬫嫋鍔ㄨЕ鍙戝嚱鏁�
+ startRight(env) {
+ this.$nextTick(() => {
+ this.dragging = true;
+ });
+ // window.window.console.log(env, "right start");
+ },
+ // 鍙宠竟鎷栧姩妯″潡鎷栧姩缁撴潫瑙﹀彂鍑芥暟
+ endRight(env) {
+ // window.window.console.log(env, "right end");
+ },
+ clickSet(data) {
+ if (data.isSetting) {
+ data.isSetting = false;
+ } else {
+ data.isSetting = true;
+ }
+ },
+ clickDel(data, Index) {
+ this.$confirm("鎻愮ず锛氬垹闄ゅ悗锛屾浠诲姟鍦ㄦ憚鍍忔満涓殑搴旂敤澶辨晥锛屾槸鍚﹀垹闄わ紵", {
+ center: true,
+ showConfirmButton: true,
+ showCancelButton: true,
+ confirmButtonClass: "comfirm-class-sure",
+ cancelButtonClass: "comfirm-class-cancle"
+ })
+ .then(() => {
+ this.deleteTask(data);
+ })
+ .catch(err => {});
+ },
+ clickSetAlgo(row, data) {
+ // window.console.log(row, data, "缂栬緫浠诲姟涓煇涓�涓畻娉�");
+ if (row.isShowSetAlgo && data.id === this.TaskMange.currentAlgoId) {
+ row.isShowSetAlgo = false;
+ data.isSelect = false;
+ return false;
+ }
+ if (data.id !== this.TaskMange.currentAlgoId) {
+ let isEdit = false;
+ if (this.argsList && this.argsList.length !== 0) {
+ this.TaskMange.argsList.map((i, index) => {
+ if (i.value2 !== this.argsList[index].value2) {
+ isEdit = true;
+ }
+ if (i.value3 !== this.argsList[index].value3) {
+ isEdit = true;
+ }
+ });
+ }
+ if (isEdit) {
+ this.$notify({
+ title: "鎻愮ず",
+ message: "璇峰厛淇濆瓨鏈繚瀛樼殑閰嶇疆锛�",
+ type: "warning"
+ });
+ return false;
+ } else {
+ let task = this.TaskMange.list2.find(element => {
+ return element.isShowSetAlgo;
+ });
+ // console.log(task, '鏄惁鏈夊凡缁忔墦寮�缂栬緫鐨�')
+ if (task !== undefined) {
+ this.$set(task, "isShowSetAlgo", false);
+ task.child.map(i => {
+ this.$set(i, "isSelect", false);
+ });
+ }
+ }
+ }
+ this.TaskMange.currentAlgoId = data.id;
+ this.TaskMange.currentTaskId = row.id;
+ let task = this.TaskMange.list2.find(element => {
+ return element.isShowSetAlgo;
+ });
+ if (task === undefined) {
+ this.getSdkArgs(data).then(() => {
+ this.getRulesByTaskSdk(row.id, data.id);
+ });
+ if (row.isShowSetAlgo) {
+ row.isShowSetAlgo = false;
+ } else {
+ row.isShowSetAlgo = true;
+ data.isSelect = true;
+ }
+ } else {
+ // this.$toast({
+ // type: "warning",
+ // message: "璇峰厛淇濆瓨鏈繚瀛樼殑閰嶇疆锛�"
+ // });
+ // this.$notify({
+ // title: "鎻愮ず",
+ // message: "璇峰厛淇濆瓨鏈繚瀛樼殑閰嶇疆锛�",
+ // type: "warning"
+ // });
+ }
+ },
+ async getRulesByTaskSdk(taskId, sdkId) {
+ let res = await getRulesByTaskSdk({
+ taskId: taskId,
+ sdkId: sdkId
+ });
+ if (res && res.success) {
+ if (res.data.rules && res.data.rules.length !== 0) {
+ this.TaskMange.argsList = res.data.rules.map((i, index) => {
+ let sdk = res.data.argList.find(j => {
+ return j.alias === i.sdk_arg_alias;
+ });
+ let obj = JSON.parse(JSON.stringify(this.TaskMange.baseObject));
+ obj.value1 = i.sdk_arg_alias ? i.sdk_arg_alias : "";
+ obj.value2 = i.operator ? i.operator : "";
+ obj.value3 = i.sdk_arg_value ? i.sdk_arg_value : "";
+ obj.unit = sdk.unit ? sdk.unit : "";
+ obj.id = i.Id ? i.Id : "";
+ obj.algoId = sdkId;
+ return obj;
+ });
+ } else {
+ this.TaskMange.argsList = res.data.argList.map(i => {
+ let obj = JSON.parse(JSON.stringify(this.TaskMange.baseObject));
+ obj.value1 = i.alias ? i.alias : "";
+ obj.value2 = i.default_operator ? i.default_operator : "";
+ obj.value3 = i.default_value ? i.default_value : "";
+ obj.unit = i.unit ? i.unit : "";
+ obj.id = "";
+ obj.algoId = sdkId;
+ return obj;
+ });
+ }
+ // window.console.log(res, '鏌ユ壘绠楁硶瑙勫垯', this.argsList)
+ this.argsList = JSON.parse(JSON.stringify(this.TaskMange.argsList));
+ }
+ },
+ async findAllSdk() {
+ let res = await findAllSdk();
+ if (res && res.success) {
+ // debugger
+ this.TaskMange.list1 = res.data.map((i, index) => {
+ this.$set(i, "isEdit", false);
+ //mock 鏈畨瑁�/寰呭崌绾�
+ // if (index == 1 || index == 2) {
+ // this.$set(i, "isUpgrade", true);
+ // }
+ // if (index == 3 || index == 4) {
+ // this.$set(i, "installed", false);
+ // }
+ //mock end
+ return i;
+ });
+ }
+ },
+ addTask() {
+ let obj = {
+ id: "",
+ name: "浠诲姟" + this.TaskMange.list2.length,
+ child: [],
+ isSetting: false,
+ isShowSetAlgo: false
+ };
+ // window.console.log(this.TaskMange.list2, "addTask");
+ this.TaskMange.list2.push(obj);
+ this.addTaskAsync(obj.name);
+ this.$nextTick(() => {
+ let taskArea = document.getElementById("taskArea");
+ taskArea.scrollTop = taskArea.scrollHeight;
+ });
+ },
+ async findAll() {
+ let res = await findAll();
+ if (res && res.success) {
+ if (res.data && res.data.length !== 0) {
+ let list = res.data.map(i => {
+ let obj = {};
+ obj.id = i.task.taskid;
+ obj.name = i.task.taskname;
+ obj.enable = i.task.enable;
+ obj.is_alarm = i.task.is_alarm;
+ obj.child = [];
+ if (i.sdks && i.sdks.length !== 0) {
+ obj.child = i.sdks.map(j => {
+ let t = {};
+ t.id = j.id;
+ t.ipc_id = j.ipc_id;
+ if (i.sdks.length == 1) {
+ t.sdk_name = i.task.taskname;
+ // console.log("鍗曚釜sdk绠楁硶锛�",t.sdk_name)
+ } else {
+ t.sdk_name = j.sdk_name;
+ // console.log("澶氫釜sdk绠楁硶锛�",t.sdk_name)
+ }
+ t.icon = j.icon;
+ t.enable = j.enable;
+ t.isSelect = false;
+ return t;
+ });
+ }
+ obj.isSetting = false;
+ obj.isShowSetAlgo = false;
+ return obj;
+ });
+ this.TaskMange.list2 = list;
+ }
+ }
+ },
+ clickDelSdk(task, sdk) {
+ this.$confirm(
+ "鎻愮ず锛氬垹闄ゅ悗锛屾绠楁硶鍦ㄦ湰浠诲姟涓Щ闄わ紝鍚屾椂鍦ㄦ憚鍍忔満涓殑搴旂敤澶辨晥锛屾槸鍚﹀垹闄わ紵",
+ {
+ center: true,
+ showConfirmButton: true,
+ showCancelButton: true,
+ confirmButtonClass: "comfirm-class-sure",
+ cancelButtonClass: "comfirm-class-cancle"
+ }
+ )
+ .then(() => {
+ this.delTaskSdk(task, sdk);
+ })
+ .catch(err => {});
+ },
+ selectChange(event, type, data) {
+ if (type === "options1") {
+ // window.window.console.log(type, data, "閫夋嫨涓嬫媺妗�");
+ data.options1.map(i => {
+ if (i.value === data.value1) {
+ this.$set(data, "unit", i.unit ? i.unit : "");
+ }
+ });
+ }
+ },
+ // 鍒犻櫎浠诲姟绠楁硶
+ async delTaskSdk(task, sdk) {
+ let json = {
+ taskId: task.id,
+ sdkId: sdk.id
+ };
+ let res = await delTaskSdk(json);
+ if (res && res.success) {
+ // this.$toast({
+ // type: "success",
+ // message: "鍒犻櫎浠诲姟绠楁硶鎴愬姛!"
+ // });
+ this.$notify({
+ title: "鎴愬姛",
+ message: "鍒犻櫎浠诲姟绠楁硶鎴愬姛!",
+ type: "success"
+ });
+ this.findAll();
+ }
+ },
+ // 鍒犻櫎浠诲姟
+ async deleteTask(data, index) {
+ // window.console.log(data, "deleteTask");
+ let res = await deleteTask({ taskId: data.id });
+ // this.$toast({
+ // type: res.success ? "success" : "error",
+ // message: res.msg
+ // });
+ this.$notify({
+ title: res.success ? "鎴愬姛" : "澶辫触",
+ message: res.msg,
+ type: res.success ? "success" : "error"
+ });
+ if (data.id && res.success) {
+ this.findAll();
+ }
+ },
+ // 鏇存柊浠诲姟鐘舵��
+ async updateTaskStatus(data) {
+ // window.console.log(data, '鏇存柊浠诲姟鐘舵��')
+ let json = {
+ taskId: data.id,
+ enable: data.enable
+ };
+ let res = await updateTaskStatus(json);
+ // this.$toast({
+ // type: res.success ? "success" : "error",
+ // message: res.msg
+ // });
+ this.$notify({
+ title: res.success ? "鎴愬姛" : "澶辫触",
+ message: res.msg,
+ type: res.success ? "success" : "error"
+ });
+ },
+ // 鏇存柊浠诲姟鍚嶇О
+ async updateTaskName(data) {
+ let json = {
+ taskId: data.id,
+ taskName: data.name
+ };
+ let res = await updateTaskName(json);
+ // this.$toast({
+ // type: res.success ? "success" : "error",
+ // message: res.msg
+ // });
+ this.$notify({
+ title: res.success ? "鎴愬姛" : "澶辫触",
+ message: res.msg,
+ type: res.success ? "success" : "error"
+ });
+ if (res && res.success) {
+ this.$set(data, "isSetting", false);
+ }
+ },
+ // 鑾峰彇搴曞簱鏁版嵁
+ async getBaseList() {
+ // let res = await getTagList();
+ // if (res && res.success) {
+ // let filter = res.data.filter(i => {
+ // return i.status === 0;
+ // });
+ // let list = filter.map(i => {
+ // let obj = {};
+ // obj.id = i.key;
+ // obj.name = i.title;
+ // obj.value = i.value;
+ // return obj;
+ // });
+ // list.unshift({
+ // id: "",
+ // name: "鍏ㄩ儴搴曞簱",
+ // value: ""
+ // })
+
+ // // this.TaskMange.baseObject.options3 = [...all, ...list];
+ // this.TaskMange.baseObject.options3 = [...list];
+ // }
+
+ this.TaskMange.baseObject.options3 = [
+ { id: true, name: true, value: true },
+ { id: false, name: false, value: false }
+ ];
+ },
+ // 鑾峰彇绠楁硶鍙傛暟
+ async getSdkArgs(data) {
+ let res = await getSdkArgs({
+ sdkId: data.id,
+ scope: "TASKRULE"
+ });
+ if (res && res.success) {
+ // window.console.log(res, "鏌ヨ绠楁硶鍙傛暟");
+ let list = res.data.map(i => {
+ let obj = {};
+ obj.name = i.name;
+ obj.id = i.alias;
+ obj.value = i.alias;
+ obj.unit = i.unit;
+ obj.must = i.must;
+ obj.range = i.range;
+ obj.sort = i.sort;
+ return obj;
+ });
+ this.TaskMange.baseObject.options1 = [...list];
+ }
+ },
+ // 鏌ヨ瀛楀吀
+ async findByType() {
+ let res = await findByType();
+ if (res && res.success) {
+ let list = res.data.RULECOMPUTEBETWEEN.map(i => {
+ let obj = {};
+ obj.name = i.name;
+ obj.value = i.value;
+ return obj;
+ });
+ this.TaskMange.baseObject.options2 = [...list];
+ }
+ },
+ // 绠楁硶閰嶇疆锛屾柊寤�
+ add() {
+ this.TaskMange.argsList.push(
+ JSON.parse(JSON.stringify(this.TaskMange.baseObject))
+ );
+ },
+ // 绠楁硶閰嶇疆 鍒犻櫎
+ delRule(index) {
+ this.TaskMange.argsList.splice(index, 1);
+ },
+ // 绠楁硶鍙傛暟淇濆瓨
+ async save() {
+ let list = this.TaskMange.argsList.map(i => {
+ let obj = {};
+ obj.id = i.id;
+ obj.operator = i.value2;
+ obj.sdk_arg_alias = i.value1;
+ obj.sdk_arg_value = i.value3;
+ return obj;
+ });
+ let json = {
+ rules: list,
+ sdkId: this.TaskMange.currentAlgoId,
+ taskId: this.TaskMange.currentTaskId
+ };
+ let res = await saveTaskSdkRule(json);
+ this.$notify({
+ title: "鎻愮ず",
+ type: res.success ? "success" : "error",
+ message: res.msg
+ });
+ if (res && res.success) {
+ let task = this.TaskMange.list2.find(i => {
+ return i.id === this.TaskMange.currentTaskId;
+ });
+ if (task) {
+ this.$set(task, "isShowSetAlgo", false);
+ this.TaskMange.argsList = [];
+ task.child.map(i => {
+ this.$set(i, "isSelect", false);
+ });
+ }
+ }
+ },
+ getDefault() {
+ this.deleteTaskSdkRule(
+ this.TaskMange.currentTaskId,
+ this.TaskMange.currentAlgoId
+ ).then(() => {
+ this.getRulesByTaskSdk(
+ this.TaskMange.currentTaskId,
+ this.TaskMange.currentAlgoId
+ );
+ });
+ },
+ async deleteTaskSdkRule(taskId, sdkId) {
+ let json = {
+ taskId: taskId,
+ sdkId: sdkId
+ };
+ let res = await deleteTaskSdkRule(json);
+ // this.$toast({
+ // type: res.success ? "success" : "error",
+ // message: res.msg
+ // });
+ this.$notify({
+ title: res.success ? "鎴愬姛" : "澶辫触",
+ message: res.msg,
+ type: res.success ? "success" : "error"
+ });
+ if (res && res.success) {
+ // window.console.log(res, "鎭㈠榛樿鍊�");
+ }
+ },
+ // 缁欎换鍔℃坊鍔犵畻娉�
+ async addTaskSdk(data) {
+ let res = await addTaskSdk(data);
+ if (res && res.success) {
+ // window.console.log(res, 'res')
+ this.findAll();
+ }
+ },
+ // 鏂版坊鍔犱换鍔�
+ async addTaskAsync(name) {
+ let res = await addTask({ taskname: name });
+ // this.$toast({
+ // type: res.success ? "success" : "error",
+ // message: res.msg
+ // });
+ // window.console.log(res, "addTaskAsync");
+ this.$notify({
+ title: res.success ? "鎴愬姛" : "澶辫触",
+ message: res.msg,
+ type: res.success ? "success" : "error"
+ });
+ if (res && res.success) {
+ this.findAll();
+ }
+ },
+ cancle(row) {
+ if (row.isShowSetAlgo) {
+ row.isShowSetAlgo = false;
+ }
+ this.TaskMange.argsList = [];
+ this.TaskMange.currentAlgoId = "";
+ row.child.map(i => {
+ this.$set(i, "isSelect", false);
+ });
+ },
+ cancleTask(row) {
+ if (row.isSetting) {
+ row.isSetting = false;
+ }
+ },
+ commandAlgo(command, row, item) {
+ if (command === 1) {
+ // console.log('璁剧疆绠楁硶')
+ this.clickSetAlgo(row, item);
+ }
+ if (command === 2) {
+ // console.log('鍒犻櫎绠楁硶')
+ this.clickDelSdk(row, item);
+ }
+ },
+ commandTask(command, row) {
+ if (command === 1) {
+ //缂栬緫浠诲姟
+ this.clickSet(row);
+ }
+ },
+ getUser() {
+ // console.log("鐧诲綍鐢ㄦ埛",JSON.parse(sessionStorage.getItem("userInfo")).username)
+ if (
+ sessionStorage.getItem("userInfo") &&
+ (JSON.parse(sessionStorage.getItem("userInfo")).username ==
+ "superadmin" ||
+ JSON.parse(sessionStorage.getItem("userInfo")).username == "basic")
+ ) {
+ this.isSuperUser = true;
+ } else {
+ this.isSuperUser = false;
+ }
+ },
+ donwload(item) {
+ this.downloading = true;
+ this.downloadItem = item.id;
+
+ downloadSdk({ path: item.id })
+ .then(rsp => {
+ this.$notify({
+ type: "success",
+ message: "绠楁硶宸插畨瑁�"
+ });
+ this.downloading = false;
+ this.downloadItem = "";
+ this.findAllSdk();
+ })
+ .catch(err => {
+ this.$notify({
+ type: "warning",
+ message: err.data
+ });
+
+ this.downloading = false;
+ this.downloadItem = "";
+ });
+ },
+ commandAlgLib(item) {
+ this.$set(item, "isEdit", true);
+ },
+ inputBlur(item) {
+ // console.log(item, '淇敼鍚嶇О')
+ this.$set(item, "isEdit", false);
+ },
+ updateTemplates() {
+ getAllTemplate().then(rsp => {
+ if (rsp && rsp.success) {
+ this.sceneTemplates = rsp.data;
+ this.sceneTemplates.forEach(element => {
+ element.icon = [
+ "iconrenlianjiance",
+ "icongetijingzhi",
+ "iconchouyan-copy",
+ "iconrenshukouzhao"
+ ];
+ });
+ }
+ });
+ },
+ cleanTemplateForm() {
+ this.appSceneForm.name = "";
+ this.appSceneForm.desc = "";
+ this.appSceneForm.rules = "";
+ this.appSceneForm.txt = "";
+
+ this.$refs.ruleEditor.cleanRule();
+ },
+ handleTabClick() {
+ if (this.activeName == "appScenarios") {
+ this.updateTemplates();
+ }
+ },
+ handleCreateScene() {
+ this.sceneDialogVisible = true;
+ this.dialogTitle = '鍒涘缓鍦烘櫙妯℃澘';
+
+ this.sceneSdks = this.TaskMange.list1.filter(sdk => {
+ return sdk.installed === true;
+ });
+ this.sceneRuleList = "";
+
+ this.$nextTick(() => {
+ this.cleanTemplateForm();
+ });
+ },
+ handleDialogClose() {
+ this.sceneDialogVisible = false;
+ },
+ handleEditScene(item) {
+ this.appSceneForm.name = item.name;
+ this.appSceneForm.desc = item.desc;
+
+ this.sceneSdks = item.sdks;
+ this.sceneRuleList = item.rules;
+ this.sceneDialogVisible = true;
+ this.dialogTitle = '缂栬緫鍦烘櫙妯℃澘';
+ },
+ handleDelScene(item){
+ this.$confirm('姝ゆ搷浣滃皢鍒犻櫎璇ュ簲鐢ㄥ満鏅ā鏉�, 鏄惁缁х画?', '鎻愮ず', {
+ confirmButtonText: '纭畾',
+ cancelButtonText: '鍙栨秷',
+ type: 'warning'
+ }).then(() => {
+ deleteTemplate(item.id).then(res=>{
+ if(res && res.success){
+ this.updateTemplates();
+ this.$message({
+ type: 'success',
+ message: '鍒犻櫎鎴愬姛!'
+ });
+ }
+ })
+
+ }).catch(() => {
+ console.log('鍙栨秷鍒犻櫎');
+ });
+ },
+ handleSaveTemplate() {
+ let editorResp = this.$refs.ruleEditor.submitRule();
+ this.appSceneForm.rules = JSON.stringify(editorResp.rules);
+ this.appSceneForm.txt = editorResp.text;
+
+ saveTemplate(this.appSceneForm).then(rsp => {
+ if (rsp && rsp.success) {
+ this.$notify({
+ type: "success",
+ message: "妯℃澘鍒涘缓鎴愬姛"
+ });
+ this.updateTemplates();
+ this.sceneDialogVisible = false;
+ }
+ });
+ }
+ }
};
</script>
<style lang="scss">
@@ -820,7 +1653,7 @@
// background-color: #f2f6fc;
.s-video-manage-breadcrumb {
height: 5%;
- -webkit-box-sizing: border-box;
+ box-sizing: border-box;
border: 1px solid #e4e7ed;
background-color: rgb(255, 255, 255);
-webkit-box-shadow: #e4e7ed 0px 0px 9px inset;
@@ -858,4 +1691,805 @@
color: #606266;
cursor: pointer;
}
+
+
+
+.installInfo{
+ text-indent: 2em;
+ font-size: 14px;
+ color: #777;
+ p{
+ text-align: center;
+ color: #666;
+ }
+}
+.task-manage {
+ height: 100%;
+ .installModel{
+ width: 100%;
+ height: 100%;
+ background-color: rgba(0, 0, 0, 0.7);
+ position: fixed;
+ top: 0;
+ left: 0;
+ z-index: 100;
+ .progress-bar{
+ width: 70%;
+ height: 17px;
+ border-radius: 3px;
+ background-color: rgb(227, 229, 231);
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ background: url(../../../assets/gif/green.gif);
+ overflow: hidden;
+ transform: translate(-50%,-50%);
+ .inner-bar{
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 0;
+ height: 100%;
+ transition: width 3s;
+ background-color: #3d68e1;
+ }
+ }
+ }
+ .el-tab-pane {
+ height: auto !important;
+ }
+ .el-tabs--border-card > .el-tabs__content {
+ padding: 0 !important;
+ overflow: auto !important;
+ }
+ .el-tabs__content {
+ padding: 0 !important;
+ overflow: auto !important;
+ }
+ //height: calc(100% - 10px);
+ // .super {
+ // .right-box {
+ // width: 58% !important;
+ // }
+ // }
+ .edit-rules-box{
+ padding: 0 2px 0 13px;
+ }
+ .common {
+ .rigth-box {
+ width: 90% !important;
+ }
+ }
+ .super,
+ .common {
+ width: 100%;
+ height: 100%;
+ .title {
+ margin-bottom: 10px;
+ line-height: 30px;
+ font-family: PingFangSC-Medium;
+ font-size: 16px;
+ color: #222222;
+ }
+ .left-box {
+ // width: 41%;
+ height: 100%;
+ padding-top: 10px;
+ box-sizing: border-box;
+ // float: left;
+
+ .action-bar {
+ margin-bottom: 30px;
+ .el-input {
+ width: 100%;
+ }
+ }
+ .task-list {
+ background: #fff;
+ padding: 30px 20px 20px;
+ box-sizing: border-box;
+ .flex-list {
+ display: flex;
+ flex-direction: row;
+ flex-wrap: wrap;
+ // justify-content: space-around;
+ // align-content: space-around;
+ // &:after {
+ // content: "";
+ // flex: auto;
+ // }
+ .wrap-box {
+ width: 16.66%;
+ }
+ .list-choose-item-left {
+ // width: 220px;
+ // height: 214px;
+ width: 80%;
+ height: auto;
+ margin: auto;
+ margin-bottom: 30px;
+ // @media screen and(min-width: 1895px) {
+ // //margin: 20px 25px 20px 20px;
+ // width: 230px;
+ // height: 224px;
+ // }
+ // @media screen and(min-width: 1695px) and(max-width:1895px ) {
+ // margin: 20px 10px 20px 15px;
+ // }
+ // @media screen and(min-width: 1460px) and(max-width: 1695px) {
+ // margin: 20px 25px 20px 20px;
+ // }
+ // @media screen and(max-width: 1460px) {
+ // margin: 20px 15px 20px 10px;
+ // }
+ }
+ }
+ }
+ .appScenarios-list {
+ display: flex;
+ flex-wrap: wrap;
+ .wrap-box {
+ width: 16.6%;
+ margin-bottom: 30px;
+ .inner {
+ width: 80%;
+
+ box-sizing: border-box;
+ position: relative;
+ font-size: 14px;
+ padding: 20px 0 50px;
+ transition: all 1s;
+ background: #ffffff;
+ border: 1px solid #e2e2e2;
+ box-shadow: 0 5px 12px 0 rgba(0, 0, 0, 0.07);
+ border-radius: 4px;
+ margin: auto;
+ &:hover{
+ .mask{
+ display: block;
+ }
+ }
+ .mask{
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ background: rgba(0, 0, 0, 0.65);
+ backdrop-filter: blur(1px) brightness(100%);
+ text-align: center;
+ z-index: 1;
+ border-radius: 3px;
+ display: none;
+ .tool{
+ position: absolute;
+ top: 49%;
+ left: 50%;
+ transform: translate(-50%,-50%);
+ i{
+ font-size: 50px;
+ }
+ i:nth-of-type(1){
+ margin-right: 30px;
+ }
+ i:nth-of-type(2){
+ color: red;
+ }
+ }
+ }
+ .scenario-icon {
+ display: flex;
+ width: 100%;
+ height: 100%;
+ margin: auto;
+ justify-content: center;
+ align-content: center;
+ align-items: center;
+ .single,
+ .double,
+ .third,
+ .four {
+ width: 80%;
+ padding-top: 80%;
+ position: relative;
+ margin: auto;
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+ .svg-wrap {
+ width: 50%;
+ position: absolute;
+ height: 0;
+ padding-top: 50%;
+ text-align: center;
+ box-shadow: 0 0 3px 2px rgb(247, 247, 247) inset;
+ svg {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ }
+ .baseImg {
+ position: absolute !important;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ }
+ }
+ }
+ .single {
+ margin: auto;
+ .svg-wrap{
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%,-50%);
+ box-shadow: none;
+ }
+ }
+ .double{
+ .svg-wrap:nth-of-type(1){
+ top: 50%;
+ transform: translateY(-50%);
+ left: 0;
+ }
+ .svg-wrap:nth-of-type(2){
+ top: 50%;
+ transform: translateY(-50%);
+ right: 0;
+ }
+ }
+ .third{
+ .svg-wrap:nth-of-type(1){
+ top: 0;
+ left: 0;
+ }
+ .svg-wrap:nth-of-type(2){
+ top: 0;
+ right: 0;
+ }
+ .svg-wrap:nth-of-type(3){
+ top: 50%;
+ left: 50%;
+ transform: translateX(-50%);
+ }
+ }
+ .four{
+ .svg-wrap:nth-of-type(1){
+ top: 0;
+ left: 0;
+ }
+ .svg-wrap:nth-of-type(2){
+ top: 0;
+ right: 0;
+ }
+ .svg-wrap:nth-of-type(3){
+ top: 50%;
+ left: 0;
+ }
+ .svg-wrap:nth-of-type(4){
+ top: 50%;
+ right: 0;
+ }
+ }
+ }
+ .scenario-name {
+ width: 100%;
+ height: 36px;
+ line-height: 36px;
+ text-align: center;
+ position: absolute;
+ bottom: 10px;
+ left: 0;
+ }
+ }
+
+ }
+ }
+ .store-list {
+ display: flex;
+ flex-wrap: wrap;
+ .wrap-box {
+ width: 16.6%;
+ margin-bottom: 30px;
+ .inner {
+ width: 80%;
+ box-sizing: border-box;
+ position: relative;
+ font-size: 14px;
+ padding-bottom: 10px;
+ transition: all 1s;
+ background: #ffffff;
+ border: 1px solid #e2e2e2;
+ box-shadow: 0 5px 12px 0 rgba(0, 0, 0, 0.07);
+ border-radius: 4px;
+ margin: auto;
+ .alg-icon {
+ position: relative;
+ width: 80%;
+ margin: auto;
+ padding-top: 80%;
+ svg{
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%,-50%);
+
+ }
+ }
+ .alg-name {
+ height: 36px;
+ text-align: center;
+ line-height: 36px;
+ }
+ .mask {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ background: rgba(0, 0, 0, 0.65);
+ backdrop-filter: blur(1px) brightness(100%);
+ text-align: center;
+ z-index: 1;
+ border-radius: 3px;
+ display: none;
+ svg {
+ position: absolute;
+ top: 49%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ z-index: 33;
+ }
+ }
+ &:hover {
+ .mask {
+ display: block;
+ }
+ }
+ }
+ }
+ }
+ .drawer-content {
+ font-family: "PingFangSC-Regular";
+ .el-step__title.is-process {
+ border-color: #3d68e1 !important;
+ color: #3d68e1 !important;
+ font-family: Tahoma, Helvetica, Arial, "\5B8B\4F53", sans-serif;
+ }
+ .el-step__head.is-process {
+ border-color: #3d68e1 !important;
+ color: #3d68e1 !important;
+ font-family: Tahoma, Helvetica, Arial, "\5B8B\4F53", sans-serif;
+ }
+ .el-input {
+ width: 100%;
+ margin-bottom: 30px;
+ }
+ .current-step {
+ margin: 40px 30px 30px;
+ }
+ .act-code {
+ padding: 0 30px;
+ p {
+ font-size: 15px;
+ margin-bottom: 16px;
+ }
+ }
+ .desc {
+ padding: 0 30px;
+ margin-bottom: 30px;
+ li {
+ border-bottom: 1px solid #eee;
+ height: 45px;
+ line-height: 45px;
+ font-size: 14px;
+ &:last-child {
+ border-bottom: none;
+ }
+ label {
+ display: inline-block;
+ width: 90px;
+ padding-left: 14px;
+ font-weight: bold;
+ }
+ }
+ }
+ .text-right {
+ padding-right: 30px;
+ .tip{
+ color: #999;
+ line-height: 38px;
+ }
+ }
+ }
+ .tab-content {
+ padding: 30px 20px;
+ }
+ }
+
+ .right-box {
+ height: 100%;
+ padding: 10px 10px;
+ box-sizing: border-box;
+ float: left;
+ .task-manage-table {
+ height: calc(100% - 30px);
+ margin-top: 5px;
+ overflow-x: hidden;
+ overflow-y: auto;
+ }
+ // .task-manage-table::-webkit-scrollbar {
+ // width: 0 !important ;
+ // }
+ }
+ .mask {
+ position: absolute;
+ width: 100%;
+ height: 100%;
+ background: rgba(0, 0, 0, 0.65);
+ backdrop-filter: blur(1px) brightness(100%);
+ text-align: center;
+ z-index: 1;
+ border-radius: 3px;
+ display: none;
+
+ i {
+ color: #fff;
+ position: relative;
+ top: 40%;
+ display: contents;
+ }
+ i:hover {
+ color: rgba(255, 255, 255, 0.685);
+ }
+ }
+
+ .text-css {
+ width: 100%;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
+ .move-hear {
+ margin: 10px 0 0 0;
+ font-size: 5rem;
+ }
+ .list-choose-item {
+ cursor: pointer;
+ position: relative;
+ font-size: 14px;
+ display: inline-block;
+ @media screen and(min-width: 1640px) {
+ margin: 30px 20px 20px 20px;
+ }
+ @media screen and(min-width: 1460px) and(max-width: 1640px) {
+ margin: 30px 20px 20px 10px;
+ }
+ @media screen and(max-width: 1460px) {
+ margin: 30px 10px 20px 10px;
+ }
+ min-width: 126px;
+ height: 120px;
+ transition: all 1s;
+ background: #fff;
+ border: 1px solid #e2e2e2;
+ box-shadow: 0 5px 12px 0 rgba(0, 0, 0, 0.07);
+ border-radius: 4px;
+ }
+ .list-choose-item:hover {
+ .mask {
+ display: block;
+ }
+ }
+
+ .alg-shadow {
+ -webkit-box-shadow: 0px 0px 10px 3px rgba(0, 0, 0, 0.3);
+ -moz-box-shadow: 0px 0px 10px 3px rgba(0, 0, 0, 0.3);
+ box-shadow: 0px 0px 10px 3px rgba(0, 0, 0, 0.3);
+ }
+ .select-color {
+ margin-top: 16px;
+ text-align: center;
+ line-height: 28px;
+ // background-color: #3498DB;
+ }
+ .list-choose-item-left {
+ cursor: pointer;
+ position: relative;
+ font-size: 14px;
+ // display: inline-block;
+ // @media screen and(min-width: 1895px) {
+ // //margin: 20px 25px 20px 20px;
+ // margin: 20px 30px 20px 20px;
+ // }
+ // @media screen and(min-width: 1695px) and(max-width:1895px ) {
+ // margin: 20px 10px 20px 15px;
+ // }
+ // @media screen and(min-width: 1460px) and(max-width: 1695px) {
+ // margin: 20px 25px 20px 20px;
+ // }
+ // @media screen and(max-width: 1460px) {
+ // margin: 20px 15px 20px 10px;
+ // }
+ // width: 126px;
+ // height: 120px;
+ // width: 220px;
+ // height: 214px;
+ transition: all 1s;
+ background: #ffffff;
+ border: 1px solid #e2e2e2;
+ box-shadow: 0 5px 12px 0 rgba(0, 0, 0, 0.07);
+ border-radius: 4px;
+ p {
+ display: none;
+ text-align: right;
+ width: 100%;
+ position: absolute;
+ right: 10px;
+ top: 5px;
+ }
+ .click-download {
+ position: absolute;
+ left: 80%;
+ top: 5%;
+ }
+ }
+ .list-choose-item-left:hover {
+ .mask {
+ display: flex;
+ align-items: flex-end;
+ .bot-btn {
+ flex: 1;
+ }
+ }
+ }
+ .list-choose-item-left-uninstal {
+ color: darkgray;
+ background-color: #ddd;
+ }
+ .list-complete-item.sortable-chosen {
+ background: #4ab7bd;
+ }
+ .list-choose-item.sortable-ghost {
+ background: #30b08f;
+ }
+ .width-new-line {
+ word-wrap: break-word;
+ word-break: break-all;
+ }
+ .dndList-list {
+ max-width: 40%;
+ }
+ .dic-border {
+ width: 98%;
+ min-height: 170px;
+ background: #fff;
+ padding: 10px 10px 10px 20px;
+ }
+ .min-h {
+ min-height: 130px;
+ }
+ .parent-div {
+ border-right: 1px solid rgba(24, 28, 33, 0.5);
+ max-width: 140px;
+ position: relative;
+ }
+ .list-choose-header {
+ position: relative;
+ width: 74px;
+ height: 74px;
+ background-image: linear-gradient(-137deg, #7076f2 0%, #3d63e1 100%);
+ box-shadow: 0 5px 12px 0 rgba(0, 0, 0, 0.07);
+ border-radius: 37px;
+ margin: 10px 25px;
+ }
+
+ .task-name-div {
+ font-family: PingFangSC-Medium;
+ font-size: 15px;
+ color: #4b68e6;
+ text-align: center;
+ margin-top: 6px;
+ max-width: 120px;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ }
+ .border-dash {
+ height: 30px;
+ width: 96%;
+ margin-bottom: 10px;
+ border: 1px dashed rgba(24, 28, 33, 0.5);
+ }
+ .i-setting {
+ position: absolute;
+ font-size: 28px;
+ margin-top: -25px;
+ margin-left: -30px;
+ }
+ .i-delete {
+ position: absolute;
+ font-size: 28px;
+ margin-top: -25px;
+ margin-left: -8px;
+ color: red;
+ }
+ .i-bell {
+ float: left;
+ position: relative;
+ left: 10px;
+ top: 10px;
+ font-size: 24px;
+ color: red;
+ }
+ .task-msg {
+ padding-left: 10px;
+ }
+ .b-top {
+ width: 100%;
+ padding-top: 10px;
+ }
+ .b-bottom {
+ width: 100%;
+ border-bottom: 1px solid rgba(24, 28, 33, 0.5);
+ }
+ .i-set-right {
+ position: absolute;
+ left: 80px;
+ top: -11px;
+ font-size: 24px;
+ }
+ .i-remove-right {
+ position: absolute;
+ right: -1px;
+ top: -11px;
+ font-size: 24px;
+ color: red;
+ }
+ .alg-t {
+ line-height: 31px;
+ font-family: PingFangSC-Medium;
+ font-size: 14px;
+ color: #222222;
+ }
+ .alg-name {
+ margin-top: 12px;
+ line-height: 36px;
+ font-family: PingFangSC-Regular;
+ font-size: 15px;
+ color: #222222;
+ // background-color: #ecf5ff;
+ .el-input {
+ position: relative;
+ font-size: 14px;
+ display: inline-block;
+ width: 100%;
+ }
+ }
+ .task-name {
+ text-align: center;
+ margin-top: 16px;
+ line-height: 28px;
+ font-family: PingFangSC-Regular;
+ font-size: 13px;
+ color: #222222;
+ text-align: center;
+ // background-color: #ecf5ff;
+ }
+ .unit-class {
+ margin-left: 10px;
+ text-align: center;
+ line-height: 38px;
+ }
+ .el-input {
+ position: relative;
+ font-size: 14px;
+ display: inline-block;
+ width: 80%;
+ }
+ .list-complete-item-handle {
+ height: 100%;
+ padding-bottom: 10px;
+ text-align: center;
+ .svg-wrap{
+ width: 80%;
+ margin: auto;
+ padding-top: 80%;
+ position: relative;
+ svg{
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%,-50%);
+ }
+ .baseImg {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%,-50%);
+ }
+ }
+ }
+ .dragAreaR {
+ height: 100%;
+ }
+ .drag-info {
+ min-width: 126px;
+ height: 120px;
+ border: 1px dashed #3d68e1;
+ box-shadow: 0 5px 12px 0 rgba(0, 0, 0, 0.07);
+ // box-shadow: 0px 0px 10px 3px rgba(0,0,0,0.3);
+ border-radius: 4px;
+ margin: 30px 10px 20px 10px;
+ }
+ .drag-info-text {
+ letter-spacing: 3px;
+ line-height: 20px;
+ width: 80px;
+ height: 42px;
+ font-family: PingFangSC-Regular;
+ font-size: 13px;
+ color: #3d68e1;
+ text-align: center;
+ }
+ .task-edit {
+ font-size: 26px;
+ position: relative;
+ bottom: -6px;
+ }
+ .el-button--cancle {
+ background: #eaeaea;
+ border-radius: 2px;
+ border-color: #eaeaea;
+ font-family: PingFangSC-Medium;
+ font-size: 13px;
+ color: #222222;
+ margin-right: 12px;
+ }
+ .click-changeImg {
+ cursor: pointer;
+ display: none;
+ background: rgba(0, 0, 0, 0.35);
+ width: 74px;
+ line-height: 20px;
+ color: rgb(255, 255, 255);
+ font-size: 14px;
+ opacity: 1;
+ border-radius: 6px;
+ }
+
+ .task-name-google {
+ position: relative;
+ top: 30px;
+ width: 126px;
+ height: 120px;
+ border: 1px solid #fff;
+ background: #fff;
+ border-radius: 4px;
+ cursor: pointer;
+ .set-task {
+ display: none;
+ cursor: pointer;
+ }
+
+ .el-switch__core {
+ width: 27px !important;
+ height: 14px;
+ }
+ .el-switch__core:after {
+ width: 10px;
+ height: 10px;
+ }
+ .el-switch.is-checked .el-switch__core::after {
+ left: 100%;
+ margin-left: -11px;
+ }
+ }
+ .task-name-google:hover {
+ .mask {
+ display: block;
+ }
+ }
+ }
+}
</style>
+
diff --git a/src/pages/algorithmManage/index/mixins.ts b/src/pages/algorithmManage/index/mixins.ts
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/pages/algorithmManage/index/mixins.ts
diff --git a/src/pages/desktop/index/components/DFrame.vue b/src/pages/desktop/index/components/DFrame.vue
index f7c5feb..ae5e3ac 100644
--- a/src/pages/desktop/index/components/DFrame.vue
+++ b/src/pages/desktop/index/components/DFrame.vue
@@ -41,6 +41,7 @@
},
mounted() {
window.addEventListener('message', e => {
+ console.log(e)
if (e.data && e.data.msg == "logout") {
location.assign("/");
}
diff --git a/src/pages/desktop/index/components/Tools.vue b/src/pages/desktop/index/components/Tools.vue
index a874279..124e00a 100644
--- a/src/pages/desktop/index/components/Tools.vue
+++ b/src/pages/desktop/index/components/Tools.vue
@@ -1,6 +1,6 @@
<template>
<div class="tools">
- <div class="center">
+
<div class="tools-left">
<div
:class="['tools-icon','tools-show-desktop', {clicked:this.$store.state.desktop.preferenceVisiable}]"
@@ -50,7 +50,7 @@
></span>
</div> -->
</div>
- </div>
+
</div>
</template>
@@ -150,7 +150,7 @@
width: 200px;
height: 100%;
float: left;
- margin-left: 8px;
+ margin-left: 14px;
}
.tools .tools-middle{
float: left;
@@ -206,5 +206,6 @@
.tools .tools-right {
float: right;
height: 100%;
+ margin-right: 14px;
}
</style>
\ No newline at end of file
diff --git a/src/pages/desktop/index/components/ToolsEntry.vue b/src/pages/desktop/index/components/ToolsEntry.vue
index ea7b7cd..c98b1e5 100644
--- a/src/pages/desktop/index/components/ToolsEntry.vue
+++ b/src/pages/desktop/index/components/ToolsEntry.vue
@@ -21,26 +21,26 @@
data(){
return {
publicPath: process.env.BASE_URL,
- applist:[
- {src: `/images/app-mid/camera-access.png`, name:'鎽勫儚鏈烘帴鍏�'},
- {src: `/images/app-mid/datastack-config.png`, name:'鏁版嵁鏍堥厤缃�'},
- {src: `/images/app-mid/DVR-access.png`, name:'纭洏褰曞儚鏈烘帴鍏�'},
- {src: `/images/app-mid/data-push.png`, name:'鏁版嵁鎺ㄩ��'},
- {src: `/images/app-mid/GB-config.png`, name:'GB28281閰嶇疆'},
- {src: `/images/app-mid/scene-config.png`, name:'鍦烘櫙閰嶇疆'},
- {src: `/images/app-mid/library.png`, name:'姣斿搴撶鐞�'},
- {src: `/images/app-mid/poll.png`, name:'杞绠$悊'},
- {src: `/images/app-mid/algorithm-manage.png`, name:'绠楁硶绠$悊'},
- {src: `/images/app-mid/algorithm-store.png`, name:'绠楁硶鍟嗗煄'},
- {src: `/images/app-mid/hashrate-manage.png`, name:'绠楀姏绠$悊'},
- {src: `/images/app-mid/monitor.png`, name:'瀹炴椂鐩戞帶-鍦ㄧ嚎鎾斁'},
- {src: `/images/app-mid/search.png`, name:'妫�绱�-缁熻鏌ヨ'},
- {src: `/images/app-mid/360.png`, name:'鍏ㄦ櫙瑙嗛'},
- {src: `/images/app-mid/log-manage.png`, name:'鏃ュ織绠$悊'},
- {src: `/images/app-mid/device.png`, name:'璁惧绠$悊'},
- {src: `/images/app-mid/settings.png`, name:'绯荤粺璁剧疆'},
- {src: `/images/app-mid/vindicate.png`, name:'绯荤粺缁存姢'}
- ]
+ // applist:[
+ // {src: `/images/app-mid/camera-access.png`, name:'鎽勫儚鏈烘帴鍏�'},
+ // {src: `/images/app-mid/datastack-config.png`, name:'鏁版嵁鏍堥厤缃�'},
+ // {src: `/images/app-mid/DVR-access.png`, name:'纭洏褰曞儚鏈烘帴鍏�'},
+ // {src: `/images/app-mid/data-push.png`, name:'鏁版嵁鎺ㄩ��'},
+ // {src: `/images/app-mid/GB-config.png`, name:'GB28281閰嶇疆'},
+ // {src: `/images/app-mid/scene-config.png`, name:'鍦烘櫙閰嶇疆'},
+ // {src: `/images/app-mid/library.png`, name:'姣斿搴撶鐞�'},
+ // {src: `/images/app-mid/poll.png`, name:'杞绠$悊'},
+ // {src: `/images/app-mid/algorithm-manage.png`, name:'绠楁硶绠$悊'},
+ // {src: `/images/app-mid/algorithm-store.png`, name:'绠楁硶鍟嗗煄'},
+ // {src: `/images/app-mid/hashrate-manage.png`, name:'绠楀姏绠$悊'},
+ // {src: `/images/app-mid/monitor.png`, name:'瀹炴椂鐩戞帶-鍦ㄧ嚎鎾斁'},
+ // {src: `/images/app-mid/search.png`, name:'妫�绱�-缁熻鏌ヨ'},
+ // {src: `/images/app-mid/360.png`, name:'鍏ㄦ櫙瑙嗛'},
+ // {src: `/images/app-mid/log-manage.png`, name:'鏃ュ織绠$悊'},
+ // {src: `/images/app-mid/device.png`, name:'璁惧绠$悊'},
+ // {src: `/images/app-mid/settings.png`, name:'绯荤粺璁剧疆'},
+ // {src: `/images/app-mid/vindicate.png`, name:'绯荤粺缁存姢'}
+ // ]
}
},
methods:{
diff --git a/src/pages/desktop/index/mock/userData.json b/src/pages/desktop/index/mock/userData.json
index 6630892..f6e7281 100644
--- a/src/pages/desktop/index/mock/userData.json
+++ b/src/pages/desktop/index/mock/userData.json
@@ -116,7 +116,7 @@
"name": "鍏ㄦ櫙瑙嗛"
},
{
- "id": "14",
+ "id": "15",
"src": "../../images/app-mid/log-manage.png",
"alt": "鏃ュ織绠$悊",
"type": "2",
@@ -124,7 +124,7 @@
"name": "鏃ュ織绠$悊"
},
{
- "id": "14",
+ "id": "16",
"src": "../../images/app-mid/device.png",
"alt": "璁惧绠$悊",
"type": "2",
@@ -132,7 +132,7 @@
"name": "璁惧绠$悊"
},
{
- "id": "15",
+ "id": "17",
"src": "../../images/app-mid/settings.png",
"alt": "绯荤粺璁剧疆",
"type": "2",
@@ -140,7 +140,7 @@
"name": "绯荤粺璁剧疆"
},
{
- "id": "16",
+ "id": "18",
"src": "../../images/app-mid/vindicate.png",
"alt": "绯荤粺缁存姢",
"type": "2",
diff --git a/src/pages/settings/components/AuthorityManagement.vue b/src/pages/settings/components/AuthorityManagement.vue
new file mode 100644
index 0000000..ec9c663
--- /dev/null
+++ b/src/pages/settings/components/AuthorityManagement.vue
@@ -0,0 +1,265 @@
+<template>
+ <div class="s-authority-management">
+ <div class="authority-table s-table" v-if="display">
+ <el-table
+ highlight-current-row
+ :data="userList"
+ style="width: 100%"
+ :header-cell-style="{background:'#f8f8f8',color:'#222222'}"
+ >
+ <el-table-column align="center" type="index" label="搴忓彿" width="100"></el-table-column>
+ <el-table-column :align="'center'" prop="username" label="鐢ㄦ埛鍚�"></el-table-column>
+ <el-table-column :align="'center'" prop="role" label="瑙掕壊">
+ <template slot-scope="scope">{{scope.row.sysRoles | roles}}</template>
+ </el-table-column>
+ <el-table-column label="鎿嶄綔" :align="'center'">
+ <template slot-scope="scope">
+ <el-tooltip content="缂栬緫" placement="top" popper-class="atooltip">
+ <i
+ icon="el-icon-edit"
+ style="font-size: 28px;"
+ @click="handleEdit(scope.$index, scope.row)"
+ ></i>
+ </el-tooltip>
+ <el-tooltip content="鍒犻櫎" placement="top" popper-class="atooltip" v-show="false">
+ <!-- :disabled="scope.row.sysRoles | roles | isSuper" -->
+ <i
+ icon="el-icon-delete"
+ style="font-size: 28px; color:red;"
+ @click="handleDelete(scope.$index, scope.row)"
+ ></i>
+ </el-tooltip>
+ </template>
+ </el-table-column>
+ </el-table>
+ </div>
+ <div class="authority-details" v-if="!display">
+ <el-form label-width="80px" :rules="rules" ref="editForm" :model="editForm">
+ <el-form-item label="鐢ㄦ埛鍚�" style="width:580px" prop="username">
+ <!-- <el-input v-model="editForm.username" placeholder="璇疯緭鍏�" size="small"></el-input> -->
+ <span class="m10" v-if="editForm.username == 'admin' || editForm.username == 'basic'">{{editForm.username}}</span>
+ <el-input v-model="editForm.username" size="small" v-else></el-input>
+ </el-form-item>
+
+ <el-form-item label="鏂板瘑鐮�" style="width:580px" v-show="loginUser != editForm.username">
+ <el-input show-password v-model="editForm.newPwd" placeholder="璇疯緭鍏ュ瘑鐮�" size="small"></el-input>
+ </el-form-item>
+
+ <el-form-item
+ label="纭瀵嗙爜"
+ style="width:580px"
+ prop="checkPass"
+ v-show="loginUser != editForm.username"
+ >
+ <el-input show-password v-model="editForm.checkPass" placeholder="璇疯緭鍏ュ啀娆¤緭鍏ュ瘑鐮�" size="small"></el-input>
+ </el-form-item>
+
+ <el-form-item label="鏉冮檺閰嶇疆" style="width:580px;">
+ <!-- <el-transfer
+ id="e-transfer"
+ :titles="['鍏ㄩ儴瑙掕壊', '褰撳墠瑙掕壊']"
+ v-model="editForm.roleIds"
+ :props="{key: 'id', label: 'name'}"
+ :data="roledata"
+ ></el-transfer>-->
+
+ <el-tree
+ ref="treeMenus"
+ :data="sysMenus"
+ :props="props"
+ node-key="id"
+ :default-checked-keys="userMenus"
+ show-checkbox
+ check-on-click-node
+ default-expand-all
+ style="margin-top: 10px;"
+ ></el-tree>
+ </el-form-item>
+
+ <el-form-item style="width:580px;">
+ <el-button type="primary" style="float: right" @click="save" size="small">淇濆瓨</el-button>
+ <el-button type="info" style="margin-right: 10px;float: right" @click="goback" size="small">杩斿洖</el-button>
+ </el-form-item>
+ </el-form>
+ </div>
+ </div>
+</template>
+
+<script>
+
+import { getUsers, getSysMenus, updataUser, getUserMenus } from "@/api/user"
+
+export default {
+ name: "AuthorityManage",
+ filters: {
+ roles(roles) {
+ return roles.map(r => {
+ return r.name
+ }).join(' ')
+ },
+ isSuper(roles) {
+ return roles.indexOf("瓒呯骇绠$悊鍛�") >= 0
+ }
+ },
+ data() {
+ const generateData = _ => {
+ const data = [];
+ for (let i = 1; i <= 15; i++) {
+ data.push({
+ key: i,
+ label: `澶囬�夐」 ${i}`,
+ disabled: i % 4 === 0
+ });
+ }
+ return data;
+ };
+ const validateCheckPass = (rule, value, callback) => {
+ if (value !== this.editForm.newPwd) {
+ callback(new Error('涓ゆ杈撳叆瀵嗙爜涓嶄竴鑷�!'));
+ } else {
+ callback()
+ }
+ };
+ var checkUserName = (rule, value, callback) => {
+ 聽聽if (value && value !== ''){
+ 聽聽聽聽let regEn = /^[A-Za-z_@.]{2,10}$/
+ console.log("鐢ㄦ埛鍚嶆牎楠岋紒",value)
+ 聽聽聽聽if (!regEn.test(value)) {
+ 聽聽聽聽聽聽callback(new Error('璇疯緭鍏�2浣嶅埌10浣嶅瓧姣嶇殑鐢ㄦ埛鍚嶏紝涓嶈兘浠ユ暟瀛楀紑澶达紝涓斾笉鑳藉寘鍚眽瀛�'))
+ 聽聽聽聽} else {
+ 聽聽聽聽聽聽callback()
+ 聽聽聽聽}
+ 聽聽} else {
+ 聽聽聽聽callback()
+ 聽聽}
+ }
+ return {
+ display: true,
+ loginUser: JSON.parse(sessionStorage.getItem('userInfo')).username,
+ acknewpwd: "",
+ sysMenus: [],
+ userMenus: [],
+ rolevalue: [],
+ userList: [],
+ editForm: {},
+ props: {
+ label: 'name'
+ },
+ rules: {
+ username: [
+ { validator: checkUserName, trigger: 'blur' }
+ ],
+ checkPass: [
+ { validator: validateCheckPass, trigger: 'change' }
+ ]
+ }
+ };
+ },
+ mounted() {
+ this.fetchUserList();
+ this.fetchSysMenus();
+ this.initEditForm();
+ },
+ methods: {
+ initEditForm() {
+ this.editForm = {
+ id: "",
+ username: "",
+ newPwd: "",
+ checkPass: "",
+ menuIds: []
+ }
+ },
+ handleEdit(index, row) {
+ this.initEditForm()
+ this.display = !this.display;
+ this.editForm.id = row.id;
+ this.editForm.username = row.username;
+ this.userMenus = []
+ getUserMenus({ userId: row.id }).then(rsp => {
+ if (rsp && rsp.success) {
+ this.userMenus = rsp.data.menus.map(menu => {
+ return menu.id
+ })
+ }
+ })
+
+ },
+ handleDelete(index, row) {
+ this.$notify({
+ type: "warning",
+ message: "鏃犳硶鍒犻櫎璇ョ敤鎴�"
+ })
+ },
+ goback() {
+ this.display = !this.display;
+ },
+ save() {
+ this.$refs.editForm.validate((valid) => {
+ if (valid) {
+ this.editForm.menuIds = this.$refs.treeMenus.getCheckedKeys()
+ updataUser(this.editForm).then(rsp => {
+ if (rsp && rsp.success) {
+ this.$notify({
+ type: "success",
+ message: "淇敼鎴愬姛"
+ })
+ }
+ })
+ }
+ });
+ },
+ fetchUserList() {
+ getUsers().then(rsp => {
+ if (rsp && rsp.success) {
+ this.userList = rsp.data;
+ }
+ })
+ },
+ fetchSysMenus() {
+ getSysMenus().then(rsp => {
+ if (rsp && rsp.success) {
+ this.sysMenus = rsp.data;
+ }
+ })
+ }
+ }
+};
+</script>
+<style lang="scss">
+.s-authority-management {
+ height: 100%;
+ width: 100%;
+ .authority-table,
+ .authority-details {
+ height: 100%;
+ width: 100%;
+ margin-top: 40px;
+ }
+ #e-transfer {
+ .el-button--primary {
+ color: #fff;
+ background-color: #bfbfbf;
+ border-color: #bfbfbf;
+ }
+ .el-button--primary:focus,
+ .el-button--primary:hover {
+ background: #4c4c4c;
+ border-color: #4c4c4c;
+ color: #fff;
+ }
+ .el-transfer-panel
+ .el-transfer-panel__header
+ .el-checkbox
+ .el-checkbox__label {
+ font-size: 14px;
+ }
+ }
+ .el-form-item__content {
+ text-align: left;
+ input {
+ max-width: 498px;
+ }
+ }
+}
+</style>
diff --git a/src/pages/settings/components/BasicSetting.vue b/src/pages/settings/components/BasicSetting.vue
new file mode 100644
index 0000000..5806be8
--- /dev/null
+++ b/src/pages/settings/components/BasicSetting.vue
@@ -0,0 +1,1307 @@
+<template>
+ <div class="s-basic-setting">
+ <el-tabs
+ id="e-basic-setting"
+ v-model="activeName"
+ v-loading="loading"
+ :element-loading-text="loadingText"
+ >
+ <!-- 鏈満淇℃伅 -->
+ <el-tab-pane label="鏈満淇℃伅" name="first">
+ <el-menu
+ :default-openeds="openeds"
+ background-color="#fff"
+ text-color="#303133"
+ active-text-color="#409EFF"
+ style="height: 100%;"
+ class="menu-css"
+ @open="menuOpen"
+ @close="menuClose"
+ >
+ <!-- 鏈満淇℃伅 -->
+ <el-submenu index="0">
+ <template slot="title">
+ <b class="tree-font">鏈満淇℃伅</b>
+ </template>
+ <el-menu-item-group class="item-group">
+ <el-form :model="sysinfo" :rules="rules" ref="sysinfo" label-width="100px">
+ <el-row>
+ <el-col :span="12">
+ <el-form-item label="鍚嶇О" prop="server_name">
+ <el-input v-model="sysinfo.server_name" placeholder="鏈嶅姟鍣ㄥ悕绉�" size="small"></el-input>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="绔彛" prop="server_port">
+ <el-input v-model="sysinfo.server_port" placeholder="WEB鏈嶅姟绔彛" size="small"></el-input>
+ </el-form-item>
+ </el-col>
+ </el-row>
+
+ <el-row>
+ <el-col :span="12">
+ <el-form-item label="IP" prop="ip">
+ <ip-input :ip="sysinfo.ip" @on-blur="sysinfo.ip = arguments[0]"></ip-input>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="瀛愮綉鎺╃爜" prop="subMask">
+ <ip-input :ip="sysinfo.subMask" @on-blur="sysinfo.subMask = arguments[0]"></ip-input>
+ </el-form-item>
+ </el-col>
+ </el-row>
+
+ <el-row>
+ <el-col :span="12">
+ <el-form-item label="缃戝叧" prop="gateway">
+ <ip-input :ip="sysinfo.gateway" @on-blur="sysinfo.gateway = arguments[0]"></ip-input>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="DNS" prop="dns">
+ <ip-input :ip="sysinfo.dns" @on-blur="sysinfo.dns = arguments[0]"></ip-input>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <div class="mt15 mb10 save-btn">
+ <el-button type="primary" @click="submitSysinfo" size="small">淇濆瓨</el-button>
+ </div>
+ </el-form>
+ </el-menu-item-group>
+ </el-submenu>
+
+ <!-- 璇︾粏淇℃伅 -->
+ <el-submenu index="1">
+ <template slot="title">
+ <b class="tree-font">璇︾粏淇℃伅</b>
+ </template>
+ <el-menu-item-group class="item-group">
+ <el-row :gutter="gutter">
+ <el-col :span="12" class="flex-box">
+ <div class="xiangqin-label">ID</div>
+ <div class="xiangqing-info">{{sysinfo.server_id}}</div>
+ </el-col>
+ <el-col :span="12" class="flex-box">
+ <div class="xiangqin-label">璁惧缂栧彿</div>
+ <div class="xiangqing-info">{{sysinfo.deviceNum}}</div>
+ </el-col>
+ <el-col :span="12" class="flex-box">
+ <div class="xiangqin-label">璁惧鍨嬪彿</div>
+ <div class="xiangqing-info">{{sysinfo.deviceType}}</div>
+ </el-col>
+ <el-col :span="12" class="flex-box">
+ <div class="xiangqin-label">璁惧搴忓垪鍙�</div>
+ <div class="xiangqing-info">{{sysinfo.deviceSerialNum}}</div>
+ </el-col>
+ <el-col :span="12" class="flex-box">
+ <div class="xiangqin-label">涓绘帶鐗堟湰</div>
+ <div class="xiangqing-info">{{sysinfo.masterVersion}}</div>
+ </el-col>
+ <el-col :span="12" class="flex-box">
+ <div class="xiangqin-label">web鐗堟湰</div>
+ <div class="xiangqing-info">{{sysinfo.webVersion}}</div>
+ </el-col>
+ <el-col :span="12" class="flex-box">
+ <div class="xiangqin-label">閫氶亾涓暟</div>
+ <div class="xiangqing-info">{{sysinfo.channelCount}}</div>
+ </el-col>
+ <el-col :span="12" class="flex-box">
+ <div class="xiangqin-label">纭洏涓暟</div>
+ <div class="xiangqing-info">{{sysinfo.diskCount}}</div>
+ </el-col>
+ </el-row>
+ </el-menu-item-group>
+ </el-submenu>
+ <!-- 浜嬩欢褰曞儚鏃堕暱 -->
+ <el-submenu index="2">
+ <template slot="title">
+ <b class="tree-font">浜嬩欢褰曞儚鏃堕暱</b>
+ </template>
+ <el-menu-item-group class="item-group">
+ <el-form
+ label-width="150px"
+ class="alarmSetting"
+ style="padding-left:5px;padding-right:5px;"
+ >
+ <el-form-item label="瑙嗛鎴彇鏈�鐭椂闀�" style="width:724px;">
+ <el-slider
+ id="cut_min_duration"
+ v-model="alarmConf.min_video_len"
+ :show-tooltip="false"
+ ></el-slider>
+ <el-input-number
+ v-model="alarmConf.min_video_len"
+ controls-position="right"
+ :min="0"
+ :max="100"
+ size="small"
+ ></el-input-number> s
+ </el-form-item>
+ <el-form-item label="瑙嗛鎴彇鏈�闀挎椂闀�" style="width:724px">
+ <el-slider
+ id="cut_max_duration"
+ v-model="alarmConf.max_video_len"
+ :show-tooltip="false"
+ ></el-slider>
+ <el-input-number
+ v-model="alarmConf.max_video_len"
+ controls-position="right"
+ :min="0"
+ :max="100"
+ size="small"
+ ></el-input-number> s
+ </el-form-item>
+ <div class="mt15 mb10 save-btn">
+ <el-button type="primary" @click="submitAlarm" size="small">淇濆瓨</el-button>
+ </div>
+ </el-form>
+ </el-menu-item-group>
+ </el-submenu>
+ <!-- 瀵瑰鏈嶅姟IP 鏀瑰悕涓哄閮ㄧ綉缁�(鏂皌ab)-->
+
+ <!-- 鏂囦欢闊宠棰� -->
+ <!-- <el-submenu index="4">
+ <template slot="title">
+ <b class="tree-font">鏂囦欢闊宠棰�</b>
+ </template>
+ <el-menu-item-group class="item-group">
+ <el-row :gutter="20">
+ <el-col :span="8">
+ <div class="p5">
+ <span class="iconfont iconpicture" style="margin-right: 5px;"></span>
+ <span class="mr10">鍥剧墖绔彛</span>
+ <el-input v-model="localFile.picPort" style="width:300px;" placeholder="璇疯緭鍏ュ唴瀹�"></el-input>
+ </div>
+ <div class="p5">
+ <span class="iconfont iconshipin" style="margin-right: 5px;"></span>
+ <span class="mr10">瑙嗛绔彛</span>
+ <el-input v-model="localFile.videoPort" style="width:300px;" placeholder="璇疯緭鍏ュ唴瀹�"></el-input>
+ </div>
+ <div class="p5">
+ <span class="iconfont iconyinpinx" style="margin-right: 5px;"></span>
+ <span class="mr10">闊抽绔彛</span>
+ <el-input v-model="localFile.audioPort" style="width:300px;" placeholder="璇疯緭鍏ュ唴瀹�"></el-input>
+ </div>
+ </el-col>
+ <el-col :span="16">
+ <el-table
+ :data="localFile.fileTable"
+ border
+ style="width: 100%">
+ <el-table-column
+ type="index"
+ label="搴忓彿"
+ align="center"
+ width="50">
+ </el-table-column>
+ <el-table-column
+ prop="date"
+ label="鍚嶇О"
+ align="center"
+ width="180">
+ </el-table-column>
+ <el-table-column
+ prop="name"
+ label="ID"
+ align="center"
+ width="180">
+ </el-table-column>
+ <el-table-column
+ prop="name"
+ label="IP"
+ align="center"
+ width="180">
+ </el-table-column>
+ <el-table-column
+ prop="name"
+ label="鍦ㄧ嚎鐘舵��"
+ align="center"
+ width="80">
+ </el-table-column>
+ <el-table-column
+ label="绫诲埆"
+ align="center"
+ width="100">
+ <template>
+ <span class="iconfont iconpicture" style="margin-right: 5px;"></span>
+ <span class="iconfont iconshipin" style="margin-right: 5px;"></span>
+ <span class="iconfont iconyinpinx" style="margin-right: 5px;"></span>
+ </template>
+ </el-table-column>
+ <el-table-column
+ prop="address"
+ align="center"
+ label="澶囨敞">
+ <template slot-scope="{row}">
+ <div v-if="row.edit">
+ <el-input :autofocus="row.edit" v-focus v-model="row.address" size="small" />
+ <el-button size="mini" type="info" @click="handleCancel(row)">鍙栨秷</el-button>
+ <el-button size="mini" type="primary" @click="handleSave(row)">淇濆瓨</el-button>
+ </div>
+ <div v-else>
+ <span>{{ row.address }}</span>
+ <el-button
+ type="text"
+ style="color: black;font-size:16px"
+ @click="handleEdit(row)"
+ icon="iconfont iconbianji"
+ ></el-button>
+ </div>
+ </template>
+ </el-table-column>
+ </el-table>
+ </el-col>
+ </el-row>
+ </el-menu-item-group>
+ </el-submenu>-->
+ </el-menu>
+ </el-tab-pane>
+
+ <!-- 鏃堕棿閰嶇疆 -->
+ <el-tab-pane label="鏃堕棿閰嶇疆" name="second">
+ <el-form label-width="100px">
+ <el-form-item label="璁惧鏃堕棿">
+ <!-- <el-input v-model="equipmentTime" placeholder="璇疯緭鍏�" size="small"></el-input> -->
+ {{ equipmentTime }}
+ </el-form-item>
+
+ <el-form-item label="鏃跺尯" prop="timezone">
+ <el-select
+ v-model="timezone"
+ placeholder="璇烽�夋嫨"
+ style="width: 360px; height: 32px"
+ size="small"
+ >
+ <el-option
+ v-for="item in timeZoneOption"
+ :key="item.value"
+ :label="item.label"
+ :value="item.value"
+ ></el-option>
+ </el-select>
+ </el-form-item>
+ <div style="text-align: left;padding: 10px 0px">
+ <div class="time-type">NTP鏍℃椂</div>
+ <div style="padding: 10px 0px;">
+ <el-radio v-model="syncType" label="1">NTP鏍℃椂</el-radio>
+ </div>
+ </div>
+
+ <el-form-item label="鏈嶅姟鍣ㄥ湴鍧�">
+ <ip-input
+ :ip="ntpServer"
+ @on-blur="ntpServer= arguments[0]"
+ :disabled="syncType === '2'"
+ ></ip-input>
+ </el-form-item>
+
+ <el-form-item label="鏍℃椂鏃堕棿闂撮殧" style="width: 41.3%;">
+ <el-input-number
+ v-model.number="timeInterval"
+ :min="1"
+ :max="60"
+ placeholder="璇疯緭鍏�"
+ size="small"
+ :controls="false"
+ :disabled="syncType === '2'"
+ ></el-input-number> 鍒嗛挓
+ <el-button
+ type="text"
+ style="position: absolute; left: 330px;"
+ :disabled="syncType === '2'"
+ @click="testNTP"
+ >娴嬭瘯</el-button>
+ </el-form-item>
+
+ <div style="text-align: left;padding: 10px 0px">
+ <div class="time-type">鎵嬪姩鏍℃椂</div>
+ <div style="padding: 10px 0px;">
+ <el-radio v-model="syncType" label="2">鎵嬪姩鏍℃椂</el-radio>
+ </div>
+ </div>
+
+ <el-form-item label="璁剧疆鏃堕棿">
+ <el-date-picker
+ v-model="settime"
+ type="datetime"
+ placeholder="閫夋嫨鏃ユ湡鏃堕棿"
+ size="small"
+ value-format="yyyy-MM-dd HH:mm:ss"
+ :readonly="settimeRadio"
+ :disabled="syncType === '1'"
+ ></el-date-picker>
+ <el-checkbox
+ v-model="settimeRadio"
+ style="margin-left: 12px;"
+ @change="syncBrowser"
+ :disabled="syncType === '1'"
+ >鍚屾鏈绠楁満鏃堕棿</el-checkbox>
+ </el-form-item>
+
+ <el-col :span="12" style="padding-right: 40px;">
+ <el-form-item>
+ <el-button type="primary" @click="submitClock" size="small">淇濆瓨</el-button>
+ </el-form-item>
+ </el-col>
+ </el-form>
+ </el-tab-pane>
+
+ <!-- 闆嗙兢绠$悊 -->
+ <el-tab-pane label="闆嗙兢绠$悊" name="third">
+ <cluster-management></cluster-management>
+ </el-tab-pane>
+ <el-tab-pane label="澶栭儴缃戠粶" name="fourth">
+ <el-row :gutter="20">
+ <el-col :span="10">
+ <div>
+ <div class="flex-box">
+ <div style="line-height:32px;">
+ <el-radio v-model="ipServer.diyOrLocalIP" :label="1">璁剧疆澶栭儴IP</el-radio>
+ <el-radio v-model="ipServer.diyOrLocalIP" :label="0">閫夌敤鏈満IP</el-radio>
+ </div>
+ <div class="ml10" style="width:205px;">
+ <ip-input :ip="ipServer.ip" @on-blur="ipServer.ip = arguments[0]"></ip-input>
+ </div>
+ </div>
+ <div class="flex-box p5" >
+ <span style="line-height:32px;">鍩熷悕</span>
+ <div style="margin-left:14px;width:205px;">
+ <el-input size="small" style v-model="ipServer.localhost"></el-input>
+ </div>
+ </div>
+ <div class="flex-box" >
+ <span style="line-height:32px;">鏈湴鏂囦欢绔彛</span>
+ <div style="margin-left:14px;width:205px;">
+ <el-input size="small" style v-model="ipServer.localFilePort"></el-input>
+ </div>
+ </div>
+ </div>
+ </el-col>
+ <!-- <el-col :span="14">
+ <div>
+ <el-table
+ :data="ipServer.fileTable"
+ border
+ fit
+ style="width: 100%">
+ <el-table-column
+ type="index"
+ label="搴忓彿"
+ align="center"
+ width="50">
+ </el-table-column>
+ <el-table-column
+ prop="date"
+ label="鍚嶇О"
+ align="center"
+ >
+ </el-table-column>
+ <el-table-column
+ prop="name"
+ label="ID"
+ align="center"
+ >
+ </el-table-column>
+ <el-table-column
+ prop="name"
+ label="IP"
+ align="center"
+ >
+ </el-table-column>
+ <el-table-column
+ prop="name"
+ label="鍦ㄧ嚎鐘舵��"
+ align="center"
+ >
+ </el-table-column>
+ </el-table>
+ </div>
+ </el-col>-->
+ </el-row>
+ <div class="mt15 save-btn" style="width:1000px;float:left;">
+ <el-button type="primary" @click="submitResource" size="small">淇濆瓨</el-button>
+ </div>
+ </el-tab-pane>
+ <el-tab-pane label="鏉冮檺绠$悊" name="user" >
+ <authority-management v-if="activeName === 'user'"></authority-management>
+ </el-tab-pane>
+ <el-tab-pane label="骞挎挱璁剧疆" name="radio" >
+ <radio-set v-if="activeName === 'radio'"></radio-set>
+ </el-tab-pane>
+ <!-- GB28181璁剧疆 -->
+ <el-tab-pane label="GB28181璁剧疆" name="fifth">
+ <el-form
+ :model="gb28181"
+ :rules="rules"
+ label-width="140px"
+ class="alarmSetting"
+ ref="gb28181"
+ >
+ <!-- <el-form-item label="鍥介檯鏈嶅姟鍣↖P" prop="ServerIp">
+ <ip-input :ip="gb28181.ServerIp" @on-blur="gb28181.ServerIp = arguments[0]"></ip-input>
+ </el-form-item>-->
+
+ <div style="text-align: left;margin-bottom: 22px;">
+ <el-radio-group v-model="gb28181.idType">
+ <el-radio :label="0">杈撳叆宸叉湁ID</el-radio>
+ <el-radio :label="1">鐢熸垚鏂扮殑ID</el-radio>
+ </el-radio-group>
+ </div>
+
+ <el-form-item label="鎵�鍦ㄥ湴">
+ <el-select
+ v-model="locationCity.province"
+ @change="changeProvince"
+ size="small"
+ placeholder="璇烽�夋嫨鐪佷唤"
+ >
+ <el-option
+ v-for="item in locationCity.provinceOptions"
+ :key="item.id"
+ :label="item.name"
+ size="small"
+ :value="item.id"
+ ></el-option>
+ </el-select>
+ <el-select
+ class="ml10 mr10"
+ v-model="locationCity.city"
+ :disabled="!locationCity.province"
+ @change="changeCity"
+ size="small"
+ placeholder="璇烽�夋嫨鍩庡競"
+ >
+ <el-option
+ v-for="item in locationCity.cityOptions"
+ :key="item.id"
+ :label="item.name"
+ :value="item.id"
+ ></el-option>
+ </el-select>
+ <el-select
+ v-model="locationCity.county"
+ :disabled="!locationCity.city"
+ size="small"
+ placeholder="璇烽�夋嫨鍖哄幙"
+ >
+ <el-option
+ v-for="item in locationCity.countyOptions"
+ :key="item.id"
+ :label="item.name"
+ :value="item.id"
+ ></el-option>
+ </el-select>
+ <el-button
+ type="text"
+ style="position: absolute"
+ v-show="gb28181.idType === 1"
+ @click="newGBID"
+ >鐢熸垚ID</el-button>
+ </el-form-item>
+
+ <!-- <el-form-item label="鍥介檯鏈嶅姟鍣ㄧ鍙�" prop="GbServerPort">
+ <el-input v-model.number="gb28181.ServerPort" placeholder="璇疯緭鍏�" size="small"></el-input>
+ </el-form-item>-->
+
+ <el-form-item label="鍥芥爣ID">
+ <el-input v-model="gb28181.PublicId" placeholder="璇疯緭鍏�" size="small"></el-input>
+ </el-form-item>
+
+ <el-form-item label="鍥芥爣绔彛" prop="ServerPort">
+ <el-input v-model.number="gb28181.GbServerPort" placeholder="璇疯緭鍏�" size="small"></el-input>
+ </el-form-item>
+
+ <el-form-item label="寮�鍚壌鏉�">
+ <el-switch v-model="gb28181.IsAuth"></el-switch>
+ </el-form-item>
+
+ <el-form-item label="閴存潈瀵嗙爜" v-show="gb28181.IsAuth">
+ <el-input v-model="gb28181.Password" placeholder="璇疯緭鍏�" size="small"></el-input>
+ </el-form-item>
+
+ <el-col :span="12">
+ <el-form-item>
+ <el-button type="primary" @click="submitGB28281" size="small">淇濆瓨</el-button>
+ </el-form-item>
+ </el-col>
+ </el-form>
+ </el-tab-pane>
+ </el-tabs>
+ </div>
+</template>
+
+<script>
+import {
+ getDevInfo,
+ getAlarmConfig,
+ getGB28181Config,
+ saveDevInfo,
+ saveAlarmConfig,
+ saveGB28181Config,
+ getClockInfo,
+ saveClockInfo,
+ testNTPserver,
+ getResourceConfig,
+ saveResourceConfig,
+ getGb28181AreaList,
+ newGb28181ID
+} from "@/api/system";
+
+import { isPort, isIPv4 } from "@/scripts/validate";
+import ipInput from "@/components/subComponents/IPInput";
+import TimeZones from "@/Pool/TimeZones"
+
+import ClusterManagement from "./ClusterManagement";
+import AuthorityManagement from "./AuthorityManagement";
+import RadioSet from "./RadioSet";
+
+export default {
+ name: "BasicSettings",
+ components: {
+ ipInput,
+ ClusterManagement,
+ AuthorityManagement,
+ RadioSet
+ },
+ computed: {
+ timeZoneOption() {
+ let options = []
+ TimeZones.forEach(zone => {
+ options = options.concat(zone.utc.map(v => {
+ return { value: v, label: v }
+ }))
+ })
+ return options
+ }
+ },
+ directives: {
+ focus: {
+ inserted: function (el) {
+ el.querySelector('input').focus()
+ }
+ }
+ },
+ data() {
+ return {
+ loading: true,
+ loadingText: "",
+ gutter: 10,
+ activeName: "first",
+ timezone: "",
+ syncType: "1",
+ ntpServer: "",
+ equipmentTime: "",
+ NYPport: "",
+ settime: "",
+ timeInterval: 10,
+ settimeRadio: false,
+ clockTimer: null,
+ browserTimer: null,
+ timestamp: 0,
+ sysinfo: {},
+ alarmConf: {},
+ gb28181: {},
+ originNetConfig: {
+ ip: "",
+ gw: "",
+ mask: "",
+ dns: ""
+ },
+ rules: {
+ ip: [
+ {
+ required: true,
+ message: "璇疯緭鍏P鍦板潃",
+ trigger: "change"
+ },
+ { validator: isIPv4, trigger: "change" }
+ ],
+ ServerIp: [
+ {
+ required: true,
+ message: "璇疯緭鍏P鍦板潃",
+ trigger: "change"
+ },
+ { validator: isIPv4, trigger: "change" }
+ ],
+ ServerPort: [
+ {
+ required: true,
+ message: "璇疯緭鍏ョ鍙�",
+ trigger: "change"
+ },
+ { validator: isPort, trigger: "change" }
+ ],
+ GbServerPort: [
+ {
+ required: true,
+ message: "璇疯緭鍏ョ鍙�",
+ trigger: "change"
+ },
+ { validator: isPort, trigger: "change" }
+ ],
+ gateway: [
+ {
+ required: true,
+ message: "璇疯緭鍏ョ綉鍏�",
+ trigger: "change"
+ },
+ { validator: isIPv4, trigger: "change" }
+ ],
+ dns: [
+ {
+ required: true,
+ message: "璇疯緭鍏ns鍦板潃",
+ trigger: "change"
+ },
+ { validator: isIPv4, trigger: "change" }
+ ],
+ server_name: [
+ { required: true, message: "璇疯緭鍏ュ悕绉�", trigger: "change" }
+ ],
+ subMask: [
+ {
+ required: true,
+ message: "璇疯緭鍏ュ瓙缃戞帺鐮�",
+ trigger: "change"
+ },
+ { validator: isIPv4, trigger: "change" }
+ ]
+ },
+ openeds: ["0"],
+ ipServer: {
+ diyOrLocalIP: "1",
+ ip: "",
+ localhost: "",
+ localFilePort: "",
+ fileTable: [
+ {
+ date: '2016-05-02',
+ name: '鐜嬪皬铏�',
+ address: '涓婃捣甯傛櫘闄�鍖洪噾娌欐睙璺� 1518 寮�',
+ edit: false
+ }, {
+ date: '2016-05-04',
+ name: '鐜嬪皬铏�',
+ address: '涓婃捣甯傛櫘闄�鍖洪噾娌欐睙璺� 1517 寮�',
+ edit: false
+ }, {
+ date: '2016-05-01',
+ name: '鐜嬪皬铏�',
+ address: '涓婃捣甯傛櫘闄�鍖洪噾娌欐睙璺� 1519 寮�',
+ edit: false
+ }, {
+ date: '2016-05-03',
+ name: '鐜嬪皬铏�',
+ address: '涓婃捣甯傛櫘闄�鍖洪噾娌欐睙璺� 1516 寮�',
+ edit: false
+ }
+ ]
+ },
+ locationCity: {
+ province: '',
+ city: '',
+ county: '',
+ provinceOptions: [],
+ cityOptions: [],
+ countyOptions: []
+ },
+ };
+ webPort: 0;
+ },
+ mounted() {
+ this.$nextTick(() => {
+ this.initSysinfo();
+ // this.initAlarmConf();
+ this.initResourceConfig();
+ this.initGB28181Conf();
+ this.initClockConf();
+ });
+ },
+ beforeDestroy() {
+ clearTimeout(this.clockTimer);
+ clearInterval(this.browserTimer);
+ },
+ methods: {
+ initSysinfo() {
+ this.loadingText = "姝e湪鑾峰彇璁惧淇℃伅...";
+ getDevInfo().then(rsp => {
+ if (rsp && rsp.success) {
+ this.sysinfo = rsp.data;
+ this.sysinfo.gateway = this.sysinfo.gateway.trim();
+ this.originNetConfig.ip = this.sysinfo.ip;
+ this.originNetConfig.mask = this.sysinfo.subMask;
+ this.originNetConfig.gw = this.sysinfo.gateway.trim();
+ this.originNetConfig.dns = this.sysinfo.dns ? this.sysinfo.dns : "";
+ this.alarmConf.min_video_len = rsp.data.min_video_len;
+ this.alarmConf.max_video_len = rsp.data.max_video_len;
+
+ if (!this.sysinfo.server_port) {
+ this.sysinfo.server_port = 7003;
+ }
+
+ this.webPort = this.sysinfo.server_port;
+ }
+
+ this.loading = false;
+ }).catch(err => {
+ this.loading = false;
+ });
+ },
+ initClockConf() {
+ getClockInfo().then(rsp => {
+ if (rsp && rsp.success) {
+ this.timezone = rsp.data.time_zone;
+ this.syncType = rsp.data.ntp ? "1" : "2";
+ if (rsp.data.ntp) {
+ this.ntpServer = rsp.data.ntp_server;
+ this.timeInterval = rsp.data.interval;
+ }
+ this.timestamp = rsp.data.local_time
+ if (this.clockTimer === null) {
+ this.runClock();
+ }
+ }
+ })
+ },
+ runClock() {
+ this.equipmentTime = this.formatTime(++this.timestamp, 'Y-M-D h:m:s');
+ // console.log(this.equipmentTime)
+ this.clockTimer = setTimeout(() => {
+ this.runClock();
+ }, 1000)
+ },
+ initAlarmConf() {
+ // getAlarmConfig().then(rsp => {
+ // if (rsp && rsp.success) {
+ // this.alarmConf = rsp.data;
+ // }
+ // });
+ },
+ initResourceConfig() {
+ getResourceConfig().then(rsp => {
+ if (rsp && rsp.success) {
+ this.ipServer.diyOrLocalIP = rsp.data.ipType
+ this.ipServer.ip = rsp.data.serviceIp
+ this.ipServer.localhost = rsp.data.domain
+ this.ipServer.localFilePort = rsp.data.filePort
+ }
+ })
+ },
+ initGB28181Conf() {
+ getGB28181Config().then(rsp => {
+ if (rsp && rsp.success) {
+ this.gb28181 = rsp.data;
+ this.gb28181.idType = 0;
+ }
+ });
+ getGb28181AreaList().then(rsp => {
+ if (rsp && rsp.success) {
+ this.locationCity.provinceOptions = rsp.data;
+ }
+ })
+ },
+ syncBrowser(enable) {
+ if (!enable) {
+ clearInterval(this.browserTimer)
+ } else {
+ this.browserTimer = setInterval(() => {
+ let timestamp = new Date().getTime() / 1000;
+ this.settime = this.formatTime(timestamp, 'Y-M-D h:m:s')
+ }, 1000)
+ }
+ },
+ submitSysinfo() {
+ this.$refs["sysinfo"].validate(valid => {
+ if (valid) {
+ if (this.sysinfo.ip !== this.originNetConfig.ip
+ || this.sysinfo.subMask !== this.originNetConfig.mask
+ || this.sysinfo.dns !== this.originNetConfig.dns
+ || this.sysinfo.gateway !== this.originNetConfig.gw) {
+
+ if (this.sysinfo.ip !== this.originNetConfig.ip) {
+ let newUri = location.protocol + "//" + this.sysinfo.ip + ":" + this.sysinfo.server_port;
+ var changeIPTimer = setTimeout(() => {
+ this.$alert('<strong>鎮ㄥ凡淇敼浜嗘湇鍔″櫒ip, 璇烽噸鏂扮櫥褰�</strong><a href="' + newUri + '"> ' + newUri + '<a/>', '鎻愮ず', {
+ dangerouslyUseHTMLString: true
+ });
+ }, 10000)
+ }
+
+ this.$confirm("纭闇�瑕佷慨鏀规湇鍔″櫒缃戠粶閰嶇疆鍚楋紵", {
+ center: true,
+ cancelButtonClass: "comfirm-class-cancle",
+ confirmButtonClass: "comfirm-class-sure"
+ }).then(() => {
+ this.loading = true;
+ this.loadingText = "姝e湪澶勭悊..."
+ saveDevInfo(this.sysinfo).then(rsp => {
+ if (rsp && rsp.success) {
+ this.$notify({
+ type: "success",
+ message: "鏈満淇℃伅淇濆瓨鎴愬姛"
+ });
+ }
+ this.initSysinfo();
+ this.loading = false;
+ }).catch(err => {
+ this.loading = false;
+ clearTimeout(changeIPTimer)
+ this.$notify({
+ type: "error",
+ message: "淇濆瓨澶辫触"
+ });
+ });
+ }).catch(err => {
+ });
+ } else {
+ saveDevInfo(this.sysinfo).then(rsp => {
+ if (rsp && rsp.success) {
+ this.$notify({
+ type: "success",
+ message: "鏈満淇℃伅淇濆瓨鎴愬姛"
+ });
+ this.initSysinfo();
+ }
+ });
+
+ if (this.sysinfo.server_port !== this.webPort) {
+ let newUri = location.protocol + "//" + this.sysinfo.ip + ":" + this.sysinfo.server_port;
+ var changeIPTimer = setTimeout(() => {
+ this.$alert('<strong>鎮ㄥ凡淇敼浜嗘湇鍔″櫒绔彛, 璇烽噸鏂扮櫥褰�</strong><a href="' + newUri + '"> ' + newUri + '<a/>', '鎻愮ず', {
+ dangerouslyUseHTMLString: true
+ });
+ }, 5000)
+ }
+ }
+ } else {
+ console.log("error submit!!");
+ return false;
+ }
+ });
+ },
+ submitClock() {
+ if (this.syncType === '1') {
+ if (this.ntpServer === "") {
+ this.$notify({
+ type: "error",
+ message: "NTP 鏈嶅姟鍣ㄥ湴鍧�涓嶈兘涓虹┖"
+ });
+ return false
+ } else if (this.timeInterval === "") {
+ this.timeInterval = 1;
+ }
+ } else {
+ if (this.settime === "") {
+ this.$notify({
+ type: "error",
+ message: "璁剧疆鏃堕棿涓嶈兘涓虹┖"
+ });
+ return false
+ }
+ }
+ let requestBody = {
+ timeZone: this.timezone,
+ ntp: this.syncType === '1',
+ ntpServer: this.ntpServer,
+ interval: this.timeInterval,
+ newTime: this.settime
+ }
+ saveClockInfo(requestBody).then(rsp => {
+ if (rsp && rsp.success) {
+ this.$notify({
+ type: "success",
+ message: "璁剧疆鎴愬姛"
+ });
+ }
+ })
+ },
+ testNTP() {
+ testNTPserver({ server: this.ntpServer }).then(rsp => {
+ if (rsp && rsp.success) {
+ this.$notify({
+ type: "success",
+ message: "鏃堕棿鍚屾鎴愬姛"
+ });
+ } else {
+ this.$notify({
+ type: "error",
+ message: "鏃堕棿鍚屾澶辫触"
+ });
+ }
+ }).catch(err => {
+ this.$notify({
+ type: "error",
+ message: "鏃堕棿鍚屾澶辫触,璇锋鏌ユ湇鍔″櫒ip"
+ });
+ })
+ },
+ submitAlarm() {
+ saveAlarmConfig(this.alarmConf).then(rsp => {
+ if (rsp && rsp.success) {
+ this.$notify({
+ type: "success",
+ message: "淇濆瓨鎴愬姛"
+ });
+ }
+ });
+ },
+ submitResource() {
+ let regNum = /^[0-9]*$/;
+ if (!this.vaildHost(this.ipServer.localhost)) {
+ this.$notify({
+ type: "warning",
+ message: "璇疯緭鍏ユ纭牸寮忓緱鍩熷悕锛�"
+ })
+ return false;
+ }
+ if (!regNum.test(this.ipServer.localFilePort)) {
+ this.$notify({
+ type: 'warning',
+ message: "璇疯緭鍏ユ纭殑绔彛鍙凤紒"
+ })
+ return false;
+ }
+ saveResourceConfig({
+ domain: this.ipServer.localhost,
+ ipType: this.ipServer.diyOrLocalIP,
+ serviceIp: this.ipServer.ip,
+ filePort: Number(this.ipServer.localFilePort)
+ }).then(res => {
+ if (res && res.success) {
+ this.$notify({
+ type: "success",
+ message: "淇濆瓨鎴愬姛"
+ });
+ } else {
+ this.$notify({
+ type: "error",
+ message: "淇濆瓨澶辫触"
+ });
+ }
+ })
+ },
+ submitGB28281() {
+ this.$refs["gb28181"].validate(valid => {
+ if (valid) {
+ saveGB28181Config(this.gb28181).then(rsp => {
+ if (rsp && rsp.success) {
+ this.$notify({
+ type: "success",
+ message: "GB28181璁剧疆淇濆瓨鎴愬姛"
+ });
+ }
+ });
+ } else {
+ console.log("error submit!!");
+ return false;
+ }
+ });
+ },
+ onIpBlur(e, ip) {
+ console.log(e, ip);
+ },
+ formatTime(number, format) {
+ var formateArr = ['Y', 'M', 'D', 'h', 'm', 's'];
+ var returnArr = [];
+
+ var date = new Date(number * 1000);
+ returnArr.push(date.getFullYear());
+ returnArr.push(this.formatNumber(date.getMonth() + 1));
+ returnArr.push(this.formatNumber(date.getDate()));
+
+ returnArr.push(this.formatNumber(date.getHours()));
+ returnArr.push(this.formatNumber(date.getMinutes()));
+ returnArr.push(this.formatNumber(date.getSeconds()));
+
+ for (var i in returnArr) {
+ format = format.replace(formateArr[i], returnArr[i]);
+ }
+ return format;
+ },
+
+ //鏁版嵁杞寲
+ formatNumber(n) {
+ n = n.toString()
+ return n[1] ? n : '0' + n
+ },
+ menuOpen(event) {
+
+ },
+ menuClose(event) {
+
+ },
+ handleEdit(row) {
+ console.log(row);
+ row.edit = true;
+ },
+ handleCancel(row) {
+ row.edit = false;
+ console.log(row);
+ },
+ handleSave(row) {
+ console.log(row);
+ row.edit = false;
+ this.$notify({
+ message: "淇濆瓨鎴愬姛",
+ type: "success"
+ });
+ },
+ //鏍¢獙鍩熷悕
+ vaildHost(str) {
+ let re = /^(?=^.{3,255}$)(http(s)?:\/\/)?(www\.)?[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+(:\d+)*(\/\w+\.\w+)*$/
+ return re.test(str)
+ },
+ changeProvince() {
+ let pid = this.locationCity.province;
+ getGb28181AreaList({ parentId: pid }).then(rsp => {
+ if (rsp && rsp.success) {
+ this.locationCity.cityOptions = rsp.data;
+ this.locationCity.city = this.locationCity.cityOptions[0].id;
+ this.changeCity();
+ }
+ })
+ },
+ changeCity() {
+ let pid = this.locationCity.city;
+ getGb28181AreaList({ parentId: pid }).then(rsp => {
+ if (rsp && rsp.success) {
+ this.locationCity.countyOptions = rsp.data;
+ this.locationCity.county = this.locationCity.countyOptions[0].id;
+ }
+ })
+ },
+ newGBID() {
+ let cCode = this.locationCity.county + "";
+ newGb28181ID({ code: cCode }).then(rsp => {
+ if (rsp && rsp.success) {
+ this.gb28181.PublicId = rsp.data;
+ }
+ })
+ }
+ }
+};
+</script>
+<style lang="scss">
+.s-basic-setting {
+ width: 100%;
+ height: 100%;
+ .el-form {
+ width: 1000px;
+ margin-top: 30px;
+ // margin-left: -80px;
+ .el-form-item {
+ text-align: left;
+ .el-button {
+ float: right;
+ }
+
+ .el-form-item__content {
+ text-align: left;
+ input {
+ max-width: 360px;
+ }
+ .el-date-editor.el-input,
+ .el-date-editor.el-input__inner {
+ width: 216px;
+ }
+ .el-checkbox__label {
+ padding-left: 5px;
+ }
+ }
+
+ .el-form-item__label {
+ text-align: left;
+ }
+ }
+ }
+ .alarmSetting {
+ .el-input {
+ width: 100%;
+ // padding-right: 10px;
+ }
+ .el-select {
+ max-width: 113px;
+ }
+ .el-slider {
+ width: calc(100% - 120px);
+ display: inline-block;
+ padding-right: 30px;
+ box-sizing: border-box;
+ vertical-align: middle;
+ }
+ .el-input-number {
+ width: 100px;
+ display: inline-block;
+ .el-input {
+ width: 100%;
+ }
+ }
+ }
+
+ .time-type {
+ height: 25px;
+ width: 413px;
+ line-height: 28px;
+ padding: 3px 23px;
+ font-size: 14px;
+ font-weight: 600;
+ background-color: #e4e6ed;
+ }
+ #e-basic-setting {
+ .el-tabs__header {
+ border: 0px solid #dcdfe6;
+ .el-tabs__item {
+ padding: 5px 50px;
+ height: 50px;
+ font-family: PingFangSC-Regular;
+ font-size: 14px;
+ color: #222222;
+ text-align: center;
+ border: 0px solid transparent;
+ }
+ .el-tabs__item:nth-child(2) {
+ padding-left: 50px;
+ }
+ .el-tabs__item:last-child {
+ padding-right: 50px;
+ }
+ .el-tabs__item.is-active {
+ color: #ff7733;
+ font-weight: bold;
+ // border-right-color: #fff;
+ // border-left-color: #fff;
+ }
+ .el-tabs__item:not(.is-disabled):hover {
+ color: #ff7733;
+ }
+ }
+ .el-tabs__active-bar {
+ background-color: #ff7733;
+ }
+ .xiangqin-label {
+ text-align: left;
+ width: 85px;
+ font-size: 14px;
+ line-height: 30px;
+ }
+ .xiangqing-info {
+ text-align: left;
+ font-size: 14px;
+ line-height: 30px;
+ }
+ }
+
+ #cut_min_duration {
+ .el-slider__bar {
+ background-color: #3d68e1;
+ }
+ .el-slider__button {
+ width: 10px;
+ height: 10px;
+ border: 4px solid #3d68e1;
+ }
+ }
+
+ #cut_max_duration {
+ .el-slider__bar {
+ background-color: #ff9e6e;
+ }
+ .el-slider__button {
+ width: 10px;
+ height: 10px;
+ border: 4px solid #ff9e6e;
+ }
+ }
+ .menu-css,
+ .el-menu {
+ border-right: none;
+ list-style: none;
+ position: relative;
+ margin: 0;
+ padding-left: 0;
+ background-color: #ffffff;
+ .el-submenu__title {
+ height: 35px;
+ line-height: 35px;
+ font-size: 14px;
+ color: #303133;
+ padding: 0 20px;
+ list-style: none;
+ cursor: pointer;
+ position: relative;
+ -webkit-transition: border-color 0.3s, background-color 0.3s, color 0.3s;
+ transition: border-color 0.3s, background-color 0.3s, color 0.3s;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+ white-space: nowrap;
+ }
+ .tree-font {
+ font-family: PingFangSC-Medium;
+ font-size: 14px;
+ color: #222222;
+ text-align: left;
+ }
+ li {
+ text-align: left;
+ .el-submenu__title {
+ // border-bottom: solid 1px #e6e6e6;
+ padding-left: 10px !important;
+ background-color: #e4e6ed !important;
+ border-radius: 2px;
+ .el-submenu__icon-arrow {
+ position: absolute;
+ top: 50%;
+ right: auto;
+ left: 135px;
+ margin-top: -7px;
+ -webkit-transition: -webkit-transform 0.3s;
+ transition: -webkit-transform 0.3s;
+ transition: transform 0.3s;
+ transition: transform 0.3s, -webkit-transform 0.3s;
+ font-size: 12px;
+ }
+ }
+ }
+ }
+ .save-btn {
+ text-align: right;
+ position: relative;
+ right: 40px;
+ }
+}
+</style>
+<style lang="scss" scoped>
+.menu-css,
+.el-menu {
+ border-right: none;
+ list-style: none;
+ position: relative;
+ margin: 0;
+ padding-left: 0;
+ background-color: #ffffff;
+
+ .tree-font {
+ font-family: PingFangSC-Medium;
+ font-size: 14px;
+ color: #222222;
+ text-align: left;
+ }
+ li {
+ text-align: left;
+ .el-submenu__title {
+ .el-submenu__icon-arrow {
+ position: absolute;
+ top: 50%;
+ right: 0;
+ margin-top: -7px;
+ -webkit-transition: -webkit-transform 0.3s;
+ transition: -webkit-transform 0.3s;
+ transition: transform 0.3s;
+ transition: transform 0.3s, -webkit-transform 0.3s;
+ font-size: 12px;
+ }
+ }
+ }
+}
+</style>
diff --git a/src/pages/settings/components/ClusterManagement.vue b/src/pages/settings/components/ClusterManagement.vue
new file mode 100644
index 0000000..d6d5d65
--- /dev/null
+++ b/src/pages/settings/components/ClusterManagement.vue
@@ -0,0 +1,620 @@
+<template>
+ <div class="s-cluster-management">
+ <div class="ui-top-view">
+ <div class="ui-top-title">瑙嗛鍒嗘瀽闆嗙兢绠$悊</div>
+ </div>
+ <el-row>
+ <el-col :span="12">
+ <el-tabs v-model="activeName" id="e-alaycluster" v-if="!isHasColony">
+ <el-tab-pane label="鍒涘缓闆嗙兢" name="1" :disabled="isHasColony">
+ <el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="80px">
+ <el-form-item label="闆嗙兢鍚嶇О" prop="clustername">
+ <el-input v-model="ruleForm.clustername" placeholder="鎵嬪姩杈撳叆, 濡傗�滈泦缇鈥�" size="small"></el-input>
+ </el-form-item>
+ <el-form-item label="闆嗙兢ID">
+ <el-input v-model="clusterid" placeholder="涓嶅厑璁歌緭鍏�,淇濆瓨鍚庡洖鏄�" disabled size="small"></el-input>
+ </el-form-item>
+ <el-form-item label="闆嗙兢瀵嗙爜" prop="clusterpwd" style="width:440px">
+ <el-input v-model="ruleForm.clusterpwd" placeholder="璇疯緭鍏�6-12浣嶅瘑鐮�,鎴栫偣鍑荤敓鎴�" size="small">
+ <el-button type="text" slot="suffix" @click="generatePassword">鐢熸垚瀵嗙爜</el-button>
+ </el-input>
+ </el-form-item>
+
+ <el-form-item label="铏氭嫙IP" prop="virtualip">
+ <ip-input :ip="ruleForm.virtualip" :on-blur="onIpBlur"></ip-input>
+ </el-form-item>
+ <el-form-item style="width:440px">
+ <el-button type="primary" size="small" @click="submitForm('ruleForm')">淇濆瓨</el-button>
+ </el-form-item>
+ </el-form>
+ </el-tab-pane>
+
+ <!-- 鍔犲叆宸叉湁闆嗙兢 -->
+ <el-tab-pane label="鍔犲叆宸叉湁闆嗙兢" name="2" :disabled="isHasColony">
+ <el-form label-width="80px" :model="joinForm" :rules="joinRules" ref="joinForm">
+ <el-form-item label="IP鍦板潃" style="width:440px">
+ <el-input v-model="joinForm.clusterip" placeholder="璇疯緭鍏ラ泦缇ゅ唴浠绘剰IP鍦板潃" size="small">
+ <el-button
+ type="text"
+ slot="suffix"
+ v-show="!searchDis"
+ @click="searchColony"
+ >鎼滅储闆嗙兢</el-button>
+ <el-button type="text" slot="suffix" v-show="searchDis" @click="stopSearch">
+ <i class="el-icon-loading"></i>鍋滄鎼滅储
+ </el-button>
+ </el-input>
+
+ <!-- <el-button size="mini" :disabled="searchDis" @click="searchColony">鎼滅储闆嗙兢</el-button>
+ <el-button size="mini" @click="stopSearch">鍋滄鎼滅储</el-button>-->
+ </el-form-item>
+ <el-form-item label="闆嗙兢瀵嗙爜" prop="clusterpwd" style="width:440px">
+ <el-input
+ v-model="joinForm.clusterpwd"
+ placeholder="璇疯緭鍏ラ泦缇ゅ瘑鐮�"
+ show-password
+ size="small"
+ ></el-input>
+ </el-form-item>
+ <el-form-item style="width:440px">
+ <el-button type="primary" @click="join('joinForm')" size="small">鍔犲叆闆嗙兢</el-button>
+ </el-form-item>
+ </el-form>
+ </el-tab-pane>
+ </el-tabs>
+ <!-- 鏈夐泦缇ょ殑鎯呭喌 -->
+ <div v-if="isHasColony" id="h-alaycluster">
+ <el-form :model="ruleForm" ref="ruleForm" label-width="80px">
+ <el-form-item label="闆嗙兢鍚嶇О" prop="clustername">
+ <el-input v-model="ruleForm.clustername" placeholder="鎵嬪姩杈撳叆, 濡傗�滈泦缇鈥�" size="small"></el-input>
+ </el-form-item>
+ <el-form-item label="闆嗙兢ID">
+ <el-input v-model="clusterid" placeholder="涓嶅厑璁歌緭鍏�,淇濆瓨鍚庡洖鏄�" disabled size="small"></el-input>
+ </el-form-item>
+ <el-form-item label="闆嗙兢瀵嗙爜" prop="clusterpwd" style="width:440px">
+ <el-input
+ v-model="ruleForm.clusterpwd"
+ disabled
+ placeholder="璇疯緭鍏�6-12浣嶅瘑鐮�,鎴栫偣鍑荤敓鎴�"
+ size="small"
+ ></el-input>
+ </el-form-item>
+
+ <el-form-item label="铏氭嫙IP" prop="virtualip">
+ <ip-input :ip="ruleForm.virtualip" :on-blur="onIpBlur"></ip-input>
+ </el-form-item>
+ <el-form-item style="width:440px;text-align: right;">
+ <el-button size="small" type="danger" @click="leave">閫�鍑洪泦缇�</el-button>
+ <el-button
+ style="margin-right:10px;"
+ type="primary"
+ size="small"
+ @click="submitForm('manageForm')"
+ >淇濆瓨</el-button>
+ </el-form-item>
+ </el-form>
+ </div>
+ </el-col>
+ <el-col :span="14" style="height: 100%;" v-if="members.length !== 0">
+ <serfDiagram
+ ref="diagram"
+ :members="members"
+ :agent="agentName"
+ v-loading="loading"
+ @selected-node="joinNode"
+ ></serfDiagram>
+ </el-col>
+ </el-row>
+ <div class="ui-top-view">
+ <div class="ui-top-title">瀛樺偍闆嗙兢绠$悊</div>
+ </div>
+ <el-row>
+ <el-col :span="12">
+ <el-tabs id="e-dbcluster" v-model="sActiveName">
+ <el-tab-pane label="鍒涘缓闆嗙兢" name="s-first">
+ <el-button type="primary" style="float: none;margin: 20px 0px;" size="small">鍒涘缓瀛樺偍闆嗙兢</el-button>
+ <p>鐐瑰嚮灏嗘湰鏈哄垱寤轰负瀛樺偍闆嗙兢</p>
+ </el-tab-pane>
+ <el-tab-pane label="鍔犲叆宸叉湁闆嗙兢" name="s-second">
+ <el-form label-width="80px">
+ <el-form-item label="IP鍦板潃" style="text-align: left;">
+ <el-input v-model="clusterip2" placeholder="璇疯緭鍏ラ泦缇ゅ唴浠绘剰IP鍦板潃" size="small">
+ <el-button
+ type="text"
+ slot="suffix"
+ v-show="!searchDis"
+ @click="searchColony"
+ >鎼滅储闆嗙兢</el-button>
+ </el-input>
+ </el-form-item>
+ <el-form-item>
+ <el-button type="primary" @click="join('joinForm')" size="small">鍔犲叆闆嗙兢</el-button>
+ </el-form-item>
+ </el-form>
+ </el-tab-pane>
+ <el-tab-pane label="绠$悊闆嗙兢" name="s-third">
+ <h3 style="text-align: left;margin: 10px 0px;">
+ <b>闆嗙兢鍚嶇О</b>
+ <span>xxx</span>
+ </h3>
+ <el-table :data="tableData" style="width: 100%">
+ <el-table-column prop="nodeType" label="鑺傜偣绫诲瀷"></el-table-column>
+ <el-table-column prop="nodeName" label="鑺傜偣鍚嶇О"></el-table-column>
+ <el-table-column prop="nodeIp" label="鑺傜偣IP鍦板潃"></el-table-column>
+ <el-table-column prop="registerTime" label="娉ㄥ唽鏃堕棿"></el-table-column>
+ </el-table>
+ </el-tab-pane>
+ </el-tabs>
+ </el-col>
+ </el-row>
+ </div>
+</template>
+
+<script>
+import {
+ createColony,
+ randomPwd,
+ search,
+ getSearchNodes,
+ stopSearching,
+ findCluster,
+ updateClusterName,
+ joinCluster,
+ leave
+} from "@/api/clusterManage";
+import serfDiagram from "@/components/serfDiagram";
+import ipInput from "@/components/subComponents/IPInput";
+
+export default {
+ components: {
+ serfDiagram,
+ ipInput
+ },
+ data() {
+ const checkPwd = (rule, value, callback) => {
+ if (!value) {
+ return callback(new Error("瀵嗙爜涓嶈兘涓虹┖"));
+ }
+ setTimeout(() => {
+ if (value.length > 16 || value.length < 6) {
+ callback(new Error("瀵嗙爜搴斾负6-16浣�!"));
+ } else {
+ callback();
+ }
+ }, 1000);
+ };
+ return {
+ activeName: "1",
+ sActiveName: "s-first",
+ clusterid: "",
+ clusterip2: "",
+ clusterpwd2: "",
+ sClusterip: "",
+ ruleForm: {
+ clustername: "",
+ clusterpwd: "",
+ virtualip: ""
+ },
+ manageForm: {
+ clustername: "娴嬭瘯闆嗙兢1",
+ clusterpwd: "123456",
+ virtualip: "192.168.1.188"
+ },
+ joinForm: {
+ clusterip: "",
+ clusterpwd: ""
+ },
+ rules: {
+ clustername: [
+ { required: true, message: "璇疯緭鍏ラ泦缇ゅ悕绉�", trigger: "change" }
+ ],
+ clusterpwd: [{ validator: checkPwd, trigger: "change" }],
+ virtualip: [
+ { required: true, message: "璇疯緭鍏ヨ櫄鎷烮P", trigger: "change" }
+ ]
+ },
+ joinRules: {
+ clusterpwd: [
+ { required: true, message: "璇疯緭鍏ラ泦缇ゅ瘑鐮�", trigger: "change" },
+ { validator: checkPwd, trigger: "change" }
+ ]
+ },
+ tableData: [
+ {
+ nodeType: "涓昏妭鐐�",
+ nodeName: "xxxx",
+ nodeIp: "192.168.12.102",
+ registerTime: "2016-04-04"
+ },
+ {
+ nodeType: "涓昏妭鐐�",
+ nodeName: "xxxx",
+ nodeIp: "192.168.14.122",
+ registerTime: "2016-05-04"
+ },
+ {
+ nodeType: "涓昏妭鐐�",
+ nodeName: "xxxx",
+ nodeIp: "192.168.10.132",
+ registerTime: "2016-02-12"
+ }
+ ],
+ scheduleId: "",
+ isHasColony: false,
+ currentCluster: {},
+ searchNum: "",
+ loading: false,
+ searchDis: false,
+ agentName: "",
+ members: []
+ };
+ },
+ watch: {},
+ methods: {
+ cleanValue() {
+ this.members = [];
+ },
+ sHandleClick(tab, event) {
+ console.log(tab, event);
+ },
+ submitForm(formName) {
+ this.$refs[formName].validate(valid => {
+ if (valid) {
+ alert("submit!");
+ let json = {
+ clusterId: this.clusterid,
+ clusterName: this.ruleForm.clustername,
+ password: this.ruleForm.clusterpwd,
+ virtualip: this.ruleForm.virtualip
+ };
+ this.createColony(json).then(() => {
+ this.findCluster();
+ });
+ } else {
+ console.log("error submit!!");
+ return false;
+ }
+ });
+ },
+ join(formName) {
+ this.$refs[formName].validate(valid => {
+ if (valid) {
+ if (Object.keys(this.currentCluster).length === 0) {
+ this.$notify({
+ type: "info",
+ duration: 1000,
+ message: "璇峰厛閫夋嫨涓�涓泦缇よ妭鐐�"
+ });
+ return true;
+ }
+ let nodeIps = this.members.map(i => {
+ return i.Address;
+ });
+ let json = {
+ clusterId: this.currentCluster.cluster_id,
+ password: this.joinForm.clusterpwd,
+ nodeIps: nodeIps
+ };
+ this.joinCluster(json).then(() => {
+ this.findCluster();
+ });
+ } else {
+ console.log("error submit!!");
+ return false;
+ }
+ });
+ },
+ async createColony(json) {
+ let res = await createColony(json);
+ console.log(res, "鍒涘缓闆嗙兢");
+ this.$notify({
+ title: res.success ? "鎴愬姛" : "澶辫触",
+ message: res.msg,
+ type: res.success ? "success" : "error"
+ });
+ },
+ async randomPwd() {
+ let res = await randomPwd();
+ if (res && res.success) {
+ this.ruleForm.clusterpwd = res.data;
+ }
+ },
+ async searchColony() {
+ this.$refs["joinForm"].validate(valid => {
+ if (valid) {
+ let json = {
+ password: this.joinForm.clusterpwd,
+ ip: this.joinForm.clusterip
+ };
+
+ this.search(json)
+ .then(() => {
+ this.setSchedule();
+ // this.searchDis = false;
+ // this.loading = false;
+ })
+ .catch(() => {
+ this.searchDis = false;
+ this.loading = false;
+ });
+ } else {
+ this.searchDis = false;
+ this.loading = false;
+ return false;
+ }
+ });
+ },
+ async search(json) {
+ let res = await search(json);
+ if (res && res.success) {
+ console.log(res, "鎼滅储闆嗙兢");
+ this.searchNum = res.data;
+ }
+ this.searchDis = true;
+ this.loading = true;
+ window.setTimeout(() => {
+ this.stopSearch();
+ }, 10 * 1000);
+ },
+ async getSearchNodes() {
+ let res = await getSearchNodes();
+ if (res && res.success) {
+ let list = res.data.map(i => {
+ let obj = {};
+ obj.cluster_id = i.clusterID ? i.clusterID : "";
+ obj.create_time = i.create_time ? i.create_time : "";
+ obj.id = i.nodeID ? i.nodeID : "";
+ obj.node_id = i.nodeID ? i.nodeID : "";
+ obj.Address = i.nodeAddress ? i.nodeAddress : "";
+ obj.nodeName = i.nodeAddress ? i.nodeAddress : "";
+ obj.role = i.role ? i.role : "pc";
+ return obj;
+ });
+ list.map(i => {
+ let found = this.members.find(element => {
+ return element.node_id === i.node_id;
+ });
+ if (found === undefined) {
+ this.members.push(i);
+ }
+ });
+ }
+ },
+ setSchedule() {
+ this.scheduleId = window.setInterval(() => {
+ this.getSearchNodes();
+ }, 1000);
+ },
+ async stopSearch() {
+ if (!this.loading) {
+ return true;
+ }
+ stopSearching({
+ searchNum: this.searchNum
+ }).then((res) => {
+ console.log(res, '姝e父缁撴潫')
+ this.loading = false;
+ this.searchDis = false;
+ window.clearInterval(this.scheduleId);
+ }).catch((err) => {
+ console.log(err, '鎶ラ敊缁撴潫')
+ this.$notify({
+ type: 'error',
+ duration: 1000,
+ message: '鍋滄鎼滅储鎶ラ敊锛�'
+ })
+ // window.setTimeout(()=>{
+ // this.loading = false;
+ // this.searchDis = false;
+ // window.clearInterval(this.scheduleId);
+ // },2000)
+ })
+ },
+ async findCluster() {
+ let res = await findCluster();
+ if (res && res.success) {
+ if (res.data && res.data.clusterId) {
+ this.isHasColony = true;
+ this.activeName = "3";
+ this.clusterid = res.data.clusterId;
+ this.ruleForm.clustername = res.data.clusterName;
+ this.ruleForm.clusterpwd = res.data.clusterpwd
+ this.ruleForm.virtualip = res.data.virtualip
+ let list = res.data.nodes.map(i => {
+ let obj = {};
+ obj.cluster_id = i.cluster_id;
+ obj.clusterName = res.data.clusterName;
+ obj.create_time = i.create_time;
+ obj.id = i.id;
+ obj.node_id = i.node_id;
+ obj.node_ip = i.node_ip;
+ obj.nodeName = i.node_name;
+ obj.Address = i.node_ip;
+ obj.role = i.role ? i.role : "pc";
+ return obj;
+ });
+ this.members = this.members.concat(list);
+ } else {
+ this.isHasColony = false;
+ // this.activeName = '1'
+ }
+ }
+ },
+ async updateClusterName() {
+ let res = await updateClusterName({
+ clusterName: this.mangeForm.colonyName
+ });
+ this.$notify({
+ title: res.success ? "鎴愬姛" : "澶辫触",
+ message: res.msg,
+ type: res.success ? "success" : "error"
+ });
+ },
+ async joinCluster(json) {
+ let res = await joinCluster(json);
+ if (res.success) {
+ this.members = []
+ }
+ this.$notify({
+ title: res.success ? "鎴愬姛" : "澶辫触",
+ message: res.msg,
+ type: res.success ? "success" : "error"
+ });
+ },
+ leave() {
+ this.$confirm(`纭畾閫�鍑洪泦缇ゅ悧?`, {
+ center: true,
+ cancelButtonClass: "comfirm-class-cancle",
+ confirmButtonClass: "comfirm-class-sure"
+ }).then(async () => {
+ let res = await leave();
+ this.$notify({
+ title: res.success ? "鎴愬姛" : "澶辫触",
+ message: res.msg,
+ type: res.success ? "success" : "error"
+ });
+ if (res && res.success) {
+ this.ruleForm.clustername = "";
+ this.ruleForm.clusterpwd = ""
+ this.clusterid = "";
+ this.isHasColony = false;
+ this.activeName = "1"
+ }
+ }).catch(() => { });
+
+ },
+ joinNode(event, node) {
+ this.currentCluster.cluster_id = node.cluster_id;
+ if (this.activeName === "3") {
+ this.manageForm.clustername = node.clusterName;
+ this.clusterid = node.cluster_id;
+ return;
+ }
+ if (this.activeName === "2") {
+ this.$refs["joinForm"].validate(valid => {
+ if (valid) {
+ this.$confirm("鏄惁瑕佸姞鍏ヨ妭鐐� " + node.nodeName + "?", "鍔犲叆闆嗙兢", {
+ confirmButtonText: "纭畾",
+ cancelButtonText: "鍙栨秷",
+ type: "success"
+ })
+ .then(() => {
+ // this.agentName = 'node' + this.members.length
+ // this.members.push({
+ // nodeName: this.agentName,
+ // Address: '172.10.10.26',
+ // role: 'pc'
+ // })
+ // this.$notify({
+ // type: 'success',
+ // duration: 1000,
+ // message: '鍔犲叆鎴愬姛!'
+ // })
+ console.log(this.currentCluster, '閫夋嫨鐨勯泦缇よ妭鐐�')
+ this.join("joinForm");
+ })
+ .catch(() => {
+ this.$notify({
+ type: "info",
+ duration: 1000,
+ message: "宸插彇娑�"
+ });
+ });
+ } else {
+ console.log("error submit!!");
+ return false;
+ }
+ });
+ }
+ },
+ generatePassword() {
+ var chars =
+ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+ var uuid = [];
+
+ for (let i = 0; i < 16; i++) {
+ uuid[i] = chars[0 | (Math.random() * 50)];
+ }
+
+ this.ruleForm.clusterpwd = uuid.join("");
+ },
+ onIpBlur(ip) {
+ this.ruleForm.virtualip = ip;
+ }
+ },
+ mounted() {
+ this.findCluster();
+ },
+ created() { }
+};
+</script>
+<style lang="scss">
+.s-cluster-management {
+ width: 100%;
+ height: 100%;
+ overflow: auto;
+
+ .el-button {
+ float: right;
+ }
+ .el-form-item__content {
+ text-align: left;
+ input {
+ max-width: 360px;
+ }
+ }
+
+ #e-alaycluster,
+ #e-dbcluster {
+ .el-tabs__header {
+ border: 0px solid #dcdfe6;
+ .el-tabs__item {
+ padding: 5px 50px;
+ height: 50px;
+ font-family: PingFangSC-Regular;
+ font-size: 14px;
+ color: #222222;
+ text-align: center;
+ border: 0px solid transparent;
+ }
+ .el-tabs__item:nth-child(2) {
+ padding-left: 50px;
+ }
+ .el-tabs__item:last-child {
+ padding-right: 50px;
+ }
+ .el-tabs__item.is-active {
+ color: #ff7733;
+ font-weight: bold;
+ // border-right-color: #fff;
+ // border-left-color: #fff;
+ }
+ .el-tabs__item:not(.is-disabled):hover {
+ color: #ff7733;
+ }
+ }
+ .el-tabs__active-bar {
+ background-color: #ff7733;
+ }
+ .el-form-item__content {
+ text-align: left;
+ input {
+ max-width: 420px;
+ }
+ }
+ }
+
+ #h-alaycluster {
+ .el-form-item__content {
+ text-align: left;
+ input {
+ max-width: 360px;
+ }
+ }
+ }
+}
+.ui-top-view {
+ height: 30px;
+ line-height: 30px;
+}
+</style>
diff --git a/src/pages/settings/components/LogManagement.vue b/src/pages/settings/components/LogManagement.vue
new file mode 100644
index 0000000..2b2d37e
--- /dev/null
+++ b/src/pages/settings/components/LogManagement.vue
@@ -0,0 +1,190 @@
+<template>
+ <div class="s-log-management">
+ <div class="top">
+ <b>鏃ュ織绫诲瀷:</b>
+ <el-select v-model="logValue" placeholder="璇烽�夋嫨" size="small">
+ <el-option
+ v-for="item in logOptions"
+ :key="item.value"
+ :label="item.label"
+ :value="item.value"
+ ></el-option>
+ </el-select>
+ <b>鏃堕棿:</b>
+ <el-date-picker
+ v-model="timeValue"
+ type="datetimerange"
+ size="small"
+ range-separator="鑷�"
+ start-placeholder="寮�濮嬫棩鏈�"
+ end-placeholder="缁撴潫鏃ユ湡"
+ ></el-date-picker>
+ <el-input
+ v-model="searchValue"
+ placeholder="璇疯緭鍏ュ唴瀹�"
+ clearable
+ style="width: 150px;margin: 0px 10px;"
+ size="small"
+ ></el-input>
+ <el-button type="primary" size="small">鎼滅储</el-button>
+ <el-button type="danger" size="small" @click="delSelected">鎵归噺鍒犻櫎</el-button>
+ <el-button type="text" size="small" style="font-size: 13px;font-weight: 600;">瀵煎嚭</el-button>
+ </div>
+ <div class="foot-table s-table">
+ <el-table
+ ref="multipleTable"
+ highlight-current-row
+ :data="tableData"
+ style="width: 100%"
+ :header-cell-style="{background:'#f8f8f8',color:'#222222'}"
+ @selection-change="handleSelectionChange"
+ >
+ <el-table-column type="selection" width="55"></el-table-column>
+ <el-table-column :align="'center'" sortable prop="index" label="搴忓彿"></el-table-column>
+ <el-table-column :align="'center'" sortable prop="logtype" label="鏃ュ織绫诲瀷"></el-table-column>
+ <el-table-column :align="'center'" sortable prop="username" label="鐢ㄦ埛鍚�"></el-table-column>
+ <el-table-column :align="'center'" sortable prop="ipaddress" label="IP鍦板潃"></el-table-column>
+ <el-table-column :align="'center'" sortable prop="operation" label="鎿嶄綔鍔熻兘"></el-table-column>
+ <el-table-column :align="'center'" sortable prop="operatetime" label="鎿嶄綔鏃堕棿"></el-table-column>
+ <el-table-column :align="'center'" sortable prop="operateinfo" label="鎿嶄綔淇℃伅"></el-table-column>
+ <el-table-column label="鎿嶄綔" :align="'center'">
+ <template slot-scope="scope">
+ <el-button
+ type="text"
+ style="color: red;font-size:16px"
+ @click="handleDelete(scope.$index, scope.row)"
+ icon="el-icon-delete"
+ ></el-button>
+ </template>
+ </el-table-column>
+ </el-table>
+ </div>
+ </div>
+</template>
+
+<script>
+export default {
+ data() {
+ return {
+ tableData: [
+ {
+ index: "1",
+ logtype: "寮傚父",
+ username: "admin",
+ ipaddress: "192.168.10.110",
+ operation: "娣诲姞鎽勫儚鏈�",
+ operatetime: "2019-5-31 16:38:21",
+ operateinfo: "娣诲姞鎿嶄綔"
+ },
+ {
+ index: "2",
+ logtype: "淇℃伅",
+ username: "admin",
+ ipaddress: "192.168.10.108",
+ operation: "鍒犻櫎鎽勫儚鏈�",
+ operatetime: "2019-5-31 16:38:21",
+ operateinfo: "娣诲姞鎿嶄綔"
+ },
+ {
+ index: "3",
+ logtype: "鎿嶄綔",
+ username: "admin",
+ ipaddress: "192.168.10.110",
+ operation: "娣诲姞鎽勫儚鏈�",
+ operatetime: "2019-5-31 16:38:21",
+ operateinfo: "娣诲姞鎿嶄綔"
+ },
+ {
+ index: "4",
+ logtype: "寮傚父",
+ username: "admin",
+ ipaddress: "192.168.10.110",
+ operation: "娣诲姞鎽勫儚鏈�",
+ operatetime: "2019-5-31 16:38:21",
+ operateinfo: "娣诲姞鎿嶄綔"
+ },
+ {
+ index: "5",
+ logtype: "寮傚父",
+ username: "admin",
+ ipaddress: "192.168.10.110",
+ operation: "鍒犻櫎鎽勫儚鏈�",
+ operatetime: "2019-5-31 16:38:21",
+ operateinfo: "娣诲姞鎿嶄綔"
+ },
+ {
+ index: "6",
+ logtype: "寮傚父",
+ username: "admin",
+ ipaddress: "192.168.10.110",
+ operation: "娣诲姞鎽勫儚鏈�",
+ operatetime: "2019-5-31 16:38:21",
+ operateinfo: "娣诲姞鎿嶄綔"
+ }
+ ],
+ multipleSelection: [],
+ logOptions: [
+ {
+ value: "鍏ㄩ儴绫诲瀷",
+ label: "鍏ㄩ儴绫诲瀷"
+ },
+ {
+ value: "鍏朵粬绫诲瀷",
+ label: "鍏朵粬绫诲瀷"
+ }
+ ],
+ logValue: "鍏ㄩ儴绫诲瀷",
+ timeValue: [
+ new Date(2000, 10, 10, 10, 10),
+ new Date(2000, 10, 11, 10, 10)
+ ],
+ searchValue: ""
+ };
+ },
+ methods: {
+ handleDelete(index, row) {
+ console.log(index, row);
+ },
+ handleSelectionChange(val) {
+ this.multipleSelection = val;
+ },
+ delSelected() {
+ console.log(this.multipleSelection);
+ }
+ }
+};
+</script>
+<style lang="scss">
+.s-log-management {
+ height: 100%;
+ width: 100%;
+ .top {
+ width: 100%;
+ margin-top: 10px;
+ margin-bottom: 20px;
+ overflow-y: auto;
+ min-width: 1156px;
+ height: 40px;
+ text-align: left;
+ b {
+ padding: 0px 10px;
+ }
+ }
+ .export {
+ display: inline-block;
+ padding-right: 10px;
+ box-sizing: border-box;
+ margin-top: 20px;
+ b:hover {
+ color: #2249b4;
+ }
+ }
+ .clear-searching {
+ cursor: pointer;
+ text-decoration: underline;
+ width: 40px;
+ font-size: 13px;
+ color: #3d68e1;
+ }
+}
+</style>
diff --git a/src/pages/settings/components/RadioSet.vue b/src/pages/settings/components/RadioSet.vue
new file mode 100644
index 0000000..89cac81
--- /dev/null
+++ b/src/pages/settings/components/RadioSet.vue
@@ -0,0 +1,189 @@
+<template>
+ <div class="s-radio-set">
+ <div class="add-btn">
+ <el-button size="mini" type="primary" @click="handleAdd()">娣诲姞</el-button>
+ </div>
+ <el-table
+ border
+ highlight-current-row
+ :data="tableData"
+ style="width: 100%; margin-top:40px; color:#000"
+ :header-cell-style="{background:'#f8f8f8',color:'#222222'}"
+ >
+ <el-table-column align="center" type="index" label="搴忓彿" width="100px"></el-table-column>
+
+ <el-table-column :align="'center'" label="骞挎挱鍚嶇О">
+ <template slot-scope="{row}">
+ <el-input v-if="row.edit" :autofocus="row.edit" v-model="row.radiosName" size="small" />
+ <span v-else>{{ row.radiosName }}</span>
+ </template>
+ </el-table-column>
+
+ <el-table-column :align="'center'" label="IP鍦板潃">
+ <template slot-scope="{row}">
+ <el-input v-if="row.edit" v-model="row.ipAddress" size="small" />
+ <span v-else>{{ row.ipAddress }}</span>
+ </template>
+ </el-table-column>
+
+ <el-table-column :align="'center'" label="杩炴帴娴嬭瘯">
+ <template slot-scope="{row}">
+ <i v-show="row.isCon" class="el-icon-success" style="color:green; font-size:18px"></i>
+
+ <el-button type="text" @click="handleTest(row)">杩炴帴娴嬭瘯</el-button>
+ </template>
+ </el-table-column>
+
+ <el-table-column label="鎿嶄綔" :align="'center'">
+ <template slot-scope="scope">
+ <template v-if="scope.row.edit">
+ <el-button size="mini" type="info" @click="handleCancel(scope.row)">鍙栨秷</el-button>
+ <el-button size="mini" type="primary" @click="handleSave(scope.row)">淇濆瓨</el-button>
+ </template>
+ <template v-else>
+ <el-button
+ type="text"
+ style="color: black;font-size:16px"
+ @click="handleEdit(scope.row)"
+ icon="el-icon-edit"
+ ></el-button>
+ <el-button
+ type="text"
+ style="color: red;font-size:16px"
+ @click="handleDelete(scope.$index)"
+ icon="el-icon-delete"
+ ></el-button>
+ </template>
+ </template>
+ </el-table-column>
+ </el-table>
+ </div>
+</template>
+
+<script>
+export default {
+ filters: {
+ isCon(r) {
+ return r.isCon ? r.isCon : false
+ }
+ },
+ data() {
+ return {
+ radioName: "",
+ ipAddress: "",
+ tableData: [
+ {
+ index: "1",
+ radiosName: "鎿嶅満",
+ ipAddress: "192.168.1.101",
+ edit: false,
+ isCon: false
+ },
+ {
+ edit: false,
+ index: "2",
+ radiosName: "鏁欏",
+ ipAddress: "192.168.12.61",
+ isCon: false
+ },
+ {
+ edit: false,
+ index: "3",
+ radiosName: "淇濆畨瀹�",
+ ipAddress: "192.168.13.121",
+ isCon: false
+ }
+ ]
+ };
+ },
+ mounted() {
+ this.testAll()
+ },
+ methods: {
+ testAll() {
+ this.tableData.forEach(l => {
+ this.$set(l, "isCon", false)
+ })
+ },
+ handleEdit(row) {
+ console.log(row);
+ row.edit = true;
+ },
+ handleCancel(row) {
+ row.edit = false;
+ console.log(row);
+ },
+ handleDelete(index) {
+ this.$confirm("纭鍒犻櫎璇ュ箍鎾悧?", {
+ center: true,
+ cancelButtonClass: "comfirm-class-cancle",
+ confirmButtonClass: "comfirm-class-sure"
+ })
+ .then(() => {
+ this.tableData.splice(index, 1)
+ this.$notify({
+ type: "success",
+ message: "鍒犻櫎鎴愬姛!"
+ });
+ })
+ .catch(() => { });
+ },
+ handleSave(row) {
+ console.log(row);
+ row.edit = false;
+ this.$notify({
+ message: "淇濆瓨鎴愬姛",
+ type: "success"
+ });
+ },
+ handleTest(row) {
+ this.$set(row, 'isCon', true)
+ },
+ handleAdd() {
+ this.tableData.push({
+ radiosName: "",
+ ipAddress: "",
+ edit: true,
+ isCon: false
+ })
+ }
+ }
+};
+</script>
+<style lang="scss">
+.s-radio-set {
+ width: 100%;
+ height: 100%;
+ .el-dialog {
+ border-radius: 8px;
+ border: 1px solid #ccc;
+ .el-dialog__header {
+ border-bottom: 1px solid #ccc;
+ }
+ }
+
+ .add-btn {
+ float: right;
+ margin-bottom: 7px;
+ }
+}
+.e-message {
+ width: 331px;
+}
+.e-confirm {
+ border-color: #ff0000 !important;
+ background-color: #ff0000 !important;
+}
+.e-confirm:hover {
+ border-color: #f83131d6 !important;
+ background-color: #f83131d6 !important;
+}
+.e-cancel {
+ border-color: #eaeaea !important;
+ background-color: #eaeaea !important;
+}
+.e-cancel:hover {
+ border-color: #e9e9e9 !important;
+ background-color: #e9e9e9 !important;
+}
+</style>
diff --git a/src/pages/settings/components/SystemMaintenance.vue b/src/pages/settings/components/SystemMaintenance.vue
new file mode 100644
index 0000000..bf40d81
--- /dev/null
+++ b/src/pages/settings/components/SystemMaintenance.vue
@@ -0,0 +1,514 @@
+<template>
+ <el-tabs
+ id="systemMaintenance"
+ v-model="activeName"
+ v-loading="loading"
+ :element-loading-text="loadingText"
+ >
+ <el-tab-pane label="璁惧缁存姢" name="first" v-if="isShow('videoSystem:sysManage:sysfix')">
+ <div class="s-system-maintenance">
+ <div class="box-card">
+ <div class="ui-top-view">
+ <div class="ui-top-title">閲嶅惎</div>
+ </div>
+ <el-divider></el-divider>
+
+ <div class="box-card-content">
+ <el-row>
+ <el-col :span="1">
+ <el-button type="primary" size="small" style="width:80px" @click="reboot">閲嶅惎</el-button>
+ </el-col>
+ <el-col :span="23">
+ <b class="card-text">閲嶅惎鑺傜偣</b>
+ </el-col>
+ </el-row>
+ <el-row style="margin-top:20px">
+ <el-col>
+ <vue-cron :expression="rebootCron" @update="setRebootCron" />
+ </el-col>
+ </el-row>
+ </div>
+ </div>
+ <!--
+ <div class="box-card">
+ <div class="ui-top-view">
+ <div class="ui-top-title">鎭㈠榛樿鍊�</div>
+ </div>
+ <el-divider></el-divider>
+
+ <div class="box-card-content">
+ <el-row>
+ <el-col :span="1">
+ <el-button type="primary" size="small">绠�鍗曟仮澶�</el-button>
+ </el-col>
+ <el-col :span="23">
+ <b class="card-text">绠�鍗曟仮澶嶈澶囧弬鏁�</b>
+ </el-col>
+ </el-row>
+ <el-row style="margin-top:20px">
+ <el-col :span="1">
+ <el-button type="primary" size="small">瀹屽叏鎭㈠</el-button>
+ </el-col>
+ <el-col :span="23">
+ <b class="card-text">瀹屽叏鎭㈠璁惧鍙傛暟鍒板嚭鍘傝缃�</b>
+ </el-col>
+ </el-row>
+ </div>
+ </div>
+
+ <div class="box-card">
+ <div class="ui-top-view">
+ <div class="ui-top-title">鍙傛暟瀵煎叆瀵煎嚭</div>
+ </div>
+ <el-divider></el-divider>
+
+ <div class="box-card-content">
+ <el-row :gutter="4">
+ <el-col :span="1">
+ <el-button type="info" size="small" style="width:80px">瀵煎叆</el-button>
+ </el-col>
+ <el-col :span="3" style="padding-left:30px">
+ <el-input placeholder="涓婁紶鍙傛暟鏂囦欢" size="small" :readonly="true">
+ <el-upload slot="suffix" action="https://jsonplaceholder.typicode.com/posts/">
+ <el-button
+ type="text"
+ icon="el-icon-upload2"
+ size="small"
+ style="font-size:18px; color:#0088ff"
+ ></el-button>
+ </el-upload>
+ </el-input>
+ </el-col>
+ </el-row>
+ <el-row style="margin-top:20px">
+ <el-col :span="1">
+ <el-button type="primary" size="small">璁惧鍙傛暟</el-button>
+ </el-col>
+ <el-col :span="23">
+ <b class="card-text">鍙傛暟瀵煎嚭</b>
+ </el-col>
+ </el-row>
+ </div>
+ </div>
+ -->
+ <div class="box-card">
+ <div class="ui-top-view">
+ <div class="ui-top-title">鍗囩骇</div>
+ </div>
+ </div>
+ <el-divider></el-divider>
+ <div class="box-card-content">
+ <el-row :gutter="4">
+ <el-col :span="6">
+ <file-uploader
+ single
+ uploadPlaceholder="涓婁紶鍗囩骇鏂囦欢"
+ url="/data/api-v/sysset/patchUpdate"
+ @complete="onFileUpload"
+ @file-added="onFileAdded"
+ />
+ </el-col>
+ <el-col :span="2">
+ <el-button
+ type="primary"
+ size="small"
+ style="width:80px"
+ @click="upgrade"
+ :disabled="!fileAdded"
+ :loading="upgrading"
+ >鍗囩骇</el-button>
+ </el-col>
+ <el-col :span="16" class="upload-msg">
+ <span v-html="patchUpdateStatus"></span>
+ </el-col>
+ </el-row>
+ </div>
+ </div>
+ </el-tab-pane>
+ <el-tab-pane label="鏁版嵁搴撶淮鎶�" name="second" v-if="isShow('videoSystem:sysManage:dbfix')">
+ <div class="box">
+ <p class="title">
+ <label>鏁版嵁娓呯悊</label>
+ </p>
+ <div class="range">
+ <div class="left">
+ <p>閫夋嫨鏁版嵁鑼冨洿锛�</p>
+ </div>
+ <div class="middle">
+ <el-date-picker
+ v-model="dataRange"
+ type="daterange"
+ range-separator="鑷�"
+ start-placeholder="寮�濮嬫棩鏈�"
+ end-placeholder="缁撴潫鏃ユ湡"
+ style="height:38px"
+ :picker-options="pickerOptions"
+ ></el-date-picker>
+ </div>
+ <div class="right">
+ <el-button @click="deleteData" style="height:38px;background:#ff0000;color:white">鍒犻櫎鏁版嵁</el-button>
+ </div>
+ </div>
+ <div class="tip">
+ <i class="iconfont icontishi-zhuyi"></i>
+ <p class="zhuyi">璇锋敞鎰忥紝鎸変互涓婃棩鏈熻寖鍥村垹闄ょ殑鏁版嵁涓嶅彲鎭㈠锛岀珛鍗崇敓鏁堬紝璇疯皑鎱庢搷浣�</p>
+ </div>
+ </div>
+ </el-tab-pane>
+ </el-tabs>
+
+</template>
+
+<script>
+import { rebootServer, getDevInfo, getRebootTask, setRebootTask, fileUpload, doUpgrade,deleteDate } from "@/api/system"
+import VueCron from "@/components/subComponents/VueCron"
+import FileUploader from "@/components/subComponents/FileUpload/index"
+
+export default {
+ components: {
+ VueCron,
+ FileUploader
+ },
+ data() {
+ return {
+ timer: null,
+ buttonAuthority: sessionStorage.getItem("buttonAuthoritys") || [],
+ rebootCron: "",
+ activeName: "first",
+ restartValue: "涓嶉噸鍚�",
+ restartTimeValue: new Date(2019, 9, 10, 18, 40),
+ loading: false,
+ loadingText: '',
+ probeSum: 0,
+ patchUpdateStatus: "",
+ dataRange: [
+ this.$moment().format("YYYY-MM-DD HH:mm:ss"),
+ this.$moment().format("YYYY-MM-DD HH:mm:ss")
+ ],
+ fileUploadUrl: fileUpload,
+ patchFile: {},
+ pickerOptions: {
+ disabledDate(time) {
+ var day = new Date()
+ day.setTime(day.getTime() - 24 * 60 * 60 * 1000)
+ return time.getTime() > day;
+ },
+ },
+ upgrading: false,
+ fileAdded: false
+ };
+ },
+ mounted() {
+ this.getRebootCron()
+ if (!this.isShow('videoSystem:sysManage:sysfix')) {
+ console.log("榛樿鏄剧ず鏁版嵁搴撶淮鎶�")
+ this.activeName = "second"
+ }
+ },
+ computed: {
+ isAdmin() {
+ if (
+ sessionStorage.getItem('userInfo') &&
+ sessionStorage.getItem('userInfo') !== ''
+ ) {
+ let loginName = JSON.parse(sessionStorage.getItem('userInfo')).username
+ return (
+ loginName === 'superadmin' || loginName === 'basic'
+ )
+ }
+ return false;
+ }
+ },
+ methods: {
+ isShow (authority) {
+ if (this.isAdmin) {
+ return true
+ } else if (
+ this.buttonAuthority.indexOf(',' + authority + ',') > -1
+ ) {
+ return true
+ } else {
+ return false
+ }
+ },
+ format(array) {
+ return [
+ this.$moment(array[0]).format("YYYY-MM-DD"),
+ this.$moment(array[1]).format("YYYY-MM-DD")
+ ];
+ },
+ getRebootCron() {
+ getRebootTask().then(rsp => {
+ this.rebootCron = rsp.data
+ })
+ },
+ setRebootCron(value) {
+ this.rebootCron = value
+ setRebootTask({ task: value }).then(rsp => {
+ if (rsp && rsp.success) {
+ this.$notify({
+ type: "success",
+ message: "閰嶇疆鎴愬姛"
+ })
+ }
+ }).catch(err => {
+ this.$notify({
+ type: "error",
+ message: "閰嶇疆澶辫触"
+ })
+ })
+ },
+ reboot() {
+ this.$confirm('纭畾瑕侀噸鍚鑺傜偣鍚�?', {
+ center: true,
+ cancelButtonClass: 'comfirm-class-cancle',
+ confirmButtonClass: 'comfirm-class-sure'
+ }).then(() => {
+ this.loading = true;
+ this.loadingText = "鏅鸿兘璁$畻鑺傜偣姝e湪閲嶅惎锛岃鑰愬績绛夊緟..."
+ rebootServer().then(rsp => {
+ this.probeServer(this.reLogin)
+ }).catch(err => {
+ if (err.status == 400) {
+ this.loading = false;
+ this.$notify({
+ type: "error",
+ message: "閲嶅惎璁$畻鑺傜偣澶辫触"
+ })
+ } else {
+ this.probeServer(this.reLogin)
+ }
+ })
+ })
+ },
+ deleteData() {
+ var timeRange = this.format(this.dataRange);
+ var showStartTime = timeRange[0]
+ var showEndTime = timeRange[1]
+ console.log("鏃堕棿锛�",showStartTime,showEndTime)
+ this.$confirm("鎻愮ず锛�"+showStartTime+" 鑷� "+showEndTime+" 浜х敓鐨勫叏閮ㄦ暟鎹皢琚垹闄わ紝姝ゆ搷浣滅珛鍗崇敓鏁堬紝涓嶅彲鎭㈠锛屾槸鍚﹀垹闄わ紵", {
+ center: true,
+ cancelButtonClass: "comfirm-class-cancle",
+ confirmButtonClass: "comfirm-class-sure"
+ }).then(() => {
+ this.loading = true
+ this.loadingText = "姝e湪鍒犻櫎鏁版嵁锛岃绋嶅�欙紒"
+ var param = {
+ startTime: showStartTime,
+ endTime: showEndTime
+ }
+ deleteDate(param).then(resp => {
+ if (resp.success) {
+ this.$message({
+ type: "success",
+ message: "鍒犻櫎鏁版嵁鎴愬姛"
+ })
+ this.loading = false
+ }
+ }).catch(err => {
+ this.$message({
+ type: "error",
+ message: "鍒犻櫎鏁版嵁澶辫触锛�"
+ })
+ this.loading = false
+ })
+
+ }).catch(() => {
+ console.log("鍙栨秷浜嗭紒")
+ })
+ },
+ reLogin() {
+ this.$router.push("/")
+ },
+ probeServer(callback) {
+ this.probeSum++;
+ let _this = this
+ if (this.probeSum > 60) {
+ this.$confirm('杩炴帴鏈嶅姟鍣ㄥけ璐�, 璇峰埛鏂伴〉闈㈡垨鑱旂郴绠$悊鍛�', '澶辫触', {
+ type: 'error',
+ cancelButtonClass: 'comfirm-class-cancle',
+ confirmButtonClass: 'comfirm-class-sure'
+ }).then(() => {
+ // _this.$router.push("/")
+ callback()
+ })
+ return
+ }
+
+ this.timer = setTimeout(() => {
+ getDevInfo().then(() => {
+ // _this.$router.push("/")
+ callback()
+ }).catch(err => {
+ _this.probeServer(callback)
+ })
+ }, 10000)
+ },
+ onFileUpload(file) {
+ this.patchUpdateStatus = `<span style="color:green">涓婁紶鎴愬姛, 鐐瑰嚮鍗囩骇鎸夐挳寮�濮嬪崌绾�</span>`
+ this.patchFile = { ...file }
+ this.fileAdded = true
+ },
+ onFileAdded() {
+ this.patchUpdateStatus = ""
+ },
+ upgrade() {
+ this.upgrading = true
+ this.patchUpdateStatus = `<span style="color:red">姝e湪鍗囩骇...</span>`
+ doUpgrade(this.patchFile).then(rsp => {
+ this.upgrading = false
+
+ if (rsp && rsp.success) {
+ clearTimeout(this.timer)
+ this.doneUpgrade()
+ }
+ }).catch(err => {
+ if (err.code) {
+ this.upgrading = false
+ this.patchUpdateStatus = `<span style="color:red">${err.data}</span>`
+ clearTimeout(this.timer)
+ } else {
+ this.probeServer(this.doneUpgrade)
+ }
+ })
+ },
+ doneUpgrade() {
+ this.upgrading = false
+ this.patchUpdateStatus = `<span style="color:green">鍗囩骇鎴愬姛</span>`
+ let _this = this
+ this.$confirm('鍗囩骇鎴愬姛, 璇烽噸鏂扮櫥褰曠郴缁�', '鎴愬姛', {
+ type: 'success',
+ cancelButtonClass: 'comfirm-class-cancle',
+ confirmButtonClass: 'comfirm-class-sure'
+ }).then(() => {
+ _this.reLogin()
+ })
+ }
+ }
+};
+</script>
+<style lang="scss">
+.s-system-maintenance {
+ width: 100%;
+ height: 100%;
+ .box-card {
+ text-align: left;
+ height: auto;
+ margin: 10px 0px;
+ .box-card-content {
+ padding-bottom: 40px;
+ .card-text {
+ padding: 0 30px;
+ line-height: 32px;
+ }
+ }
+ }
+
+ .upload-icon {
+ font-size: 18px;
+ color: #0088ff;
+ }
+ .upload-msg {
+ padding-left: 10px;
+ text-align: left;
+ span {
+ line-height: 32px;
+ font-size: 13px;
+ }
+ }
+}
+.box{
+ width: 50%;
+ min-width: 700px;
+ height: 270px;
+ border: 1px solid #eee;
+ .title {
+ font-size:20px;
+ font-weight: bold;
+ text-align: left;
+ padding: 20px;
+ border-bottom: 1px solid #eee;
+ }
+ .range {
+ width: 100%;
+ padding-top: 30px;
+ height: 38px;
+ .left {
+ width: 120px;
+ float: left;
+ text-align: right;
+ font-size: 14px;
+ p {
+ height: 38px;
+ line-height: 38px;
+ }
+ }
+ .middle {
+ width: 50%;
+ min-width: 400px;
+ height: 38px;
+ float: left;
+ }
+ .right {
+ width: 20%;
+ height: 38px;
+ float: left;
+ }
+ }
+ .tip {
+ width: 100%;
+ padding: 30px 0px 0px 30px;
+ height: 34px;
+
+ .zhuyi {
+ font-size: 14px;
+ height: 34px;
+ line-height: 34px;
+ margin-left: 20px;
+ float: left;
+ }
+ i {
+ font-size: 32px;
+ color: #e99038;
+ float: left;
+ }
+ }
+}
+#systemMaintenance{
+
+ .el-tabs__header {
+ border: 0px solid #dcdfe6;
+ .el-tabs__item {
+ padding: 5px 50px;
+ height: 50px;
+ font-family: PingFangSC-Regular;
+ font-size: 14px;
+ color: #222222;
+ text-align: center;
+ border: 0px solid transparent;
+ }
+ .el-tabs__item:nth-child(2) {
+ padding-left: 50px;
+ }
+ .el-tabs__item:last-child {
+ padding-right: 50px;
+ }
+ .el-tabs__item.is-active {
+ color: #ff7733;
+ font-weight: bold;
+ // border-right-color: #fff;
+ // border-left-color: #fff;
+ }
+ .el-tabs__item:not(.is-disabled):hover {
+ color: #ff7733;
+ }
+
+ }
+ .el-tabs__active-bar {
+ background-color: #ff7733;
+ }
+ .el-tabs__content {
+ padding-left: 15px !important;
+ }
+}
+</style>
diff --git a/src/pages/settings/index/App.vue b/src/pages/settings/index/App.vue
new file mode 100644
index 0000000..84c1bb0
--- /dev/null
+++ b/src/pages/settings/index/App.vue
@@ -0,0 +1,166 @@
+<template>
+ <div class="s-system-manage">
+ <basic-setting v-show="activeName === 'basic'"></basic-setting>
+ </div>
+</template>
+
+<script>
+import AuthorityManagement from "../components/AuthorityManagement";
+import BasicSetting from "../components/BasicSetting";
+import ClusterManagement from "../components/ClusterManagement";
+import LogManagement from "../components/LogManagement";
+import RadioSet from "../components/RadioSet";
+import SystemMaintenance from "../components/SystemMaintenance";
+//import EventPush from "../components/systemManage/EventPush/index";
+
+export default {
+ name: 'settings',
+ components: {
+ AuthorityManagement,
+ BasicSetting,
+ LogManagement,
+ RadioSet,
+ SystemMaintenance
+ },
+ data() {
+ return {
+ activeName: "basic",
+ buttonAuthority: sessionStorage.getItem("buttonAuthoritys") || [],
+ loginName: JSON.parse(sessionStorage.getItem("userInfo")).username || "鐢ㄦ埛鍚�"
+ }
+ },
+ computed: {
+ isAdmin() {
+ if (
+ sessionStorage.getItem("userInfo") &&
+ sessionStorage.getItem("userInfo") !== ""
+ ) {
+ let loginName = JSON.parse(sessionStorage.getItem("userInfo")).username;
+ return loginName === "superadmin" || loginName === "basic";
+ }
+ return false;
+ }
+ },
+ methods: {
+ isShow(authority) {
+ if (this.isAdmin) {
+ return true;
+ } else if (this.buttonAuthority.indexOf("," + authority + ",") > -1) {
+ return true;
+ } else {
+ return false;
+ }
+ },
+ },
+ created() {
+ if(this.isShow('videoSystem:base')){
+ this.activeName = "basic"
+ }else if(this.isShow('videoSystem:permission')){
+ this.activeName = "user"
+ }else if(this.isShow('videoSystem:broadcast')){
+ this.activeName = "radio"
+ }else if(this.isShow('videoSystem:eventPush')){
+ this.activeName = "event"
+ }else if(this.isShow('videoSystem:logManage')){
+ this.activeName = "log"
+ }else if(this.isShow('videoSystem:sysManage')){
+ this.activeName = "system"
+ }
+ },
+};
+</script>
+<style lang="scss">
+.s-system-manage {
+ width: 100% !important;
+ box-sizing: border-box;
+ padding: 10px;
+ background-color: #e9ebf2;
+ .s-system-manage-breadcrumb {
+ height: 5%;
+ box-sizing: border-box;
+ border: 1px solid #e4e7ed;
+ box-shadow: #e4e7ed 0px 0px 9px inset;
+ box-shadow: #e4e7ed 0px 0px 9px inset;
+ border-radius: 5px;
+ }
+
+ .el-tabs--border-card {
+ border: 0px solid #dcdfe6;
+ -webkit-box-shadow: none;
+ box-shadow: none;
+ .el-tabs__header {
+ border: 0px solid #dcdfe6;
+ .el-tabs__item {
+ padding: 5px 50px;
+ height: 50px;
+ font-family: PingFangSC-Regular;
+ font-size: 15px;
+ color: #222222;
+ text-align: center;
+ border: 0px solid transparent;
+ }
+ .el-tabs__item:nth-child(2) {
+ padding-left: 50px !important;
+ }
+ .el-tabs__item:last-child {
+ padding-right: 50px !important;
+ }
+ .el-tabs__item.is-active {
+ color: #3d68e1;
+ font-weight: bold;
+ // border-right-color: #fff;
+ // border-left-color: #fff;
+ }
+ .el-tabs__item:not(.is-disabled):hover {
+ color: #3d68e1;
+ }
+ }
+ }
+ .el-tabs__content {
+ height: calc(100% - 64px);
+ width: calc(100% - 20px);
+ box-sizing: border-box;
+ overflow-y: auto;
+ padding: 10px 40px !important;
+ .el-tab-pane {
+ width: 100%;
+ .s-title {
+ text-align: left;
+ padding: 15px 0px;
+ font-size: 16px;
+ }
+ }
+ }
+
+ .s-table {
+ border: 1px solid #e8e8e9;
+ margin-top: 40px;
+ }
+
+ .ui-top-title {
+ padding-bottom: 10px;
+ /* border-bottom: 1px solid #ebebeb; */
+ position: relative;
+ text-align: left;
+ padding-left: 15px;
+ font-size: 16px;
+ font-weight: bold;
+ }
+
+ .ui-top-title:before {
+ content: " ";
+ border-left: 4px solid #f53d3d;
+ display: inline-block;
+ height: 16px;
+ position: absolute;
+ top: 50%;
+ left: 0;
+ margin-top: -13px;
+ }
+
+ .el-button--text {
+ color: #3d68e1;
+ text-decoration: underline;
+ }
+}
+</style>
diff --git a/src/pages/settings/index/main.ts b/src/pages/settings/index/main.ts
new file mode 100644
index 0000000..80f18a4
--- /dev/null
+++ b/src/pages/settings/index/main.ts
@@ -0,0 +1,11 @@
+import Vue from 'vue'
+import ElementUI from 'element-ui'
+import 'element-ui/lib/theme-chalk/index.css'
+import App from './App.vue'
+
+Vue.use(ElementUI)
+
+new Vue({
+ el: '#app',
+ render: h => h(App)
+})
--
Gitblit v1.8.0