wangyi пре 3 година
родитељ
комит
b49155dba0
63 измењених фајлова са 4685 додато и 24970 уклоњено
  1. 10 1
      config/index.js
  2. 234 24806
      package-lock.json
  3. 3 0
      package.json
  4. 1 0
      src/assets/img/cnnmnist.svg
  5. 0 0
      src/assets/img/visisvg/BinomialLogisticRegression.svg
  6. 0 0
      src/assets/img/visisvg/CNNtextclassfication.svg
  7. 1 0
      src/assets/img/visisvg/DecisionTreeClassification.svg
  8. 1 0
      src/assets/img/visisvg/KNN.svg
  9. 1 0
      src/assets/img/visisvg/OCR.svg
  10. 1 0
      src/assets/img/visisvg/RNNtextclassfication.svg
  11. 0 0
      src/assets/img/visisvg/SVM.svg
  12. 0 0
      src/assets/img/visisvg/YOLO.svg
  13. 1 0
      src/assets/img/visisvg/cnnmnist.svg
  14. 0 0
      src/assets/img/visisvg/cnntextclassification1.svg
  15. 1 0
      src/assets/img/visisvg/contourCircle2.svg
  16. 0 0
      src/assets/img/visisvg/contourCircle22.svg
  17. 0 0
      src/assets/img/visisvg/contourRect1.svg
  18. 0 0
      src/assets/img/visisvg/contourRect11.svg
  19. 0 0
      src/assets/img/visisvg/feature.svg
  20. 0 0
      src/assets/img/visisvg/intelligent-algorithm.svg
  21. 1 0
      src/assets/img/visisvg/jiebafenci.svg
  22. 1 0
      src/assets/img/visisvg/minmaxscaler.svg
  23. 1 0
      src/assets/img/visisvg/missvalueprocess.svg
  24. 0 0
      src/assets/img/visisvg/resnet50.svg
  25. 1 0
      src/assets/img/visisvg/sentencessimilarity.svg
  26. 1 0
      src/assets/img/visisvg/sentiment.svg
  27. 1 0
      src/assets/img/visisvg/snownlpfenci.svg
  28. 0 0
      src/assets/img/visisvg/sparkBinomialLogisticRegression.svg
  29. 0 0
      src/assets/img/visisvg/sparkDecision-tree-regression.svg
  30. 1 0
      src/assets/img/visisvg/sparkDecisionTreeClassification.svg
  31. 0 0
      src/assets/img/visisvg/sparkFactorizationMachinesRegression.svg
  32. 1 0
      src/assets/img/visisvg/sparkGaussianMixtureModel.svg
  33. 0 0
      src/assets/img/visisvg/sparkGradientBoostedTreeClassification.svg
  34. 1 0
      src/assets/img/visisvg/sparkIsotonicRegression.svg
  35. 0 0
      src/assets/img/visisvg/sparkLatentDirichletAllocation.svg
  36. 1 0
      src/assets/img/visisvg/sparkLinearRegression.svg
  37. 1 0
      src/assets/img/visisvg/sparkMultinomialLogisticRegression.svg
  38. 1 0
      src/assets/img/visisvg/sparkNaiveBayes.svg
  39. 0 0
      src/assets/img/visisvg/sparkRandomForestClassification.svg
  40. 0 0
      src/assets/img/visisvg/sparkmlKmeans.svg
  41. 0 0
      src/assets/img/visisvg/standardscaler.svg
  42. 0 0
      src/assets/img/visisvg/vgg16.svg
  43. 1 0
      src/assets/img/visisvg/wasiyuce.svg
  44. 5 1
      src/router/index.js
  45. 6 1
      src/utils/httpRequest.js
  46. 631 0
      src/views/modules/snoop/home.vue
  47. 270 0
      src/views/modules/snoop/job.vue
  48. 191 0
      src/views/modules/snoop/jobLog.vue
  49. 207 0
      src/views/modules/snoop/jobResult.vue
  50. 194 0
      src/views/modules/snoop/jobResult_visi.vue
  51. 298 0
      src/views/modules/snoop/jobResult_visi_echars.vue
  52. 106 0
      src/views/modules/snoop/jobWatch.vue
  53. 965 0
      src/views/modules/snoop/measure.vue
  54. 97 0
      src/views/modules/snoop/measureUserWatch.vue
  55. 593 0
      src/views/modules/snoop/showRules.vue
  56. 47 0
      src/views/modules/snoop/snoop-add.vue
  57. 94 0
      src/views/modules/visi/design-create.vue
  58. 7 3
      src/views/modules/visi/design-experconfig.vue
  59. 353 141
      src/views/modules/visi/design-graph1.vue
  60. 2 2
      src/views/modules/visi/design-node-config.vue
  61. 1 1
      src/views/modules/visi/design-workflowlog.vue
  62. 349 13
      src/views/modules/visi/design.vue
  63. 2 1
      src/views/new-menue.vue

+ 10 - 1
config/index.js

@@ -12,7 +12,16 @@ module.exports = {
     assetsSubDirectory: 'static',
     assetsPublicPath: '/',
     // 代理列表, 是否开启代理通过[./dev.env.js]配置
-    proxyTable: devEnv.OPEN_PROXY === false ? {} : {
+    proxyTable: devEnv.OPEN_PROXY === false ? {
+      '/snoopapi':{
+        // target:'http://192.168.10.166:38080',
+        target:'http://192.168.10.112:8090',
+        changeOrigin: true,
+        pathRewrite: {
+          '^/snoopapi': '/api'
+        }
+      }
+    } : {
       '/proxyApi': {
         target: 'http://demo.renren.io/renren-fast/',
         changeOrigin: true,

Разлика између датотеке није приказан због своје велике величине
+ 234 - 24806
package-lock.json


+ 3 - 0
package.json

@@ -14,12 +14,14 @@
     "build": "gulp"
   },
   "dependencies": {
+    "@antv/g2": "^4.1.47",
     "@antv/x6": "^1.25.1",
     "ajv": "^8.4.0",
     "ant-design-vue": "^1.7.6",
     "axios": "0.17.1",
     "babel-plugin-component": "0.10.1",
     "babel-polyfill": "6.26.0",
+    "echarts-wordcloud": "^1.1.3",
     "element-ui": "2.9.0",
     "gulp": "4.0.2",
     "gulp-concat": "2.6.1",
@@ -33,6 +35,7 @@
     "npm": "^6.9.0",
     "papaparse": "^5.3.1",
     "svg-sprite-loader": "3.7.3",
+    "v-echarts": "^1.0.2",
     "vue": "2.5.16",
     "vue-codemirror": "^4.0.6",
     "vue-cookie": "1.1.4",

+ 1 - 0
src/assets/img/cnnmnist.svg

@@ -0,0 +1 @@
+<?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 t="1640351717755" class="icon" viewBox="0 0 1058 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="23347" xmlns:xlink="http://www.w3.org/1999/xlink" width="206.640625" height="200"><defs><style type="text/css"></style></defs><path d="M992.88417 0.262722a49.814807 49.814807 0 0 0-54.591569 55.273964v818.873542c0 17.74226-23.883812 32.754942-60.050727 32.754942a48.450018 48.450018 0 0 1-50.497202-46.402834V59.631054a60.050726 60.050726 0 0 0-43.673255-55.956359V0.262722H68.239462a68.239462 68.239462 0 0 0-68.239462 68.239462v768.37634A188.340915 188.340915 0 0 0 190.388099 1023.85465h687.853775a172.645839 172.645839 0 0 0 179.469785-164.457103V59.631054a62.09791 62.09791 0 0 0-64.827489-59.368332zM648.274888 682.657341h-477.676233a34.119731 34.119731 0 0 1 0-68.239462h477.676233a34.119731 34.119731 0 0 1 0 68.239462z m0-204.718386h-477.676233a34.119731 34.119731 0 0 1 0-68.239462h477.676233a34.119731 34.119731 0 0 1 0 68.239462z m0-204.718386h-272.957848a34.119731 34.119731 0 0 1 0-68.239461h272.957848a34.119731 34.119731 0 0 1 0 68.239461z" p-id="23348"></path></svg>

Разлика између датотеке није приказан због своје велике величине
+ 0 - 0
src/assets/img/visisvg/BinomialLogisticRegression.svg


Разлика између датотеке није приказан због своје велике величине
+ 0 - 0
src/assets/img/visisvg/CNNtextclassfication.svg


+ 1 - 0
src/assets/img/visisvg/DecisionTreeClassification.svg

@@ -0,0 +1 @@
+<?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 t="1640349370492" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7202" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M4.143262 2.378831h1008.246153v1008.246154h-1008.246153z" fill="#000000" p-id="7203"></path><path d="M504.123077 47.261538a94.523077 94.523077 0 0 1 84.283077 137.373539L837.159385 389.498092a94.523077 94.523077 0 1 1 29.365169 176.348554l-77.697969 235.189169a94.523077 94.523077 0 1 1-140.6976 101.691077H375.855262a94.523077 94.523077 0 1 1-140.6976-101.691077L157.443938 565.846646a94.523077 94.523077 0 1 1 27.884308-177.152l235.425477-202.295138A94.523077 94.523077 0 0 1 504.123077 47.261538z m58.226215 168.991508A94.113477 94.113477 0 0 1 504.123077 236.307692a94.097723 94.097723 0 0 1-56.635077-18.8416L217.056492 415.428923A94.113477 94.113477 0 0 1 236.307692 472.615385a94.4128 94.4128 0 0 1-40.802461 77.792492l78.548677 237.757046a94.554585 94.554585 0 0 1 101.817107 73.570462H648.113231a94.554585 94.554585 0 0 1 101.817107-73.570462l78.564431-237.757046A94.4128 94.4128 0 0 1 787.692308 472.615385c0-20.873846 6.774154-40.172308 18.2272-55.800123z" fill="#1890FF" p-id="7204"></path></svg>

+ 1 - 0
src/assets/img/visisvg/KNN.svg

@@ -0,0 +1 @@
+<?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 t="1640335722997" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2686" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M4.143262 2.378831h1008.246153v1008.246154h-1008.246153z" fill="#000000" opacity=".01" p-id="2687"></path><path d="M378.092308 803.446154a78.769231 78.769231 0 1 1 0 157.538461 78.769231 78.769231 0 0 1 0-157.538461z m252.061538-15.753846a78.769231 78.769231 0 1 1 0 157.538461 78.769231 78.769231 0 0 1 0-157.538461z m204.8-157.538462a78.769231 78.769231 0 1 1 0 157.538462 78.769231 78.769231 0 0 1 0-157.538462z m-661.661538 0a78.769231 78.769231 0 1 1 0 157.538462 78.769231 78.769231 0 0 1 0-157.538462z m235.173415-281.174646v187.029662l193.583262-187.029662h53.941169l-162.831754 154.261662L678.675692 708.923077h-55.453538L464.423385 529.959385 408.465723 582.892308v126.030769h-41.338092V348.9792h41.338092zM882.215385 378.092308a78.769231 78.769231 0 1 1 0 157.538461 78.769231 78.769231 0 0 1 0-157.538461zM126.030769 378.092308a78.769231 78.769231 0 1 1 0 157.538461 78.769231 78.769231 0 0 1 0-157.538461z m630.153846-220.553846a78.769231 78.769231 0 1 1 0 157.538461 78.769231 78.769231 0 0 1 0-157.538461z m-504.123077 0a78.769231 78.769231 0 1 1 0 157.538461 78.769231 78.769231 0 0 1 0-157.538461z m252.061539-78.769231a78.769231 78.769231 0 1 1 0 157.538461 78.769231 78.769231 0 0 1 0-157.538461z" fill="#A8ADBB" p-id="2688"></path></svg>

+ 1 - 0
src/assets/img/visisvg/OCR.svg

@@ -0,0 +1 @@
+<?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 t="1640335892407" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4926" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M796.1 929.4c-3.3 0-6.7-0.1-10.2-0.3-38.6-1.9-83-13.9-132-35.7-96-42.6-202.2-119.5-299.1-216.4-96.9-97-173.8-203.2-216.5-299.1-21.8-49-33.8-93.4-35.7-132-2.8-57.8 18.2-91.6 36.3-109.7 18.1-18.1 51.8-39.1 109.7-36.3 38.6 1.9 83 13.9 132 35.7 95.9 42.7 202.1 119.6 299.1 216.5 96.9 96.9 173.8 203.1 216.5 299.1 21.8 49 33.8 93.4 35.7 132 2.8 57.8-18.2 91.6-36.3 109.7-17.1 16.9-47.9 36.5-99.5 36.5z m-558-751c-19.4 0-34.3 4.5-43.4 13.5-22.6 22.6-16.6 81.6 15.6 154 38.9 87.3 110 185.1 200.2 275.4 90.3 90.3 188.1 161.4 275.4 200.2 43.3 19.3 81.8 29.1 110.6 29.1 19.4 0 34.3-4.5 43.4-13.5 22.6-22.6 16.6-81.6-15.6-154-38.9-87.3-110-185.1-200.3-275.4-90.3-90.3-188.1-161.4-275.4-200.2-43.3-19.3-81.8-29.1-110.5-29.1z" p-id="4927"></path><path d="M238.4 929.4c-51.6 0-82.4-19.6-99.4-36.6-18.1-18.1-39.1-51.9-36.3-109.7 1.9-38.6 13.9-83 35.7-132C181 555.2 257.9 449 354.8 352c96.9-96.9 203.1-173.8 299.1-216.5 49-21.8 93.4-33.8 132-35.7 57.8-2.8 91.6 18.2 109.7 36.3 18.1 18.1 39.1 51.9 36.3 109.7-1.9 38.6-13.9 83-35.7 132-42.7 96-119.6 202.2-216.5 299.2S476.6 850.8 380.6 893.5c-49 21.8-93.4 33.8-132 35.7-3.5 0.1-6.9 0.2-10.2 0.2z m558-751c-28.8 0-67.3 9.9-110.6 29.1-87.3 38.9-185.1 110-275.4 200.2-90.2 90.3-161.3 188.1-200.1 275.4-32.2 72.4-38.2 131.4-15.6 154 22.6 22.6 81.6 16.6 154-15.6 87.3-38.8 185.1-110 275.4-200.2 90.3-90.3 161.4-188.1 200.2-275.4 32.2-72.4 38.2-131.4 15.6-154-9.1-9.1-24.1-13.5-43.5-13.5z" p-id="4928"></path></svg>

+ 1 - 0
src/assets/img/visisvg/RNNtextclassfication.svg

@@ -0,0 +1 @@
+<?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 t="1640350635725" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="18433" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M928 960h-832c-19.2 0-32-12.8-32-32v-832c0-19.2 12.8-32 32-32h832c19.2 0 32 12.8 32 32v832c0 19.2-12.8 32-32 32zM896 128H128v768h768V128zM240 332.8L499.2 528c0 3.2 3.2 6.4 0 9.6l-259.2 195.2c-3.2 3.2-6.4 3.2-9.6 0V339.2c0-3.2 3.2-6.4 6.4-6.4h3.2z m54.4 281.6l105.6-80L294.4 454.4v160z m291.2-393.6L672 307.2l86.4-86.4c3.2-3.2 6.4-3.2 9.6 0l35.2 35.2c3.2 3.2 3.2 6.4 0 9.6L716.8 352l86.4 86.4c3.2 3.2 3.2 6.4 0 9.6l-35.2 35.2c-3.2 3.2-6.4 3.2-9.6 0L672 396.8 585.6 483.2c-3.2 3.2-6.4 3.2-9.6 0L540.8 448c-3.2-3.2-3.2-6.4 0-9.6L627.2 352 540.8 265.6c-3.2-3.2-3.2-6.4 0-9.6L576 220.8c3.2-3.2 6.4-3.2 9.6 0z m102.4 323.2C768 544 832 608 832 688S768 832 688 832 544 768 544 688s64-144 144-144z m0 224c44.8 0 80-35.2 80-80s-35.2-80-80-80-80 35.2-80 80 35.2 80 80 80z" p-id="18434"></path></svg>

Разлика између датотеке није приказан због своје велике величине
+ 0 - 0
src/assets/img/visisvg/SVM.svg


Разлика између датотеке није приказан због своје велике величине
+ 0 - 0
src/assets/img/visisvg/YOLO.svg


+ 1 - 0
src/assets/img/visisvg/cnnmnist.svg

@@ -0,0 +1 @@
+<?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 t="1640351717755" class="icon" viewBox="0 0 1058 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="23347" xmlns:xlink="http://www.w3.org/1999/xlink" width="206.640625" height="200"><defs><style type="text/css"></style></defs><path d="M992.88417 0.262722a49.814807 49.814807 0 0 0-54.591569 55.273964v818.873542c0 17.74226-23.883812 32.754942-60.050727 32.754942a48.450018 48.450018 0 0 1-50.497202-46.402834V59.631054a60.050726 60.050726 0 0 0-43.673255-55.956359V0.262722H68.239462a68.239462 68.239462 0 0 0-68.239462 68.239462v768.37634A188.340915 188.340915 0 0 0 190.388099 1023.85465h687.853775a172.645839 172.645839 0 0 0 179.469785-164.457103V59.631054a62.09791 62.09791 0 0 0-64.827489-59.368332zM648.274888 682.657341h-477.676233a34.119731 34.119731 0 0 1 0-68.239462h477.676233a34.119731 34.119731 0 0 1 0 68.239462z m0-204.718386h-477.676233a34.119731 34.119731 0 0 1 0-68.239462h477.676233a34.119731 34.119731 0 0 1 0 68.239462z m0-204.718386h-272.957848a34.119731 34.119731 0 0 1 0-68.239461h272.957848a34.119731 34.119731 0 0 1 0 68.239461z" p-id="23348"></path></svg>

Разлика између датотеке није приказан због своје велике величине
+ 0 - 0
src/assets/img/visisvg/cnntextclassification1.svg


+ 1 - 0
src/assets/img/visisvg/contourCircle2.svg

@@ -0,0 +1 @@
+<?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 t="1640335952427" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5731" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M512 294.4m-89.6 0a89.6 89.6 0 1 0 179.2 0 89.6 89.6 0 1 0-179.2 0Z" p-id="5732"></path><path d="M755.2 704m-89.6 0a89.6 89.6 0 1 0 179.2 0 89.6 89.6 0 1 0-179.2 0Z" p-id="5733"></path><path d="M268.8 704m-89.6 0a89.6 89.6 0 1 0 179.2 0 89.6 89.6 0 1 0-179.2 0Z" p-id="5734"></path><path d="M896 0H128C57.6 0 0 57.6 0 128v768c0 70.4 57.6 128 128 128h768c70.4 0 128-57.6 128-128V128c0-70.4-57.6-128-128-128zM512 806.4c-44.8 0-83.2-12.8-121.6-32-25.6 44.8-70.4 70.4-121.6 70.4C192 844.8 128 780.8 128 704c0-76.8 64-140.8 140.8-140.8s140.8 64 140.8 140.8v19.2c44.8 25.6 102.4 32 153.6 25.6l12.8 51.2c-25.6 0-44.8 6.4-64 6.4z m0-371.2c-51.2 0-96-32-121.6-70.4-44.8 32-76.8 83.2-89.6 134.4l-51.2-6.4c12.8-70.4 57.6-140.8 121.6-179.2v-19.2c0-76.8 64-140.8 140.8-140.8 76.8 0 140.8 64 140.8 140.8S588.8 435.2 512 435.2z m243.2 409.6c-76.8 0-140.8-64-140.8-140.8 0-70.4 44.8-121.6 108.8-140.8v-25.6c0-51.2-19.2-102.4-57.6-140.8l38.4-32c44.8 51.2 70.4 108.8 70.4 179.2v25.6c70.4 6.4 121.6 64 121.6 134.4 0 76.8-64 140.8-140.8 140.8z" p-id="5735"></path></svg>

Разлика између датотеке није приказан због своје велике величине
+ 0 - 0
src/assets/img/visisvg/contourCircle22.svg


Разлика између датотеке није приказан због своје велике величине
+ 0 - 0
src/assets/img/visisvg/contourRect1.svg


Разлика између датотеке није приказан због своје велике величине
+ 0 - 0
src/assets/img/visisvg/contourRect11.svg


Разлика између датотеке није приказан због своје велике величине
+ 0 - 0
src/assets/img/visisvg/feature.svg


Разлика између датотеке није приказан због своје велике величине
+ 0 - 0
src/assets/img/visisvg/intelligent-algorithm.svg


+ 1 - 0
src/assets/img/visisvg/jiebafenci.svg

@@ -0,0 +1 @@
+<?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 t="1640350701444" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="19244" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M554.496 192v640h277.504v-640h-277.504zM106.496 106.496h810.496v810.496H106.496V106.496z m128 213.504h192V234.496H234.496v85.504z m0 149.504h192V384H234.496v85.504z m0 148.992h192v-85.504H234.496v85.504z m0 149.504h192v-85.504H234.496V768z" fill="#FF6A00" p-id="19245"></path></svg>

+ 1 - 0
src/assets/img/visisvg/minmaxscaler.svg

@@ -0,0 +1 @@
+<?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 t="1640351895483" class="icon" viewBox="0 0 1280 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="26471" xmlns:xlink="http://www.w3.org/1999/xlink" width="250" height="200"><defs><style type="text/css"></style></defs><path d="M223.996375 896.003397h351.990657V306.499045a159.815758 159.815758 0 0 1-86.757698-94.93748l-263.992992-88.517651a31.999151 31.999151 0 0 1-20.159465-40.518924l20.31946-60.67839A31.999151 31.999151 0 0 1 265.99526 1.687135l235.773742 79.077901C529.388269 32.746311 580.606909 0.027179 639.985333 0.027179a159.995753 159.995753 0 0 1 159.995753 159.995754 158.115803 158.115803 0 0 1-1.999947 19.999469l256.793184 86.097714a31.999151 31.999151 0 0 1 20.159465 40.518925l-20.359459 60.738388a31.999151 31.999151 0 0 1-40.598923 20.159465l-283.992462-95.257472a160.955728 160.955728 0 0 1-25.99931 14.239622V992.000849a31.999151 31.999151 0 0 1-31.99915 31.999151H223.996375a31.999151 31.999151 0 0 1-31.999151-31.999151v-63.998301a31.999151 31.999151 0 0 1 31.999151-31.999151z" p-id="26472"></path><path d="M0.00232 608.011042c0 88.357655 114.616958 159.995753 255.993205 159.995753s255.993205-71.638099 255.993205-159.995753c0-31.339168 4.15989-14.499615-169.995487-363.010365-35.359061-70.718123-136.436379-70.578127-171.735442 0C-2.63761 590.551505 0.00232 575.6519 0.00232 608.011042z m111.997027-31.999151l143.996178-287.992356 143.996178 287.992356z m655.982589 287.992356c0 88.357655 114.616958 159.995753 255.993205 159.995753s255.993205-71.638099 255.993205-159.995753c0-31.339168 4.15989-14.499615-170.095485-363.010365-35.359061-70.718123-136.436379-70.578127-171.735442 0C765.342006 846.54471 767.981936 831.645106 767.981936 864.004247z m111.997027-31.999151l143.996178-287.992356 143.996178 287.992356z" p-id="26473"></path></svg>

+ 1 - 0
src/assets/img/visisvg/missvalueprocess.svg

@@ -0,0 +1 @@
+<?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 t="1640351837026" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="25676" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M406.5 56c160.9 0 269.2 26.9 312.6 47.9-43.4 21-151.7 47.9-312.6 47.9s-269.2-26.9-312.6-47.9C137.3 82.9 245.6 56 406.5 56m0-56C194.3 0 22.2 46.5 22.2 103.9s172 103.9 384.3 103.9c212.2 0 384.3-46.5 384.3-103.9S618.7 0 406.5 0zM432.3 1024C149 1024 20 955.6 20 892.1h56c0 22 124.8 75.9 356.3 75.9 21.3 0 42.2-0.5 62.5-1.4l2.5 55.9c-21.2 1-42.9 1.5-65 1.5zM348.8 755.5c-7.3-0.3-14.6-0.5-21.8-0.9-129.9-6.6-240.3-30.8-295.2-64.9l29.5-47.5c46.5 28.9 149.4 50.5 268.5 56.5l21 0.9-2 55.9zM408 466.7c-128.2 0-263.9-20.1-373.4-72.2l24-50.6c222 105.5 554 65.9 677.5 14.2l21.6 51.6c-78.4 32.9-209.6 57-349.7 57z" fill="#231815" p-id="25677"></path><path d="M20.3 104.8h56v371.5h-56zM20.3 577.1h56v327.2h-56zM731.9 90.6h56v371.7h-56z" fill="#231815" p-id="25678"></path><path d="M633.5 1016.4L485.2 642.8l373.6-148.4L1007.1 868l-373.6 148.4z m-90.2-348.5l115.3 290.3L949 842.9 833.6 552.6 543.3 667.9z" fill="#040000" p-id="25679"></path><path d="M487.709 638.792l482.08-191.4 16.53 41.637-482.079 191.4z" fill="#040000" p-id="25680"></path><path d="M575.9 643.9l380.7 157.5 21.5 54.1-332 131.9-131.9-332z" fill="#040000" p-id="25681"></path></svg>

Разлика између датотеке није приказан због своје велике величине
+ 0 - 0
src/assets/img/visisvg/resnet50.svg


+ 1 - 0
src/assets/img/visisvg/sentencessimilarity.svg

@@ -0,0 +1 @@
+<?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 t="1640351573254" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="21251" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M506.6 911.9c-1.1 0-2.2 0-3.3-0.2C404 901.9 79 860.6 66.9 737.4c-5.6-56.5 36.3-135.7 406.2-250.4V145.3c0-9.5 4-18.5 11-24.8 7-6.4 16.3-9.5 25.8-8.5 99.3 9.7 424.3 51.1 436.5 174.3 5.6 56.5-36.3 135.7-406.2 250.4v341.7c0 9.5-4 18.5-11 24.8-6.3 5.6-14.3 8.7-22.6 8.7z m-33.5-354.6C137.4 663.5 133 724 133.6 730.8 137.4 769.7 292 819 473 840.9V557.3z m67-374.6v283.6c335.7-106.2 340.1-166.7 339.5-173.5-3.8-38.9-158.4-88.2-339.5-110.1z" p-id="21252"></path><path d="M506.6 911.9c-4.1 0-8.4-0.8-12.5-2.4-20-8-195.2-81.8-200.6-206.1-3.4-78.8 63.2-153.4 198-221.5 107.6-54.4 163.4-109.3 161.2-158.7-3-69.1-118.4-130.6-158.6-146.7-17.2-6.9-25.5-26.4-18.7-43.6 6.9-17.2 26.4-25.5 43.6-18.7 20 8 195.2 81.8 200.6 206.1 3.4 78.8-63.2 153.4-198 221.5C414.1 596.1 358.4 651 360.5 700.5c3 69.1 118.4 130.6 158.6 146.7 17.2 6.9 25.5 26.4 18.7 43.6-5.3 13.1-17.9 21.1-31.2 21.1z" p-id="21253"></path><path d="M834.6 540.6c-1 48.2-1 97.5-1 147.2v23.6c0 48.3 0 97 1 145.7l51.6 4.3v16.9H714v-16.9l51.6-4.3c0.5-47.8 0.5-96.5 0.5-145.7v-23.6c0-48.7 0-98.4-0.5-147.2h-74.8l-20.3 79.6h-27l3.4-99.9h306.4l2.9 99.9h-27l-19.8-79.6h-74.8z" p-id="21254"></path></svg>

+ 1 - 0
src/assets/img/visisvg/sentiment.svg

@@ -0,0 +1 @@
+<?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 t="1640350831406" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="20413" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M844.8 140.8c-89.6-38.4-185.6-32-281.6 19.2-19.2 12.8-38.4 19.2-64 0-19.2-6.4-38.4-19.2-64-25.6-108.8-32-204.8-19.2-281.6 51.2C76.8 249.6 44.8 339.2 64 454.4c0 12.8 12.8 25.6 19.2 32 32 6.4 44.8-6.4 51.2-19.2 0-6.4 6.4-12.8 0-38.4-12.8-64 6.4-121.6 44.8-166.4 38.4-44.8 96-70.4 153.6-76.8 64 0 121.6 19.2 172.8 64 19.2 19.2 38.4 19.2 57.6 0 12.8-12.8 32-25.6 51.2-38.4 70.4-38.4 140.8-38.4 204.8-6.4 57.6 32 102.4 83.2 115.2 153.6 12.8 89.6-25.6 166.4-51.2 217.6-83.2 140.8-204.8 236.8-326.4 326.4-19.2 12.8-38.4 6.4-44.8 0-83.2-57.6-179.2-134.4-256-230.4-32-38.4-51.2-38.4-64-38.4-6.4 0-19.2 6.4-19.2 12.8 0 0-6.4 12.8 0 19.2 83.2 108.8 192 211.2 345.6 313.6 6.4 6.4 12.8 6.4 25.6 6.4 6.4 0 19.2 0 25.6-6.4 121.6-83.2 211.2-160 288-243.2 83.2-89.6 128-172.8 147.2-268.8 25.6-140.8-38.4-268.8-160-326.4z" fill="#019bf0" p-id="20414"></path><path d="M396.8 544c0-6.4 6.4-12.8 6.4-19.2l25.6-57.6 19.2 57.6c0 6.4 6.4 12.8 6.4 19.2l6.4 25.6c12.8 51.2 25.6 96 38.4 147.2 6.4 25.6 12.8 38.4 25.6 38.4 19.2 0 25.6-6.4 32-32l19.2-32c12.8-19.2 19.2-38.4 25.6-57.6 12.8-32 32-32 51.2-32h96c12.8 0 32 0 32-19.2 0-6.4 6.4-32-25.6-32H633.6c-38.4 0-51.2 6.4-64 38.4-6.4 25.6-25.6 76.8-32 70.4-6.4-6.4-12.8-44.8-12.8-44.8L512 556.8c-12.8-57.6-32-115.2-44.8-172.8-6.4-32-12.8-32-25.6-38.4-12.8 0-19.2 6.4-32 25.6l-12.8 38.4-38.4 96c-12.8 32-25.6 44.8-64 44.8h-256c-12.8 0-19.2 6.4-25.6 6.4-6.4 6.4-12.8 12.8-6.4 19.2 0 12.8 6.4 25.6 32 25.6H320c57.6 0 57.6 0 76.8-57.6z" fill="#019bf0" p-id="20415"></path></svg>

+ 1 - 0
src/assets/img/visisvg/snownlpfenci.svg

@@ -0,0 +1 @@
+<?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 t="1640350706531" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="19380" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M554.496 192v640h277.504v-640h-277.504zM106.496 106.496h810.496v810.496H106.496V106.496z m128 213.504h192V234.496H234.496v85.504z m0 149.504h192V384H234.496v85.504z m0 148.992h192v-85.504H234.496v85.504z m0 149.504h192v-85.504H234.496V768z" fill="#6415FF" p-id="19381"></path></svg>

Разлика између датотеке није приказан због своје велике величине
+ 0 - 0
src/assets/img/visisvg/sparkBinomialLogisticRegression.svg


Разлика између датотеке није приказан због своје велике величине
+ 0 - 0
src/assets/img/visisvg/sparkDecision-tree-regression.svg


+ 1 - 0
src/assets/img/visisvg/sparkDecisionTreeClassification.svg

@@ -0,0 +1 @@
+<?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 t="1640335959080" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6557" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M928 80v864H96V80h832z m-32 32H128v800h768V112zM608 736v32H416v-32h192z m56.032-400L410.24 608H368l253.76-272h42.272z" fill="#333333" p-id="6558"></path><path d="M624 480a48 48 0 0 1 48 48v32a48 48 0 0 1-96 0v-32a48 48 0 0 1 48-48z m0 32a16 16 0 0 0-15.888 14.128L608 528v32a16 16 0 0 0 31.888 1.872L640 560v-32a16 16 0 0 0-16-16zM416 336a48 48 0 0 1 48 48v32a48 48 0 0 1-96 0v-32a48 48 0 0 1 48-48z m0 32a16 16 0 0 0-15.888 14.128L400 384v32a16 16 0 0 0 31.888 1.872L432 416v-32a16 16 0 0 0-16-16z" fill="#0A74F2" p-id="6559"></path></svg>

Разлика између датотеке није приказан због своје велике величине
+ 0 - 0
src/assets/img/visisvg/sparkFactorizationMachinesRegression.svg


+ 1 - 0
src/assets/img/visisvg/sparkGaussianMixtureModel.svg

@@ -0,0 +1 @@
+<?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 t="1640335693119" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2150" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M4.143262 2.378831h1008.246153v1008.246154h-1008.246153z" fill="#000000" opacity=".01" p-id="2151"></path><path d="M535.630769 78.769231a94.523077 94.523077 0 0 1 88.946216 126.582154l226.9184 209.368615a94.523077 94.523077 0 1 1-24.418462 166.203077L631.934031 769.701415A94.523077 94.523077 0 1 1 459.067077 839.68H249.856A94.523077 94.523077 0 1 1 137.058462 726.898215l-0.015754-128.393846a94.523077 94.523077 0 1 1 46.395077-179.263015l264.412553-210.786462A94.523077 94.523077 0 0 1 535.630769 78.769231z m253.054031 439.154215l-175.560862 1.811692a94.554585 94.554585 0 0 1-186.147446 1.906216l-192.685292 2.000738a94.696369 94.696369 0 0 1-56.256985 67.804554v135.451569a94.649108 94.649108 0 0 1 71.806031 71.821785H459.067077a94.554585 94.554585 0 0 1 144.336738-58.446769l196.292923-189.959877a93.892923 93.892923 0 0 1-11.027692-32.389908zM602.190769 240.403692A94.208 94.208 0 0 1 535.630769 267.815385a94.192246 94.192246 0 0 1-64.559261-25.489723L216.048246 445.6448c8.459815 10.712615 14.635323 23.315692 17.8176 37.037292l194.418216-2.016492a94.570338 94.570338 0 0 1 182.6816-1.890462l180.696615-1.874707a94.475815 94.475815 0 0 1 23.804061-39.699693z" fill="#A8ADBB" p-id="2152"></path></svg>

Разлика између датотеке није приказан због своје велике величине
+ 0 - 0
src/assets/img/visisvg/sparkGradientBoostedTreeClassification.svg


+ 1 - 0
src/assets/img/visisvg/sparkIsotonicRegression.svg

@@ -0,0 +1 @@
+<?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 t="1640349539404" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="12210" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M51.2 35.310345m141.241379 0l670.896552 0q141.241379 0 141.241379 141.241379l0 670.896552q0 141.241379-141.241379 141.241379l-670.896552 0q-141.241379 0-141.241379-141.241379l0-670.896552q0-141.241379 141.241379-141.241379Z" fill="#F5222D" opacity=".15" p-id="12211"></path><path d="M548.016552 594.273103c0 2.718897 2.118621 4.943448 4.660965 4.943449h114.829242c2.542345 0 4.660966-2.224552 4.660965-4.943449v-29.801931c0-2.718897-2.118621-4.943448-4.660965-4.943448h-114.829242c-2.542345 0-4.660966 2.224552-4.660965 4.943448v29.801931z m-120.973242 3.778207l119.172414-99.928276a5.014069 5.014069 0 0 0 0-7.627034l-119.172414-99.857655a4.943448 4.943448 0 0 0-8.121379 3.778207v38.912c0 1.483034 0.635586 2.824828 1.800828 3.778207L488.871724 494.344828l-68.148965 57.202758a5.014069 5.014069 0 0 0-1.765518 3.813517v38.912c0 4.237241 4.872828 6.532414 8.12138 3.778207zM774.002759 246.113103H317.086897a19.844414 19.844414 0 0 0-19.844414 19.844414V722.802759c0 10.946207 8.862897 19.844414 19.844414 19.844413H774.002759a19.844414 19.844414 0 0 0 19.844413-19.844413V265.886897a19.844414 19.844414 0 0 0-19.844413-19.844414z m-24.823173 451.866483H341.945379V290.745379h407.198897v407.198897z" fill="#F5222D" p-id="12212"></path></svg>

Разлика између датотеке није приказан због своје велике величине
+ 0 - 0
src/assets/img/visisvg/sparkLatentDirichletAllocation.svg


+ 1 - 0
src/assets/img/visisvg/sparkLinearRegression.svg

@@ -0,0 +1 @@
+<?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 t="1640351895483" class="icon" viewBox="0 0 1280 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="26471" xmlns:xlink="http://www.w3.org/1999/xlink" width="250" height="200"><defs><style type="text/css"></style></defs><path d="M223.996375 896.003397h351.990657V306.499045a159.815758 159.815758 0 0 1-86.757698-94.93748l-263.992992-88.517651a31.999151 31.999151 0 0 1-20.159465-40.518924l20.31946-60.67839A31.999151 31.999151 0 0 1 265.99526 1.687135l235.773742 79.077901C529.388269 32.746311 580.606909 0.027179 639.985333 0.027179a159.995753 159.995753 0 0 1 159.995753 159.995754 158.115803 158.115803 0 0 1-1.999947 19.999469l256.793184 86.097714a31.999151 31.999151 0 0 1 20.159465 40.518925l-20.359459 60.738388a31.999151 31.999151 0 0 1-40.598923 20.159465l-283.992462-95.257472a160.955728 160.955728 0 0 1-25.99931 14.239622V992.000849a31.999151 31.999151 0 0 1-31.99915 31.999151H223.996375a31.999151 31.999151 0 0 1-31.999151-31.999151v-63.998301a31.999151 31.999151 0 0 1 31.999151-31.999151z" p-id="26472"></path><path d="M0.00232 608.011042c0 88.357655 114.616958 159.995753 255.993205 159.995753s255.993205-71.638099 255.993205-159.995753c0-31.339168 4.15989-14.499615-169.995487-363.010365-35.359061-70.718123-136.436379-70.578127-171.735442 0C-2.63761 590.551505 0.00232 575.6519 0.00232 608.011042z m111.997027-31.999151l143.996178-287.992356 143.996178 287.992356z m655.982589 287.992356c0 88.357655 114.616958 159.995753 255.993205 159.995753s255.993205-71.638099 255.993205-159.995753c0-31.339168 4.15989-14.499615-170.095485-363.010365-35.359061-70.718123-136.436379-70.578127-171.735442 0C765.342006 846.54471 767.981936 831.645106 767.981936 864.004247z m111.997027-31.999151l143.996178-287.992356 143.996178 287.992356z" p-id="26473"></path></svg>

+ 1 - 0
src/assets/img/visisvg/sparkMultinomialLogisticRegression.svg

@@ -0,0 +1 @@
+<?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 t="1640348956756" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6814" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M4.143262 2.378831h1008.246153v1008.246154h-1008.246153z" fill="#000000" opacity=".01" p-id="6815"></path><path d="M504.123077 47.261538a94.523077 94.523077 0 0 1 84.283077 137.373539L837.159385 389.498092a94.523077 94.523077 0 1 1 29.365169 176.348554l-77.697969 235.189169a94.523077 94.523077 0 1 1-140.6976 101.691077H375.855262a94.523077 94.523077 0 1 1-140.6976-101.691077L157.443938 565.846646a94.523077 94.523077 0 1 1 27.884308-177.152l235.425477-202.295138A94.523077 94.523077 0 0 1 504.123077 47.261538z m58.226215 168.991508A94.113477 94.113477 0 0 1 504.123077 236.307692a94.097723 94.097723 0 0 1-56.635077-18.8416L217.056492 415.428923A94.113477 94.113477 0 0 1 236.307692 472.615385a94.4128 94.4128 0 0 1-40.802461 77.792492l78.548677 237.757046a94.554585 94.554585 0 0 1 101.817107 73.570462H648.113231a94.554585 94.554585 0 0 1 101.817107-73.570462l78.564431-237.757046A94.4128 94.4128 0 0 1 787.692308 472.615385c0-20.873846 6.774154-40.172308 18.2272-55.800123z" fill="#A8ADBB" p-id="6816"></path></svg>

+ 1 - 0
src/assets/img/visisvg/sparkNaiveBayes.svg

@@ -0,0 +1 @@
+<?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 t="1640349453478" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="9609" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M209.92 848l631.04-631.04a24 24 0 1 0-33.92-33.92l-631.04 631.04V152a24 24 0 0 0-48 0V896h744a24 24 0 1 0 0-48H209.92zM128 0h768a128 128 0 0 1 128 128v768a128 128 0 0 1-128 128H128a128 128 0 0 1-128-128V128a128 128 0 0 1 128-128z m239.36 486.912a48 48 0 1 0-96 0 48 48 0 0 0 96 0zM512 272.768a48 48 0 1 0-96 0 48 48 0 0 0 96 0z m275.904 287.296a48 48 0 1 0-95.872-0.064 48 48 0 0 0 95.872 0.064z m-187.136 125.888a48 48 0 1 0-96 0 48 48 0 0 0 96 0z" fill="#F57948" p-id="9610"></path></svg>

Разлика између датотеке није приказан због своје велике величине
+ 0 - 0
src/assets/img/visisvg/sparkRandomForestClassification.svg


Разлика између датотеке није приказан због своје велике величине
+ 0 - 0
src/assets/img/visisvg/sparkmlKmeans.svg


Разлика између датотеке није приказан због своје велике величине
+ 0 - 0
src/assets/img/visisvg/standardscaler.svg


Разлика између датотеке није приказан због своје велике величине
+ 0 - 0
src/assets/img/visisvg/vgg16.svg


+ 1 - 0
src/assets/img/visisvg/wasiyuce.svg

@@ -0,0 +1 @@
+<?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 t="1640335739856" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2819" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M0 0h1024v1024H0z" fill="#000000" opacity=".01" p-id="2820"></path><path d="M418.848 824.896l1.088 41.6-395.392 10.304-1.088-41.6 395.392-10.304zM384 480a96 96 0 0 1 90.192 128.944l128.88 141.008h370.08v41.6H584.784l-134-146.576a96.032 96.032 0 0 1-160.528-48.192L54 596.8v-41.6h236.272A96.032 96.032 0 0 1 384 480z m128.208-33.344l456 4.544-0.416 41.6-456-4.544 0.416-41.6z m460.96-245.872v41.6H561.664l-176.096 158.72H111.488v-41.6H369.6l176.144-158.72h427.44z" fill="#A8ADBB" p-id="2821"></path></svg>

+ 5 - 1
src/router/index.js

@@ -70,7 +70,11 @@ const mainRoutes = {
     { path: '/train-watch', component: _import('modules/alg/train-watch'), name: 'trainwatch', meta: { title: '编辑文件', isTab: false } },
     // 训练任务tensorboard图像对比的路由
     { path: '/train-compare', component: _import('modules/alg/train-compare'), name: 'traincompare', meta: { title: '训练任务tensorboard图像对比', isTab: false } },
-    { path: '/visi-previewcsv', component: _import('modules/visi/previewcsv'), name: 'previewcsv', meta: { title: '预览csv', isTab: false } }
+    // 数据探测路由
+    { path: '/snoop-measure', component: _import('modules/snoop/measure'), name: 'measure', meta: { title: '创建度量标准', isTab: false } },
+    { path: '/snoop-job', component: _import('modules/snoop/job'), name: 'job', meta: { title: '创建调度任务', isTab: false } },
+    { path: '/visi-previewcsv', component: _import('modules/visi/previewcsv'), name: 'previewcsv', meta: { title: '预览csv', isTab: false } },
+    { path: '/design-create', component: _import('modules/visi/design-graph1'), name: '/design-create', meta: { title: '实验设置', isTab: false } }
   ],
   beforeEnter (to, from, next) {
     let token = Vue.cookie.get('Algtoken')

+ 6 - 1
src/utils/httpRequest.js

@@ -45,7 +45,12 @@ http.adornUrl = (actionName) => {
   // 非生产环境 && 开启代理, 接口前缀统一使用[/proxyApi/]前缀做代理拦截!
   return (process.env.NODE_ENV !== 'production' && process.env.OPEN_PROXY ? '/proxyApi/' : window.SITE_CONFIG.baseUrl) + actionName
 }
-
+// 数据质量探测 请求前缀
+http.snoopUrl = (actionName) => {
+  // snoop
+  // return '/snoopapi'
+  return '/snoopapi' + actionName
+}
 /**
  * get请求参数处理
  * @param {*} params 参数对象

+ 631 - 0
src/views/modules/snoop/home.vue

@@ -0,0 +1,631 @@
+<!--  -->
+<template>
+  <div class=''>
+    <el-breadcrumb class="divi2" separator-class="el-icon-arrow-right">
+      <el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
+      <el-breadcrumb-item>数据质量探测</el-breadcrumb-item>
+    </el-breadcrumb>
+    <el-divider class="divi"></el-divider>
+
+    <el-form :inline="true" :model="dataForm" @keyup.enter.native="getMeasureOrJobList">
+      <el-form-item>
+        <el-button v-if="isAuth('snoop:save')" type="primary" @click="addHandle()">新建探测</el-button>
+        <el-button v-if="isAuth('snoop:delete')" type="danger" @click="measureAndJobDelete()"
+                   :disabled="dataListSelections.length <= 0">批量删除
+        </el-button>
+      </el-form-item>
+      <el-form-item>
+        <el-input v-model="dataForm.algorithmName" :placeholder="classificationtag=='度量'?'请输入度量名称':'请输入任务名称' " clearable
+                  @keyup.enter.native="pageIndex = 1;getMeasureList()"></el-input>
+      </el-form-item>
+      <el-form-item>
+        <el-button @click="pageIndex = 1;getMeasureList()">查询</el-button>
+      </el-form-item>
+      <el-form-item>
+        <el-tag>筛选:</el-tag>
+        <el-select v-model="classificationtag" placeholder="类别" size="mini" style="width: 130px;"
+                   @change="pageIndex = 1;getMeasureOrJobList()">
+          <el-option v-for="data in classification" :key="data" :label="data" :value="data">
+          </el-option>
+        </el-select>
+      </el-form-item>
+    </el-form>
+
+
+    <div v-if="classificationtag === '度量'" >
+      <el-table key="度量" :data="measureList" border
+                v-loading="measDataListLoading"
+                @selection-change="SelectionChange"
+                style="width: 100%;">
+        <el-table-column type="selection" header-align="center" align="center" width="50">
+        </el-table-column>
+        <el-table-column prop="Id" header-align="center" align="center" width="80" label="序号"
+                         type="index" :index='(index)=>{return (index+1) + (this.pageIndex-1)*this.pageSize}'>
+        </el-table-column>
+        <el-table-column prop="measureName" header-align="center" align="center" label="度量名称">
+        </el-table-column>
+        <el-table-column prop="measureType" header-align="center" align="center" label="度量类型"></el-table-column>
+        <!--        <el-table-column prop="username" header-align="center" align="center" label="创建人">-->
+        <!--        </el-table-column>-->
+        <!--        <el-table-column prop="createTime" header-align="center" align="center" label="创建时间">-->
+        <!--        </el-table-column>-->
+        <el-table-column prop="remark" header-align="center" align="center" label="备注">
+        </el-table-column>
+        <el-table-column fixed="right" header-align="center" align="center" width="250" label="操作">
+          <template slot-scope="scope">
+            <el-button type="text" size="small"  v-if="isAuth('snoop:measure:look')" @click="userwatch(scope.row)">查看</el-button>
+            <el-button type="text" size="small"  v-if="isAuth('snoop:delete')"  @click="measureDeleteHandle(scope.row)">删除</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+    </div>
+
+    <div v-if="classificationtag === '任务'">
+      <el-table key="任务" :data="jobList" border
+                v-loading="jobDataListLoading"
+                @selection-change="SelectionChange"
+                style="width: 100%;">
+        <el-table-column type="selection" header-align="center" align="center" width="50">
+        </el-table-column>
+        <el-table-column prop="Id" header-align="center" align="center" width="80" label="序号"
+                         type="index" :index='(index)=>{return (index+1) + (this.pageIndex-1)*this.pageSize}'>
+        </el-table-column>
+        <el-table-column prop="jobName" header-align="center" align="center" label="任务名称">
+        </el-table-column>
+        <el-table-column prop="jobState.previousFireTime" header-align="center" align="center" label="上次执行时间">
+          <template slot-scope="scope">
+            {{ scope.row.jobState.previousFireTime | timeFormater }}
+          </template>
+        </el-table-column>
+        <el-table-column prop="jobState.nextFireTime" header-align="center" align="center" label="下次执行时间">
+          <template slot-scope="scope">
+            {{ scope.row.jobState.nextFireTime | timeFormater }}
+          </template>
+        </el-table-column>
+        <el-table-column prop="state" header-align="center" align="center" label="状态">
+          <template slot-scope="scope">
+            <el-tag v-if="scope.row.jobState.state === 'NORMAL'" size="small">正常</el-tag>
+            <el-tag v-else size="small" type="danger">暂停</el-tag>
+          </template>
+        </el-table-column>
+        <!--        <el-table-column prop="username" header-align="center" align="center" label="创建人">-->
+        <!--        </el-table-column>-->
+        <!--        <el-table-column prop="createTime" header-align="center" align="center" label="创建时间">-->
+        <!--        </el-table-column>-->
+
+        <el-table-column fixed="right" header-align="center" align="center" width="250" label="操作">
+          <template slot-scope="scope">
+            <el-button v-if="isAuth('snoop:job:look')" type="text" size="small" @click="jobWatch(scope.row)">查看
+            </el-button>
+            <el-button v-if="isAuth('snoop:job:delete')" type="text" size="small"
+                       @click="jobDeleteHandle(scope.row)">删除
+            </el-button>
+            <el-button v-if="isAuth('snoop:job:pause')" type="text" size="small"
+                       @click="jobPauseHandle(scope.row)" >
+              暂停
+            </el-button>
+            <el-button v-if="isAuth('snoop:job:resume')" type="text" size="small"
+                       @click="jobResumeHandle(scope.row)">恢复
+            </el-button>
+            <el-button v-if="isAuth('snoop:job:result')" type="text" size="small" @click="jobResHandle(scope.row)">结果
+            </el-button>
+            <el-button v-if="isAuth('sys:schedule:log')" type="text" size="small" @click="jobLogHandle(scope.row)">日志
+            </el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+    </div>
+
+    <el-pagination @size-change="sizeChangeHandle" @current-change="currentChangeHandle" :current-page="pageIndex"
+                   :page-sizes="[10, 20, 50, 100]" :page-size="pageSize" :total="totalPage"
+                   layout="total, sizes, prev, pager, next, jumper">
+    </el-pagination>
+    <snoop v-if="addVisible" ref="addS" @refreshDataList="getMeasureList"></snoop>
+    <measureUserWatch v-if="newWatchVisible" ref="measureWatch"></measureUserWatch>
+    <job-watch v-if="jobWatchVisible" ref="jobWatch"></job-watch>
+    <job-log v-if="jobLoghVisible" ref="jobLog"></job-log>
+    <jobResultVisiEchars v-if="jobResVisible" ref="jobRes" ></jobResultVisiEchars>
+  </div>
+</template>
+
+<script>
+// import AlgAdd from './alg-add.vue';
+// 这里可以导入其他文件(比如:组件,工具js,第三方插件js,json文件,图片文件等等)
+// 例如:import 《组件名称》 from '《组件路径》';
+// import AddOrUpdate from "./dataset-add-or-update";
+// import Watch from "./dataset-watch";
+import snoop from './snoop-add'
+import measureUserWatch from './measureUserWatch'
+import jobWatch from './jobWatch'
+import jobLog from './jobLog'
+// import jobResultVisi from './jobResult_visi'
+import jobResultVisiEchars from './jobResult_visi_echars'
+import { MessageBox } from 'element-ui'
+import { Message } from 'element-ui'
+
+export default {
+  // import引入的组件需要注入到对象中才能使用
+  data () {
+    return {
+      dataForm: {
+        algorithmName: ''
+      },
+      userID: this.$store.state.user.id, // 用户编号
+      // userName: this.$store.state.user.name, // 用户编号
+      userName: 'test',
+      measureList: [],    // 分页使用  当前显示的度量数据
+      measureListAll: [],  // 分页使用  所用的度量数据
+      jobList: [],   // 分页使用  当前显示的任务数据
+      jobListAll: [],  // 分页使用  所用的任务数据
+      pageIndex: 1,
+      pageSize: 10,
+      totalPage: 0,
+      jobDataListLoading: false,
+      measDataListLoading: false,
+      dataListSelections: [],
+      addOrUpdateVisible: false,
+      newWatchVisible: false,
+      jobWatchVisible: false,
+      addVisible: false,
+      jobLoghVisible: false,
+      jobResVisible: false,
+      classificationtag: '',
+      classification: ['度量', '任务']
+    }
+  },
+  components: {
+    // AlgAdd
+    // AddOrUpdate,
+    // Watch,
+    // Add
+    snoop,
+    measureUserWatch,
+    jobWatch,
+    jobLog,
+    jobResultVisiEchars
+  },
+
+  activated () {
+    // this.getMeasureList()
+    // this.getJobList()
+    this.classificationtag = this.classification[0]
+    var sign = this.$route.query.status
+    if (sign) {
+      this.classificationtag = this.classification[sign]
+      this.getMeasureOrJobList()
+    }
+  },
+  mounted () {
+    this.getMeasureList()
+  },
+  filters: {
+    timeFormater (value) {
+      var date = new Date(value)
+      let years = date.getFullYear()
+      let month = (date.getMonth() + 1) > 10 ? date.getMonth() + 1 : '0' + (date.getMonth() + 1)
+      let day = (date.getDate() >= 10) ? date.getDate() : '0' + date.getDate()
+      let hours = (date.getHours() >= 10) ? date.getHours() : '0' + date.getHours()
+      let minutes = (date.getMinutes() >= 10) ? date.getMinutes() : '0' + date.getMinutes()
+      let seconds = (date.getSeconds() >= 10) ? date.getSeconds() : '0' + date.getSeconds()
+      if (value) {
+        return years + '-' + month + '-' + day +
+          ' ' + hours + ':' + minutes + ':' + seconds
+      } else {
+        return 'N/A'
+      }
+    }
+  },
+  methods: {
+    getMeasureOrJobList () {
+      if (this.classificationtag === '度量') {
+        this.getMeasureList()
+      } else {
+        this.getJobList()
+      }
+    },
+    // 获取数据列表
+    getMeasureList () {
+      this.measureListAll = []
+      this.measureList = []
+      this.measDataListLoading = true
+
+      // this.measureList = [
+      //   {'measureID': 1, 'measureName': 'demo1', 'measureType': 'profiling', 'remark': '测试'},
+      //   {'measureID': 1, 'measureName': 'demo1', 'measureType': 'profiling', 'remark': '测试'}
+      //
+      // ]
+      this.$http({
+        url: this.$http.snoopUrl('/v1/measures/owner/') + this.userName,
+        methods: 'get'
+      }).then((datas) => {
+        if (datas && datas.status === 200) {
+          var res = datas.data.reverse()
+          // console.log(res)
+          res.map((info) => {
+            var measure = {
+              'measureID': info['id'],
+              'measureName': info['name'],
+              'measureType': info['dq.type'],
+              'remark': info['description']
+            }
+            this.measureListAll.push(measure)
+          })
+        }
+        this.unique(this.measureListAll)
+        this.measureList = this.measureListAll.slice(0, this.pageSize)
+        this.totalPage = this.measureListAll.length
+        this.measDataListLoading = false
+      })
+    },
+    toCamel (myString) {
+      return myString.replace(/[.]([a-z])/g, function (g) {
+        return g[1].toUpperCase()
+      })
+    },
+
+    swapJson (json) {
+      const ret = {}
+      for (const key in json) {
+        ret[this.toCamel(key)] = json[key]
+      }
+      return ret
+    },
+    getJobList () {
+      this.jobListAll = []
+      this.jobDataListLoading = true
+      const self = this
+      this.$http({
+        url: this.$http.snoopUrl('/v1/jobs'),
+        methods: 'get'
+      }).then((datas) => {
+        if (datas && datas.status === 200) {
+          var data = datas.data
+          const trans = Object.keys(data).map(function (index) {
+            const job = self.swapJson(data[index])
+            job.jobState.previousFireTime = job.jobState.previousFireTime < 0 ? '' : job.jobState.previousFireTime
+            return job
+          })
+          this.jobListAll = Object.assign([], trans).reverse()
+          this.jobList = this.jobListAll.slice(0, this.pageSize)
+          this.totalPage = this.jobListAll.length
+        }
+
+        this.jobDataListLoading = false
+      })
+    },
+    // 去重
+    unique (arr) {
+      var ss = []
+      for (var i = 0; i < arr.length; i++) {
+        ss[i] = arr[i].measureName
+      }
+      return Array.from(new Set(ss))
+    },
+    // 每页数
+    sizeChangeHandle (val) {
+      this.pageSize = val
+      this.pageIndex = 1
+      if (this.classificationtag === '任务') {
+        let start = (this.pageIndex - 1) * this.pageSize
+        this.jobList = this.jobListAll.slice(start, this.pageSize)
+      } else {
+        let start = (this.pageIndex - 1) * this.pageSize
+        this.measureList = this.measureListAll.slice(start, this.pageSize)
+      }
+    },
+    // 当前页
+    currentChangeHandle (val) {
+      this.pageIndex = val
+      if (this.classificationtag === '任务') {
+        let start = (this.pageIndex - 1) * this.pageSize
+        let end = (this.pageIndex) * this.pageSize
+        this.jobList = this.jobListAll.slice(start, end)
+      } else {
+        let start = (this.pageIndex - 1) * this.pageSize
+        let end = (this.pageIndex) * this.pageSize
+        this.measureList = this.measureListAll.slice(start, end)
+      }
+    },
+    // **********************8多选
+    SelectionChange (val) {
+      this.dataListSelections = val
+    },
+
+    // 查看
+    userwatch (info) {
+      this.newWatchVisible = true
+      this.$nextTick(() => {
+        this.$refs.measureWatch.init(info)
+      })
+    },
+    jobWatch (info) {
+      this.jobWatchVisible = true
+      this.$nextTick(() => {
+        this.$refs.jobWatch.init(info)
+      })
+    },
+    jobLogHandle (info) {
+      this.jobLoghVisible = true
+      this.$nextTick(() => {
+        this.$refs.jobLog.init(info)
+      })
+    },
+    jobResHandle (info) {
+      this.jobResVisible = true
+      this.$nextTick(() => {
+        this.$refs.jobRes.init(info)
+      })
+    },
+
+    // 这里处理新建
+    addHandle () {
+      this.addVisible = true
+      this.$nextTick(() => {
+        this.$refs.addS.init()
+      })
+    },
+    jobResumeHandle (info) {
+      MessageBox.confirm(
+        `确定对[任务名=${info.jobName}]进行[恢复]操作?`,
+        '提示',
+        {
+          confirmButtonText: '确定',
+          cancelButtonText: '取消',
+          type: 'warning'
+        }
+      ).then((data) => {
+        this.jobDataListLoading = true
+        //  进行后台请求
+        this.$http({
+          url: this.$http.snoopUrl('/v1/jobs/') + info.id + '?action=start',
+          method: 'put'
+        }).then((data) => {
+          if (data && data.status === 200) {
+            Message({
+              message: '操作成功',
+              type: 'success',
+              duration: 1500,
+              onClose: () => {
+                this.getJobList()
+              }
+            })
+          } else {
+            this.$message.error(info.jobName + '恢复失败')
+            this.getJobList()
+          }
+        })
+      })
+        .catch(() => {
+        })
+    },
+    jobPauseHandle (info) {
+      MessageBox.confirm(
+        `确定对[任务名=${info.jobName}]进行[暂停]操作?`,
+        '提示',
+        {
+          confirmButtonText: '确定',
+          cancelButtonText: '取消',
+          type: 'warning'
+        }
+      ).then((data) => {
+        this.jobDataListLoading = true
+        //  进行后台请求
+        this.$http({
+          url: this.$http.snoopUrl('/v1/jobs/') + info.id + '?action=stop',
+          method: 'put'
+        }).then((data) => {
+          if (data && data.status === 200) {
+            Message({
+              message: '操作成功',
+              type: 'success',
+              duration: 1500,
+              onClose: () => {
+                this.getJobList()
+              }
+            })
+          } else {
+            this.$message.error(info.jobName + '恢复失败')
+            this.getJobList()
+          }
+        })
+      })
+        .catch(() => {
+        })
+    },
+    jobDeleteHandle (info) {
+      MessageBox.confirm(
+        `确定对[任务名=${info.jobName}]进行 [删除] 操作?`,
+        '提示',
+        {
+          confirmButtonText: '确定',
+          cancelButtonText: '取消',
+          type: 'warning'
+        }
+      ).then(() => {
+        this.jobDataListLoading = true
+        //  进行后台请求
+        this.$http({
+          url: this.$http.snoopUrl('/v1/jobs/') + info.id,
+          method: 'delete'
+        }).then((data) => {
+          // console.log(data)
+          if (!data.data) {
+            Message({
+              message: '操作成功',
+              type: 'success',
+              duration: 1500,
+              onClose: () => {
+                this.getJobList()
+              }
+            })
+          } else {
+            MessageBox.error(info.jobName + '删除失败')
+            this.getJobList()
+          }
+        })
+      })
+        .catch(() => {
+        })
+    },
+    // ********** 删除
+    measureDeleteHandle (info) {
+      MessageBox.confirm(
+        `确定对[${info.measureName}]进行[删除]操作? 删除后,对应job也会被删除`,
+        '提示',
+        {
+          confirmButtonText: '确定',
+          cancelButtonText: '取消',
+          type: 'warning'
+        }
+      )
+        .then(() => {
+          this.$http({
+            url: this.$http.snoopUrl('/v1/measures/') + info.measureID,
+            method: 'delete'
+          }).then(({data}) => {
+            this.measDataListLoading = true
+            if (!data.data) {
+              Message({
+                message: '操作成功',
+                type: 'success',
+                duration: 1500
+              })
+              this.measDataListLoading = false
+              this.getMeasureList()
+              this.pageIndex = 1
+            } else {
+              Message.error(data.msg)
+            }
+          })
+        })
+        .catch(() => {
+        })
+    },
+    async measureAndJobDelete () {
+      var waitSecond = 1
+      if (this.classificationtag === '度量') {
+        var allMeasureName = []
+        for (var index in this.dataListSelections) {
+          allMeasureName.push(this.dataListSelections[index].measureName)
+        }
+        await MessageBox.confirm(
+          `确定对[${allMeasureName}]进行[删除]操作? 删除后,对应job也会被删除`,
+          '提示',
+          {
+            confirmButtonText: '确定',
+            cancelButtonText: '取消',
+            type: 'warning'
+          }
+        ).then(() => {
+          this.measDataListLoading = true
+          let failure = []
+          for (var index = 0; index < this.dataListSelections.length; index++) {
+            waitSecond = waitSecond + 0.5
+            this.$http({
+              url: this.$http.snoopUrl('/v1/measures/') + this.dataListSelections[index].measureID,
+              method: 'delete'
+            }).then((data) => {
+              if (data.data) {
+                failure.push(this.dataListSelections[index])
+              }
+            })
+          }
+
+          if (failure.length === 0) {
+            MessageBox({
+              message: '操作成功',
+              type: 'success',
+              duration: 1500
+            })
+          } else {
+            var msg = ''
+            failure.forEach(x => {
+              msg = msg + ' ' + x.measureName
+            })
+            MessageBox.error(msg)
+          }
+          setTimeout(() => {
+            this.measDataListLoading = false
+            this.getMeasureList()
+          }, waitSecond * 1000)
+        }).catch(() => {
+
+        })
+      } else {
+        var allJobName = []
+        for (var jobindex in this.dataListSelections) {
+          allJobName.push(this.dataListSelections[jobindex].jobName)
+        }
+        await MessageBox.confirm(
+          `确定对[${allJobName}]进行[删除]操作? `,
+          '提示',
+          {
+            confirmButtonText: '确定',
+            cancelButtonText: '取消',
+            type: 'warning'
+          }
+        ).then(() => {
+          this.jobDataListLoading = true
+          let failure = []
+          for (var index = 0; index < this.dataListSelections.length; index++) {
+            waitSecond = waitSecond + 0.5
+            this.$http({
+              url: this.$http.snoopUrl('/v1/jobs/') + this.dataListSelections[index].id,
+              method: 'delete'
+            }).then((data) => {
+              if (data.data) {
+                failure.push(this.dataListSelections[index])
+              }
+            })
+          }
+
+          if (failure.length === 0) {
+            MessageBox({
+              message: '操作成功',
+              type: 'success',
+              duration: 1500
+            })
+          } else {
+            var msg = ''
+            failure.forEach(x => {
+              msg = msg + ' ' + x.jobName
+            })
+            MessageBox.error(msg)
+          }
+          setTimeout(() => {
+            this.jobDataListLoading = false
+            this.getJobList()
+          }, waitSecond * 1000)
+        }).catch(() => {
+
+        })
+      }
+    }
+  }
+}
+</script>
+<style scoped>
+.divi {
+  display: block;
+  height: 1px;
+  width: 100%;
+  margin: 24px 0;
+  background-color: #dcdfe6;
+  position: relative;
+}
+
+.divi2 {
+  display: block;
+  height: 1px;
+  width: 100%;
+  position: relative;
+}
+
+.sele {
+  border: 1px solid #409eff;
+  border-radius: 5px;
+  box-sizing: border-box;
+  padding: 5px 0px;
+  margin: 10px;
+}
+</style>

+ 270 - 0
src/views/modules/snoop/job.vue

@@ -0,0 +1,270 @@
+<template>
+<div>
+  <el-breadcrumb class="divi2" separator-class="el-icon-arrow-right">
+    <el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
+    <el-breadcrumb-item :to="{ path: '/snoop-home'}">数据质量探测</el-breadcrumb-item>
+    <el-breadcrumb-item>创建度量标准</el-breadcrumb-item>
+  </el-breadcrumb>
+  <el-divider class="divi"></el-divider>
+
+
+  <el-col :span="16" style="height: 100%;margin-left: 160px;">
+    <h4> 配置调度任务 :</h4>
+    <div style="height: 360px;overflow-scrolling: auto">
+      <el-form ref="jobForm" :model="jobcForm" label-width="120px" :rules="rules">
+        <el-form-item label="任务名称 :" prop="name">
+          <el-input v-model="jobcForm.name"></el-input>
+        </el-form-item>
+        <el-form-item label="度量名称 :" prop="measureID">
+          <el-select v-model="jobcForm.measureID"   @change="onChange" placeholder="请选择"              >
+            <el-option
+              v-for="measure in measures"
+              :key="measure.id"
+              :label="measure.name"
+              :value="measure.id"></el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="调度周期 :" prop="cron">
+          <el-input  v-model="jobcForm.cron" placeholder="请输入抽取周期"  clearable
+                     @focus="dialogVisible = true">
+          </el-input>
+          <el-dialog custom-class="cron-box-dialog-first" :visible.sync="dialogVisible" v-if="dialogVisible">
+            <mycron v-bind:extractionPeriod.sync="jobcForm.cron"></mycron>
+          </el-dialog>
+        </el-form-item>
+        <el-form-item label="请选择时间范围 :" prop="range">
+          <el-slider v-model="jobcForm.range" range show-stops :max="0" :min="-10" :marks="marks">
+          </el-slider>
+        </el-form-item>
+        <el-form-item style="float:right ;margin-top: 20px">
+          <el-button @click="visible = false;redirectHandle()">取消</el-button>
+          <el-button type="primary" @click="submitForm()">确定</el-button>
+        </el-form-item>
+      </el-form>
+
+    </div>
+  </el-col>
+</div>
+</template>
+
+<script>
+import mycron from '../visi/quartz/mycron'
+import { MessageBox } from 'element-ui'
+import { Message } from "element-ui"
+export default {
+  components: {mycron},
+  name: 'job',
+  data () {
+    // var checkExtractionPeriod = (rule, value, callback) => {
+    //   if (!value) {
+    //     return callback(new Error('抽取周期不能为空'))
+    //   } else {
+    //     return callback()
+    //   }
+    // }
+    return {
+      jobcForm: {
+        name: '',
+        measureID: '',
+        cron: '',
+        range: [-1, 0],
+        dropdownList: []
+      },
+      marks: {
+        '-1': '-1 day',
+        '-2': '-2 day',
+        '-3': '-3 day',
+        '-5': '-5 day',
+        '-7': '-7 day',
+        '-10': '-10 day'
+      },
+      dialogVisible: false,
+      measures: [],
+      rules: {
+        name: [
+          {required: true, message: '请输入任务名称', trigger: 'blur'},
+          {min: 3, max: 18, message: '长度在 3 到 18 个字符', trigger: 'blur'}
+        ],
+        measureID: [
+          { required: true, message: '请选择度量方案', trigger: 'change' }
+        ],
+        cron: [
+          // { validator: checkExtractionPeriod, trigger: 'blur' }
+          { required: true, message: '请输入调度周期', trigger: 'change' }
+        ]
+      }
+    }
+  },
+  methods: {
+    redirectHandle () {
+      this.$router.replace({ path: '/snoop-home' })
+    },
+
+    // 向后台提交数据
+    async finallySubmit () {
+      this.newJob = {
+        'job.name': this.jobcForm.name,
+        'job.type': 'batch',
+        'measure.id': this.jobcForm.measureID,
+        'cron.expression': this.jobcForm.cron,
+        // 'cron.time.zone': this.timezone,
+        'cron.time.zone': 'GMT+8:00',
+        // "predicate.config": {
+        // "interval": "1m",
+        // "repeat": 2
+        // },
+        'data.segments': [
+          // {
+          //   "data.connector.index": "source[0]",
+          //   "segment.range": {
+          //   "begin": "",
+          //   "length": ""
+          //   }
+          // },
+          // {
+          //   "data.connector.index": "target[0]",
+          //   "segment.range": {
+          //   "begin": "",
+          //   "length": ""
+          //   }
+          // }
+        ]
+      }
+      for (let i = 0; i < this.dropdownList.length; i++) {
+        var connector = this.dropdownList[i]
+        var begin = this.jobcForm.range[0]
+        var length = this.jobcForm.range[1] - this.jobcForm.range[0]
+        var beginStr = this.getTimeByUnit(begin, connector.size)
+        var lengthStr = this.getTimeByUnit(length, connector.size)
+        this.newJob['data.segments'].push({
+          'data.connector.name': connector.connectorname,
+          'as.baseline': true,
+          'segment.range': {
+            begin: beginStr,
+            length: lengthStr
+          }
+        })
+      }
+      if (this.dropdownList.length === 2) {
+        delete this.newJob['data.segments'][1]['as.baseline']
+      }
+      console.log(this.newJob)
+      await this.$http({
+        url: this.$http.snoopUrl('/v1/jobs'),
+        method: 'post',
+        data: this.$http.adornData(this.newJob)
+      }).then((datas) => {
+        // console.log(6666)
+        if (datas.status === 201) {
+          return true
+        } else {
+          return false
+        }
+      })
+        // .catch(err => {
+        //   console.log(err)
+        //   let response = JSON.parse(err.error)
+        //   console.log(response)
+        //   if (response.code === '40004') {
+        //     console.log('error', 'Error!', 'Job name already exists!')
+        //   } else {
+        //     console.log('error', 'Error!', response.message)
+        //   }
+        // })
+    },
+    submitForm () {
+      this.$refs['jobForm'].validate((valid) => {
+        if (valid) {
+          var submit = this.finallySubmit()
+
+          setTimeout(() => {
+            if (submit) {
+              Message({
+                message: '调度任务   ' + this.jobcForm.name + '   创建成功',
+                type: 'success'
+              })
+            } else {
+              Message({
+                message: '调度任务   ' + this.jobcForm.name + '   创建失败',
+                type: 'error'
+              })
+            }
+            this.$router.replace({path: '/snoop-home', query: {'status': '1'}})
+            this.$destroy()
+          }, 2 * 1000)
+        } else {
+          // console.log('error submit!!')
+          return false
+        }
+      })
+    },
+    getTimeByUnit (multiplier, unit) {
+      var regex = /^(\d+)([a-zA-Z]+)$/g
+      var arr = regex.exec(unit)
+      if (arr.length > 2) {
+        var n = parseInt(arr[1])
+        var unitStr = arr[2]
+        return ((n * multiplier).toString() + arr[2])
+      } else {
+        return multiplier.toString()
+      }
+    },
+    onChange (measure) {
+      this.dropdownList = []
+      console.log(measure)
+      for (let index in this.measures) {
+        var map = this.measures[index]
+        // console.log(measure)
+        // console.log(map.id)
+        if (measure === map.id) {
+          var source = map['data.sources']
+          for (let i = 0; i < source.length; i++) {
+            var connector = source[i].connector
+            if (connector['data.unit'] !== undefined) {
+              var table = connector.config.database + '.' + connector.config['table.name']
+              var size = connector['data.unit']
+              var connectorname = connector['name']
+              var detail = {
+                id: i + 1,
+                name: table,
+                size: size,
+                connectorname: connectorname
+              }
+              this.dropdownList.push(detail)
+            }
+          }
+        }
+      }
+    }
+  },
+  mounted () {
+    // console.log(this.$http.snoopUrl('/v1/measures/owner/') +  this.$store.state.user.name)  实际项目用这个
+    this.$http({
+      url: this.$http.snoopUrl('/v1/measures/owner/') + 'test',
+      method: 'get'
+    }).then((datas) => {
+      if (datas && datas.status === 200) {
+        var res = datas.data.reverse()
+        res.forEach((info) => {
+          if (info['process.type'] === 'BATCH') {
+            this.measures.push(info)
+          }
+        })
+      }
+    })
+    // for (var i = 0; i < 10; i++) {
+    //   obj = { 'id': i, 'name': 'demo' + i}
+    //   this.measures.push(obj)
+    // }
+  }
+}
+</script>
+
+<style scoped>
+.divi2 {
+  display: block;
+  height: 1px;
+  width: 100%;
+  position: relative;
+}
+</style>

+ 191 - 0
src/views/modules/snoop/jobLog.vue

@@ -0,0 +1,191 @@
+<template>
+<div>
+  <el-dialog
+    title="日志列表"
+    :close-on-click-modal="false"
+    v-if="visible"
+    :visible.sync="visible"
+    width="75%">
+    <el-table
+      :data="dataList"
+      border
+      v-loading="logDataListLoading"
+      height="460"
+      style="width: 100%;margin-top: -30px;">
+      <el-table-column
+        prop="id"
+        header-align="center"
+        align="center"
+        label="日志ID">
+      </el-table-column>
+      <el-table-column
+        prop="appId"
+        header-align="center"
+        align="center"
+        label="AppID">
+        <template slot-scope="scope">
+<!--          style="color:blue;cursor:pointer"-->
+          <div @click="detailData(scope.row.appUri)" >{{ scope.row.appId }}</div>
+        </template>
+      </el-table-column>
+      <el-table-column
+        prop="timestamp"
+        header-align="center"
+        align="center"
+        label="执行时间"
+      >
+        <template slot-scope="scope">
+          {{scope.row.timestamp | timeFormater}}
+        </template>
+      </el-table-column>
+      <el-table-column
+        prop="status"
+        header-align="center"
+        align="center"
+        label="状态">
+        <template slot-scope="scope">
+
+          <el-tag v-if="scope.row.state === 'STARTING'" size="small">排队中</el-tag>
+          <el-tag v-else-if="scope.row.state === 'FINDING'" size="small">启动中</el-tag>
+          <el-tag v-else-if="scope.row.state === 'RUNNING'" size="small">进行中</el-tag>
+          <el-tag v-else-if="scope.row.state === 'SUCCESS'" size="small">已完成</el-tag>
+          <el-tag v-else  size="small" type="danger" style="cursor: pointer;">失败</el-tag>
+        </template>
+      </el-table-column>
+    </el-table>
+    <el-pagination
+      @size-change="sizeChangeHandle"
+      @current-change="currentChangeHandle"
+      :current-page="pageIndex"
+      :page-sizes="[10, 20, 50, 100]"
+      :page-size="pageSize"
+      :total="totalPage"
+      layout="sizes, prev, pager, next">
+    </el-pagination>
+  </el-dialog>
+</div>
+</template>
+
+<script>
+export default {
+  name: 'jobLog',
+  data () {
+    return {
+      visible: true,
+      dataForm: {
+        id: ''
+      },
+      info: null,
+      dataList: [],
+      pageIndex: 1,
+      pageSize: 10,
+      totalPage: 0,
+      logDataListLoading: false
+    }
+  },
+  filters: {
+    timeFormater (value) {
+      // console.log('@', value)
+      var date = new Date(value)
+      let years = date.getFullYear()
+      let month = (date.getMonth() + 1) > 10 ? date.getMonth() + 1 : '0' + (date.getMonth() + 1)
+      let day = (date.getDate() >= 10) ? date.getDate() : '0' + date.getDate()
+      let hours = (date.getHours() >= 10) ? date.getHours() : '0' + date.getHours()
+      let minutes = (date.getMinutes() >= 10) ? date.getMinutes() : '0' + date.getMinutes()
+      let seconds = (date.getSeconds() >= 10) ? date.getSeconds() : '0' + date.getSeconds()
+      if (value) {
+        return years + '-' + month + '-' + day +
+          ' ' + hours + ':' + minutes + ':' + seconds
+      } else {
+        return 'N/A'
+      }
+    }
+  },
+  methods: {
+    init (info) {
+      this.visible = true
+      this.info = info
+      this.dataList = []
+      this.pageIndex = 1
+      this.pageSize = 10
+      this.totalPage = 0
+      // console.log(info.id)
+      this.getJobLog()
+    },
+    getJobLog () {
+      // console.log(id)
+      this.dataList = []
+      this.logDataListLoading = true
+      this.$http({
+        url: this.$http.snoopUrl('/v1/jobs/instances'),
+        methods: 'get',
+        params: this.$http.adornParams({
+          'page': this.pageIndex - 1,
+          'size': this.pageSize + 1,
+          'jobId': this.info.id
+        })
+      }).then((data) => {
+        if (data && data.status === 200) {
+          // console.log(data.data)
+          this.dataList = data.data
+        }
+        this.$nextTick(() => {
+          this.haveNextPage()
+        })
+        this.logDataListLoading = false
+      })
+      // this.dataList = [
+      //   {
+      //     'id': 1727,
+      //     'sessionId': 719,
+      //     'state': 'STARTING',
+      //     'type': 'BATCH',
+      //     'appId': 'application_1642725586357_0719',
+      //     'appUri': 'http://griffin:8088 /cluster/app/ application_1642725586357_0719',
+      //     'predicateGroup': 'PG',
+      //     'predicateName': 'demo1_job_predicate_1642734240026',
+      //     'timestamp': 1642734240026,
+      //     'expireTimestamp': 1643339040026
+      //   },
+      //   {
+      //     'id': 1721,
+      //     'sessionId': 713,
+      //     'state': 'STARTING',
+      //     'type': 'BATCH',
+      //     'appId': 'application_1642725586357_0714',
+      //     'appUri': 'http://griffin:8088 /cluster/app/ application_1642725586357_0714',
+      //     'predicateGroup': 'PG',
+      //     'predicateName': 'demo1_job_predicate_1642734180011',
+      //     'timestamp': 1642734180012,
+      //     'expireTimestamp': 1643338980012
+      //   }]
+    },
+    detailData (url) {
+      let newuRL = url.replace(/hadoop112/g, 'hadoop113')
+      window.open(newuRL, '_blank')
+    },
+    // 每页数
+    sizeChangeHandle (val) {
+      this.pageSize = val
+      this.pageIndex = 1
+      this.getJobLog()
+    },
+    // 当前页
+    currentChangeHandle (val) {
+      this.pageIndex = val
+      this.getJobLog()
+    },
+    haveNextPage () {
+      if (this.dataList.length > this.pageSize) {
+        this.totalPage = (this.pageIndex - 1) * this.pageSize + this.dataList.length
+        this.dataList.pop()
+      }
+    }
+
+  }
+}
+</script>
+
+<style scoped>
+
+</style>

+ 207 - 0
src/views/modules/snoop/jobResult.vue

@@ -0,0 +1,207 @@
+<template>
+  <div>
+    <el-dialog
+      :title="title"
+      :close-on-click-modal="false"
+      v-if="visible"
+      :visible.sync="visible"
+      width="75%">
+      <el-table
+        :data="useDataList"
+        border
+        v-loading="dataListLoading"
+        height="530"
+        style="width: 100%;margin-top: -30px;">
+
+        <el-table-column v-if="showID" prop="Id" header-align="center" align="center" width="80" label="id"
+                         type="index" :index='(index)=>{return (index+1) + (this.pageIndex-1)*this.pageSize}'>
+        </el-table-column>
+        <el-table-column  v-if="showID" header-align="center" align="center"  label="time">
+          <template slot-scope="scope">
+            {{scope.row.time | timeFormater}}
+          </template>
+        </el-table-column>
+        <el-table-column v-for="col in tableClo" :key="col"
+                         :prop="col"
+                         header-align="center"
+                         align="center"
+                         :label="col">
+        </el-table-column>
+      </el-table>
+      <el-pagination
+        @size-change="sizeChangeHandle"
+        @current-change="currentChangeHandle"
+        :current-page="pageIndex"
+        :page-sizes="[10, 20, 50, 100]"
+        :page-size="pageSize"
+        :total="totalPage"
+        layout=" sizes, prev, pager, next">
+      </el-pagination>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'jobResult',
+  data () {
+    return {
+      dataList: [],
+      useDataList: [],
+      tableClo: [],
+      visible: true,
+      info: null,
+      showID: true,
+      title: '',
+      pageIndex: 1,
+      pageSize: 10,
+      totalPage: 0,
+      dataListLoading: false
+    }
+  },
+  filters: {
+    timeFormater (value) {
+      // console.log('@', value)
+      var date = new Date(value)
+      let years = date.getFullYear()
+      let month = (date.getMonth() + 1) > 10 ? date.getMonth() + 1 : '0' + (date.getMonth() + 1)
+      let day = (date.getDate() >= 10) ? date.getDate() : '0' + date.getDate()
+      let hours = (date.getHours() >= 10) ? date.getHours() : '0' + date.getHours()
+      let minutes = (date.getMinutes() >= 10) ? date.getMinutes() : '0' + date.getMinutes()
+      let seconds = (date.getSeconds() >= 10) ? date.getSeconds() : '0' + date.getSeconds()
+      if (value) {
+        return years + '-' + month + '-' + day +
+          ' ' + hours + ':' + minutes + ':' + seconds
+      } else {
+        return 'N/A'
+      }
+    }
+  },
+  methods: {
+    init (info) {
+      this.visible = true
+      this.info = info
+      this.title = '结果 : ' + info.jobName
+      this.dataList = []
+      this.useDataList = []
+      this.getJobRes()
+      this.pageIndex = 1
+      this.pageSize = 10
+      this.totalPage = 0
+      // console.log(info)
+    },
+    getJobRes () {
+      this.dataListLoading = true
+      this.useDataList = []
+      this.$http({
+        url: this.$http.snoopUrl('/v1/metrics/values'),
+        methods: 'get',
+        params: this.$http.adornParams({
+          'offset': (this.pageIndex - 1) * this.pageSize,
+          'size': this.pageSize + 1,
+          'metricName': this.info.jobName
+        })
+      }).then((data) => {
+        if (data.data.length && data.status === 200) {
+          this.showID = true
+          this.dataList = data.data
+          for (const item of this.dataList) {
+            item.value['time'] = item.tmst
+            for (let key in item.value) {
+              if (typeof (item.value[key]) !== 'object') {
+                item.value[key].toString()
+              } else {
+                const keysplit = key.split('-')
+                let records = ''
+                let record
+                for (const i in item.value[key]) {
+                  let name, count
+                  for (const category in item.value[key][i]) {
+                    if (category !== 'count') {
+                      name = item.value[key][i][category]
+                      count = item.value[key][i].count
+                    }
+                  }
+                  record = ' (' + name + ',' + count + ') '
+                  records += record
+                }
+                delete item.value[key]
+                key = key + ' (' + keysplit[0].split('_')[0] + ', count)'
+                item.value[key] = records
+              }
+            }
+            this.useDataList.push(item.value)
+          }
+          // console.log(this.dataList)
+          // this.useDataList = this.dataList
+          // this.dataList.forEach((x) => {
+          //   console.log(x)
+          //   this.useDataList.push(x.value)
+          // })
+          // // console.log(this.dataList[0].value)
+          this.tableClo = Object.keys(this.dataList[0].value)
+          this.tableClo.forEach((data, index) => {
+            if (data === 'time') {
+              this.tableClo.splice(index, 1)
+            }
+          })
+          this.dataListLoading = false
+          this.$nextTick(() => {
+            this.haveNextPage()
+          })
+          // console.log(this.tableClo)
+        } else {
+          this.tableClo = []
+          this.showID = false
+          this.dataListLoading = false
+        }
+      })
+      // this.dataList = [
+      //   {
+      //     'name': 'demo3',
+      //     'tmst': 1642670565000,
+      //     'value': {
+      //       'id_count': 6375000,
+      //       'id_max': 124,
+      //       'age_max': 2000,
+      //       'age_min': 1
+      //     }
+      //   },
+      //   {
+      //     'name': 'demo3',
+      //     'tmst': 1642670550000,
+      //     'value': {
+      //       'id_count': 6375000,
+      //       'id_max': 124,
+      //       'age_max': 2000,
+      //       'age_min': 1
+      //     }
+      //   }]
+    },
+    // 每页数
+    sizeChangeHandle (val) {
+      this.pageSize = val
+      this.pageIndex = 1
+      this.getJobRes()
+    },
+    // 当前页
+    currentChangeHandle (val) {
+      this.pageIndex = val
+      this.getJobRes()
+    },
+    /** 判断是否还有下一页
+     *  思路 : 每次请求 pageSize +1 判断实际收到的数组长度
+     */
+    haveNextPage () {
+      if (this.useDataList.length > this.pageSize) {
+        this.totalPage = (this.pageIndex - 1) * this.pageSize + this.useDataList.length
+        this.useDataList.pop()
+      }
+    }
+  }
+}
+</script>
+
+<style scoped>
+
+</style>

+ 194 - 0
src/views/modules/snoop/jobResult_visi.vue

@@ -0,0 +1,194 @@
+<template>
+  <div>
+    <el-dialog
+      title= '结果 : '
+      :close-on-click-modal="false"
+      v-if="visible"
+      :visible.sync="visible"
+      width="75%">
+      <div  v-loading="dataListLoading" >
+        <div id = 'showResult'></div>
+      </div>
+      <div style="text-align: center">
+        <span style="">{{title  }} :    </span><el-select v-model="selectValue" placeholder="请选择" size="mini">
+        <el-option
+          v-for="item in tableClo"
+          :key="item"
+          :label="item"
+          :value="item">
+        </el-option>
+      </el-select>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+// 引入 AutV G2 npm install @antv/g2
+import { Chart } from '@antv/g2'
+
+export default {
+  name: 'jobResult',
+  data () {
+    return {
+      dataList: [],
+      visiDataMap: {},
+      tableClo: [],
+      visible: true,
+      info: null,
+      chart: null,
+      title: '',
+      selectValue: '',
+      dataListLoading: false
+    }
+  },
+  watch: {
+    selectValue:
+    {
+      immediate: false, // 初始化时让handler调用一下
+      handler (newValue, oldValue) {
+        this.dataListLoading = true
+        console.log(this.selectValue)
+        this.chart.data(this.visiDataMap[this.selectValue])
+        this.chart.render()
+        this.dataListLoading = false
+      }
+    }
+  },
+  methods: {
+    init (info) {
+      this.visible = true
+      this.info = info
+      this.title = info.jobName
+      this.dataList = []
+      this.tableClo = []
+      this.visiDataMap = {}
+      this.chart = null
+      this.getJobRes()
+      // console.log(info)
+    },
+    getJobRes () {
+      this.dataListLoading = true
+      this.visiDataMap = {}
+      var visiData = {}
+      this.$http({
+        url: this.$http.snoopUrl('/v1/metrics/values'),
+        methods: 'get',
+        params: this.$http.adornParams({
+          'offset': 0,
+          'size': 100,
+          'metricName': this.info.jobName
+        })
+      }).then((data) => {
+        if (data.data.length && data.status === 200) {
+          this.dataList = data.data
+          let fristSign = true
+          for (const item of this.dataList) {
+            let time = this.timeFormater(item.tmst)
+            for (let key in item.value) {
+              if (fristSign) {
+                this.visiDataMap[key] = []
+              }
+              if (typeof (item.value[key]) !== 'object') {
+                visiData = {
+                  'time': time,
+                  'value': item.value[key].toString()
+                }
+                this.visiDataMap[key].push(visiData)
+              } else {
+                for (const i in item.value[key]) {
+                  let name, count
+                  for (const category in item.value[key][i]) {
+                    if (category !== 'count') {
+                      name = item.value[key][i][category]
+                      count = item.value[key][i].count
+                    }
+                  }
+                  visiData = {
+                    'time': time,
+                    'name': name,
+                    'value': count
+                  }
+
+                  this.visiDataMap[key].push(visiData)
+                }
+              }
+            }
+            fristSign = false
+          }
+          this.tableClo = Object.keys(this.dataList[0].value)
+          this.selectValue = this.tableClo[0]
+
+          this.charInit(this.visiDataMap[this.selectValue])
+          this.dataListLoading = false
+          // console.log(this.tableClo)
+        } else {
+          this.tableClo = []
+          this.dataListLoading = false
+        }
+      })
+    },
+    timeFormater (value) {
+      // console.log('@', value)
+      var date = new Date(value)
+      // let years = date.getFullYear()
+      // let month = (date.getMonth() + 1) > 10 ? date.getMonth() + 1 : '0' + (date.getMonth() + 1)
+      // let day = (date.getDate() >= 10) ? date.getDate() : '0' + date.getDate()
+      let hours = (date.getHours() >= 10) ? date.getHours() : '0' + date.getHours()
+      let minutes = (date.getMinutes() >= 10) ? date.getMinutes() : '0' + date.getMinutes()
+      let seconds = (date.getSeconds() >= 10) ? date.getSeconds() : '0' + date.getSeconds()
+      if (value) {
+        // return years + '-' + month + '-' + day + '' + hours + ':' + minutes + ':' + seconds
+        return hours + ':' + minutes + ':' + seconds
+      } else {
+        return 'N/A'
+      }
+    },
+    charInit (data) {
+      console.log(this.selectValue)
+      this.chart = new Chart({
+        container: 'showResult',
+        autoFit: true,
+        height: 500,
+        padding: [50, 20, 50, 20]
+      })
+      // data.forEach(x => {
+      //   x['value'] = x['value'] / 100000
+      // })
+      this.chart.data(data)
+      this.chart.scale({
+        time: {
+          tickCount: 10
+        },
+        value: {
+          nice: true
+        }
+      })
+      this.chart.scale({
+        time: {
+          tickCount: 10
+        },
+        value: {
+          nice: true,
+          tickCount: 10
+        }
+      })
+      this.chart.axis('value', {
+        tickLine: null,
+        label: {
+          autoRotate: false,
+          autoHide: false // 取消自动隐藏label
+        }
+      })
+      this.chart.line().position('time*value')
+
+      this.chart.render()
+      // this.chart.interval().position('time*value')
+    }
+  }
+}
+</script>
+
+<style scoped>
+
+</style>

+ 298 - 0
src/views/modules/snoop/jobResult_visi_echars.vue

@@ -0,0 +1,298 @@
+<template>
+  <div>
+    <el-dialog
+      :close-on-click-modal="false"
+      v-if="visible"
+      :visible.sync="visible"
+      width="75%"
+      destroy-on-close>
+      <div  v-loading="dataListLoading" >
+
+        <el-row :gutter="20">
+          <el-col :span="24">
+            <el-card>
+              <div v-show="!showCiyun" id="jobresultshow" style="min-height: 400px;">
+                暂无数据
+              </div>
+              <div  v-show="showCiyun" id="jobresultshowCiYun" style="min-height: 400px;">
+                暂无数据
+              </div>
+            </el-card>
+          </el-col>
+          <el-col :span="24">
+              <div style="text-align: center;margin-top: 20px">
+                <span style="">{{title  }} :    </span><el-select v-model="selectValue" placeholder="请选择" size="mini">
+                <el-option
+                  v-for="item in tableClo"
+                  :key="item"
+                  :label="item"
+                  :value="item">
+                </el-option>
+              </el-select>
+              </div>
+          </el-col>
+        </el-row>
+      </div>
+
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import echarts from 'echarts'
+// cnpm install echarts-wordcloud@1.1.3 --save
+import 'echarts-wordcloud/dist/echarts-wordcloud.min'
+export default {
+  name: 'jobResult',
+  data () {
+    return {
+      dataList: [],
+      visiDataMap: {},
+      tableClo: [],
+      visible: true,
+      info: null,
+      title: '',
+      selectValue: '-1',
+      dataListLoading: false,
+      showCiyun: false,
+      chartLine: null,
+      charWordCloud: null
+    }
+  },
+  watch: {
+    selectValue:
+    {
+      immediate: false, // 初始化时让handler调用一下
+      handler (newValue, oldValue) {
+        if (oldValue !== '-1') {
+          this.dataListLoading = true
+          this.charDecisionTree(newValue)
+          this.dataListLoading = false
+        }
+      }
+    }
+  },
+  methods: {
+    init (info) {
+      this.visible = true
+      this.info = info
+      this.title = info.jobName
+      this.dataList = []
+      this.tableClo = []
+      this.visiDataMap = {}
+      this.getJobRes()
+      // console.log(info)
+    },
+    getJobRes () {
+      this.dataListLoading = true
+      this.visiDataMap = {}
+      var visiData = {}
+      this.$http({
+        url: this.$http.snoopUrl('/v1/metrics/values'),
+        methods: 'get',
+        params: this.$http.adornParams({
+          'offset': 0,
+          'size': 100,
+          'metricName': this.info.jobName
+        })
+      }).then((data) => {
+        if (data.data.length && data.status === 200) {
+          this.dataList = data.data
+          let fristSign = true
+          for (const item of this.dataList) {
+            let time = this.timeFormater(item.tmst)
+            for (let key in item.value) {
+              if (fristSign) {
+                this.visiDataMap[key] = []
+              }
+              if (typeof (item.value[key]) !== 'object') {
+                visiData = {
+                  'time': time,
+                  'value': item.value[key].toString()
+                }
+                this.visiDataMap[key].push(visiData)
+              } else {
+                for (const i in item.value[key]) {
+                  let name, count
+                  for (const category in item.value[key][i]) {
+                    if (category !== 'count') {
+                      name = item.value[key][i][category]
+                      count = item.value[key][i].count
+                    }
+                  }
+                  visiData = {
+                    'time': time,
+                    'name': name,
+                    'value': count
+                  }
+
+                  this.visiDataMap[key].push(visiData)
+                }
+              }
+            }
+            fristSign = false
+          }
+          this.tableClo = Object.keys(this.dataList[0].value)
+          this.selectValue = this.tableClo[0]
+          this.dataListLoading = false
+          // console.log(this.tableClo)
+        } else {
+          this.tableClo = []
+          this.dataListLoading = false
+        }
+        this.$nextTick(() => {
+          this.charDecisionTree(this.selectValue)
+        })
+      })
+    },
+    timeFormater (value) {
+      // console.log('@', value)
+      var date = new Date(value)
+      // let years = date.getFullYear()
+      // let month = (date.getMonth() + 1) > 10 ? date.getMonth() + 1 : '0' + (date.getMonth() + 1)
+      // let day = (date.getDate() >= 10) ? date.getDate() : '0' + date.getDate()
+      let hours = (date.getHours() >= 10) ? date.getHours() : '0' + date.getHours()
+      let minutes = (date.getMinutes() >= 10) ? date.getMinutes() : '0' + date.getMinutes()
+      let seconds = (date.getSeconds() >= 10) ? date.getSeconds() : '0' + date.getSeconds()
+      if (value) {
+        // return years + '-' + month + '-' + day + '' + hours + ':' + minutes + ':' + seconds
+        return hours + ':' + minutes + ':' + seconds
+      } else {
+        return 'N/A'
+      }
+    },
+    charDecisionTree (cloum) {
+      if (cloum.search('top10') === -1) {
+        this.showCiyun = false
+        this.initChartLine(cloum)
+      } else {
+        this.showCiyun = true
+        this.$nextTick(() => {
+          this.initCharWordCloud(cloum)
+        })
+      }
+    },
+    // 折线图
+    initChartLine (cloum) {
+      let datas = this.visiDataMap[cloum]
+      // console.log(datas)
+      if (datas && cloum !== '-1') {
+        let xdata = []
+        let ydata = []
+        datas.map((data) => {
+          xdata.push(data['time'])
+          ydata.push(data['value'])
+        })
+        var option = {
+          title: {
+            text: this.title + ':' + this.selectValue
+          },
+          tooltip: {
+            trigger: 'axis'
+          },
+          // legend: {
+          //   data: ['邮件营销', '联盟广告', '视频广告', '直接访问', '搜索引擎']
+          // },
+          grid: {
+            left: '3%',
+            right: '4%',
+            bottom: '3%',
+            containLabel: true
+          },
+          toolbox: {
+            feature: {
+              saveAsImage: {}
+            }
+          },
+          xAxis: {
+            type: 'category',
+            boundaryGap: false,
+            data: xdata.reverse()
+          },
+          yAxis: {
+            type: 'value'
+          },
+          series: [
+            {
+              name: 'value',
+              type: 'line',
+              stack: '总量',
+              data: ydata.reverse()
+            }
+          ]
+        }
+        this.chartLine = echarts.init(document.getElementById('jobresultshow'))
+        this.chartLine.setOption(option)
+        // window.addEventListener('resize', () => {
+        //   this.chartLine.resize()
+        // })
+      }
+    },
+    // 词云
+    initCharWordCloud (cloum) {
+      let datas = this.visiDataMap[cloum]
+      if (datas && cloum !== '-1') {
+        var option = {
+          title: {
+            text: this.title + ':' + this.selectValue
+          },
+          tooltip: {
+            show: true,
+            position: 'top',
+            textStyle: {
+              fontSize: 30
+            }
+          },
+          series: [{
+            type: 'wordCloud',
+           // 用来调整词之间的距离
+            gridSize: 30,
+           // 用来调整字的大小范围
+
+            sizeRange: [14, 60],
+           // 用来调整词的旋转方向,,[0,0]--代表着没有角度,也就是词为水平方向,需要设置角度参考注释内容
+           // rotationRange: [-45, 0, 45, 90],
+           // rotationRange: [ 0,90],
+            rotationRange: [0, 0],
+           // 随机生成字体颜色
+            textStyle: {
+              normal: {
+                color: function () {
+                  return (
+                   'rgb(' +
+                   Math.round(Math.random() * 255) +
+                   ', ' +
+                   Math.round(Math.random() * 255) +
+                   ', ' +
+                   Math.round(Math.random() * 255) +
+                   ')'
+                  )
+                }
+              }
+            },
+           // 位置相关设置
+            left: 'center',
+            top: 'center',
+            right: null,
+            bottom: null,
+            width: '200%',
+            height: '200%',
+           // 数据
+            data: datas.slice(0, 10)
+          }]
+        }
+        this.charWordCloud = echarts.init(document.getElementById('jobresultshowCiYun'))
+        this.charWordCloud.setOption(option)
+      }
+
+      // window.addEventListener('resize', () => {
+      //   this.charWordCloud.resize()
+      // })
+    }
+  }
+}
+</script>
+
+<style scoped>
+
+</style>

+ 106 - 0
src/views/modules/snoop/jobWatch.vue

@@ -0,0 +1,106 @@
+<template>
+  <div>
+
+
+
+    <el-dialog :title="'查看任务'" :close-on-click-modal="false" :visible.sync="visible">
+
+      <el-form :model="job_info" label-width="200px"  v-loading="jobDataListLoading">
+        <el-form-item label="任务名称 :" prop="name">
+          <!--                  <el-input v-model="goal_info.config.name"></el-input>-->
+          <span>{{ job_info.jobName }}</span>
+        </el-form-item>
+        <el-form-item label="度量名称 :">
+          <span>{{ job_info.measureName }}</span>
+          <!--                  <el-input v-model="goal_info.config.description"></el-input>-->
+        </el-form-item>
+        <el-form-item label="度量类型 :">
+          <span>{{ job_info.measureType }}</span>
+        </el-form-item>
+
+        <el-form-item label="处理方式 :">
+          <span>{{ job_info.processType }}</span>
+        </el-form-item>
+        <el-form-item label="探测周期 :">
+          <span>{{ job_info.cronExpression }}</span>
+      </el-form-item>
+        <el-form-item label="时  区 :">
+          <span>{{ job_info.cronTimeZone }}</span>
+        </el-form-item>
+        <el-form-item label="单次探测起始时间 :">
+          <span>{{ job_info.rangeConfig.begin}}</span>
+      </el-form-item>
+        <el-form-item label="单次探测持续时间 :">
+          <span>{{ job_info.rangeConfig.length }}</span>
+        </el-form-item>
+      </el-form>
+
+
+      <span slot="footer" class="dialog-footer">
+      <el-button @click="visible = false">取消</el-button>
+      <el-button type="primary" @click="visible=false">确定</el-button>
+    </span>
+    </el-dialog>
+
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'jobWatch',
+  data () {
+    return {
+      job_info: {
+        jobName: '',
+        measureName: '',
+        measureType: '',
+        processType: '',
+        cronExpression: '',
+        cronTimeZone: '',
+        rangeConfig: ''
+      },
+      visible: false,
+      jobDataListLoading: false
+    }
+  },
+  methods: {
+    init (info) {
+      this.visible = true
+      this.jobDataListLoading = false
+      this.getJobInfo(info)
+      // console.log(info)
+    },
+    getJobInfo (info) {
+      this.job_info = info
+      const mesureId = info['measureId']
+      this.getMeasureById(mesureId)
+      for (const item of info['dataSegments']) {
+        // console.log(item['segment.range'])
+        this.job_info.rangeConfig = item['segment.range']
+      }
+    },
+    getMeasureById (id) {
+      this.jobDataListLoading = true
+      this.$http({
+        url: this.$http.snoopUrl('/v1/measures/') + id,
+        methods: 'get'
+      }).then((data) => {
+        if (data && data.status === 200) {
+          var measureData = data.data
+          this.job_info.measureName = measureData.name
+          this.job_info.measureType = measureData['dq.type'].toLowerCase()
+          this.job_info.processType = measureData['process.type'].toLowerCase()
+        }
+        this.jobDataListLoading = false
+      }
+
+        )
+    }
+
+  }
+}
+</script>
+
+<style scoped>
+
+</style>

+ 965 - 0
src/views/modules/snoop/measure.vue

@@ -0,0 +1,965 @@
+<!--  -->
+<template>
+  <div class=''>
+    <el-breadcrumb class="divi2" separator-class="el-icon-arrow-right">
+      <el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
+      <el-breadcrumb-item :to="{ path: '/snoop-home'}">数据质量探测</el-breadcrumb-item>
+      <el-breadcrumb-item>创建度量标准</el-breadcrumb-item>
+    </el-breadcrumb>
+    <el-divider class="divi"></el-divider>
+
+    <el-steps :active="active" align-center finish-status="success" style="margin: 50px 20px 0px 10px;">
+      <el-step title="选择目标" description="选择需要度量的目标数据集字段"></el-step>
+      <el-step title="定义/选择模型" description="定义将应用于所选字段的语法检查逻辑"></el-step>
+      <el-step title="分区配置" description="设置目标数据集的分区配置"></el-step>
+      <el-step title="完成" description="设置模型的基本配置"></el-step>
+    </el-steps>
+
+
+    <div style=" margin: 10px 120px 0px 166px;height: 420px;">
+      <el-row :gutter="50">
+        <div v-if="active == 0">
+          <el-col :span="8" style="height: 100% ">
+            <h4>1.1 选择数据源</h4>
+            <div style="height: 360px;border: 1px solid rgb(0, 0, 0);overflow: scroll; ">
+              <div style="margin: 10px;"> <!-- 控制左边树形区域的下方的div -->
+                <el-tree
+                  v-if="showTree"
+                  id='tree'
+                  node-key="subEquipmentid"
+                  :props="defaultProps"
+                  ref="tree"
+                  :load="loadTreeNode"
+                  lazy
+                  @node-click="treeNodeClick">
+                <span class="custom-tree-node" slot-scope="{ node, data }">
+                  <span>
+                      <i :class="data.icon" style="margin-right: 4px"></i>{{ node.label }}
+                  </span>
+               </span>
+                </el-tree>
+              </div>
+            </div>
+          </el-col>
+          <el-col :span="16" style="height: 100%">
+            <h4>1.2 选择字段</h4>
+            <div style="height: 360px;border: 1px solid rgb(0, 0, 0) ;padding: 10px;overflow-scrolling: auto">
+              <el-table
+                ref="multipleTable"
+                :data="tableData"
+                tooltip-effect="dark"
+                style="width: 100%"
+                @selection-change="handleSelectionChange">
+                <el-table-column
+                  type="selection"
+                  width="55">
+                </el-table-column>
+                <el-table-column
+                  prop="colname"
+                  label="列名"
+                  width="120">
+                </el-table-column>
+                <el-table-column
+                  prop="type"
+                  label="类型"
+                  width="120">
+                </el-table-column>
+                <el-table-column
+                  prop="comment"
+                  label="备注"
+                  show-overflow-tooltip>
+                </el-table-column>
+              </el-table>
+            </div>
+          </el-col>
+        </div>
+
+        <div v-if="active == 1">
+          <el-col :span="16" style="height: 100%;margin-left: 160px;">
+            <h4>2. 请选择下列其中一种分析模式 :</h4>
+            <div style="height: 360px;border: 1px solid rgb(0, 0, 0) ;padding: 10px;overflow-scrolling: auto">
+              <el-table
+                :data="goal_info.chooseCloum"
+                style="width: 100%">
+                <el-table-column prop="colname" label="列名" width="120"></el-table-column>
+                <el-table-column prop="type" label="类型" width="120"></el-table-column>
+                <el-table-column prop="comment" label="rule" show-overflow-tooltip>
+                  <template slot="header" slot-scope="scope">
+                    <span>rule</span>
+                    <i class="el-icon-info"
+                       :class="isShowRules"
+                       @mouseover="isShowRules.showRules = true"
+                       @mouseleave="isShowRules.showRules = false"
+                       @click="showrule"
+                    ></i>
+                  </template>
+
+<!--                  <template slot="header">-->
+
+<!--                    <i class="el-icon-info"-->
+<!--                       @mouseover="isShowRules.showRules = true"-->
+<!--                       @mouseleave="isShowRules.showRules = false"-->
+<!--                       @click="showrule"></i>-->
+<!--                  </template>-->
+
+                  <template slot-scope="scope" style="width: 80%">
+                    <!--                                        <el-button type="text" size="small" @click="userwatch(scope)">查看-->
+                    <!--                                        </el-button>-->
+
+                    <el-select
+                      v-model="scope.row.rule"
+                      multiple
+                      filterable
+                      style="width: 80%"
+                      placeholder="请选择">
+                      <el-option-group
+                        v-for="group in scope.row.dropdownList"
+                        :key="group.label"
+                        :label="group.label"
+
+                      >
+                        <el-option
+                          v-for="item in group.options"
+                          :key="item.value"
+                          :label="item.label"
+                          :value="item.value">
+                        </el-option>
+                      </el-option-group>
+
+                    </el-select>
+                  </template>
+                </el-table-column>
+              </el-table>
+            </div>
+          </el-col>
+        </div>
+
+        <div v-if="active == 2">
+          <el-col :span="16" style="height: 100%;margin-left: 160px;">
+            <h4>3. 配置信息 :</h4>
+            <div style="height: 360px;overflow-scrolling: auto">
+              <h5>度量配置 : </h5>
+              <el-form ref="form" :model="datacForm" label-width="100px" :rules="rules">
+                <el-form-item label="度量名称 :" prop="name">
+                  <el-input v-model="datacForm.name"></el-input>
+                </el-form-item>
+                <el-form-item label="度量描述 :">
+                  <el-input v-model="datacForm.description"></el-input>
+                </el-form-item>
+
+                <h5>数据源配置 : </h5>
+                <el-form-item label="查询条件 :">
+                  <el-input v-model="datacForm.where"></el-input>
+                </el-form-item>
+                <el-form-item label="分区大小 :">
+                  <el-input-number v-model="datacForm.num" controls-position="right" :min="0"></el-input-number>
+                  <el-select v-model="datacForm.timetype" placeholder="请选择">
+                    <el-option label="day" value="day"></el-option>
+                    <el-option label="hour" value="hour"></el-option>
+                    <el-option label="minute" value="minute"></el-option>
+                  </el-select>
+                </el-form-item>
+                <el-form-item label="时 区 :">
+                  <el-select v-model="datacForm.timezone" placeholder="请选择">
+                    <el-option
+                      v-for="item in timezones"
+                      :key="item.value"
+                      :label="item.label"
+                      :value="item.value">
+                    </el-option>
+                  </el-select>
+
+                </el-form-item>
+              </el-form>
+            </div>
+          </el-col>
+        </div>
+
+        <div v-if="active == 3">
+          <el-col :span="16" style="height: 100%;margin-left: 160px;">
+            <h4>4. 信息校对 :</h4>
+            <div style="height: 360px;overflow-scrolling: auto">
+
+              <el-form ref="measureform" :model="goal_info" label-width="100px" :rules="rules">
+                <el-form-item label="度量名称 :" prop="name">
+                  <!--                  <el-input v-model="goal_info.config.name"></el-input>-->
+                  <span>{{ goal_info.config.name }}</span>
+                </el-form-item>
+                <el-form-item label="度量描述 :">
+                  <span>{{ goal_info.config.description }}</span>
+                  <!--                  <el-input v-model="goal_info.config.description"></el-input>-->
+                </el-form-item>
+                <el-form-item label="数据源 :">
+                  <span>{{ goal_info.equipment.name }}</span>
+                  <!--                  <el-input v-model="goal_info.equipment.name"></el-input>-->
+                </el-form-item>
+                <!--                <el-form-item label="查询条件 :">-->
+                <!--                  <span>{{goal_info.config.where}}</span>-->
+                <!--&lt;!&ndash;                  <el-input v-model="goal_info.config.where"></el-input>&ndash;&gt;-->
+                <!--                </el-form-item>-->
+                                <el-form-item label="分区信息 :">
+                                  <span>{{goal_info.config.num  + "  " + goal_info.config.timetype + " " + goal_info.config.timezone}}</span>
+<!--                                  <el-input v-model="goal_info.config.num" >{{goal_info.config.num + goal_info.config.timetype}}</el-input>-->
+<!--                                  <el-input v-model="goal_info.config.timezone"></el-input>-->
+                                </el-form-item>
+                <el-form-item label="度量规则 :">
+                  <!--                  <el-input-number v-model="datacForm.num" controls-position="right" :min="0"></el-input-number>-->
+                  <div style="height: 100px;overflow: auto">
+                    <template v-for="rule in  goal_info.chooseCloum">
+                      <li>{{ rule.colname }} : {{ rule.rule }}</li>
+                    </template>
+
+                    <!--    <template v-for="rule in  timezones" >-->
+                    <!--      <li>{{rule.label}} : {{rule.value}}</li>-->
+                    <!--    </template>-->
+                  </div>
+                </el-form-item>
+              </el-form>
+            </div>
+          </el-col>
+        </div>
+      </el-row>
+
+
+    </div>
+    <el-form :inline="true">
+      <el-form-item style="float:left">
+        <el-button type="primary" @click="preStey()" :disabled = bottonDisable.pre>上一步</el-button>
+      </el-form-item>
+      <el-form-item style="float:right">
+        <el-button v-if="!buttonFinish" ref="buttonFinish" type="primary" @click="next()" :disabled = bottonDisable.next>下一步</el-button>
+        <el-button v-if="buttonFinish" type="primary" @click="submitForm()" >完成</el-button>
+      </el-form-item>
+    </el-form>
+
+    <show-rules v-if="isShowRulesDrog" ref="ShowRulesDrogref"></show-rules>
+  </div>
+</template>
+
+<script>
+// 这里可以导入其他文件(比如:组件,工具js,第三方插件js,json文件,图片文件等等)
+// 例如:import 《组件名称》 from '《组件路径》';
+import showRules from './showRules'
+import { MessageBox } from 'element-ui'
+import { Message } from "element-ui"
+
+export default {
+  created () {
+
+  },
+  components: {
+    showRules
+  },
+  data () {
+    return {
+      value: [],
+      showTree: true,
+      visible: false,
+      chooseEqpment: '',
+      active: 0,
+      goal_info: '',
+      userID: this.$store.state.user.id, // 用户编号
+      // userName: this.$store.state.user.name, // 用户编号
+      userName: 'test', // 用户编号
+      isShowRules: {
+        showRules: false
+      },
+
+      transrule: [],
+      transenumrule: [],
+      transnullrule: [],
+      transregexrule: [],
+      newMeasure: {},
+      rulesDesc: [],
+
+      buttonFinish: false,
+      bottonDisable: {
+        pre: true,
+        next: true
+      },
+      rules: {
+        name: [
+          {required: true, message: '请输入度量名称', trigger: 'blur'},
+          {min: 3, max: 18, message: '长度在 3 到 18 个字符', trigger: 'blur'}
+        ]
+      },
+      isShowRulesDrog: false,
+      datacForm: {
+        name: '',
+        description: '',
+        where: '',
+        timezone: '',
+        num: 1,
+        timetype: 'day',
+        needpath: false,
+        path: ''
+      },
+      options_int: [{
+        label: 'Simple Statistics',
+        options: [{
+          id: 1,
+          value: 'Null Count',
+          label: 'Null Count'
+        }, {
+          id: 2,
+          value: 'Distinct Count',
+          label: 'Distinct Count'
+        }]
+      }, {
+        label: 'Summary Statistics',
+        options: [{
+          id: 3,
+          value: 'Total Count',
+          label: 'Total Count'
+        }, {
+          id: 4,
+          value: 'Maximum',
+          label: 'Maximum'
+        }, {
+          id: 5,
+          value: 'Minimum',
+          label: 'Minimum'
+        }, {
+          id: 6,
+          value: 'Average',
+          label: 'Average'
+        }]
+      }, {
+        label: 'Advanced Statistics',
+        options: [{
+          id: 7,
+          value: 'Enum Detection Top10 Count',
+          label: 'Enum Detection Top10 Count'
+        }]
+      }
+      ],
+      options_str: [{
+        label: 'Simple Statistics',
+        options: [{
+          id: 1,
+          value: 'Null Count',
+          label: 'Null Count'
+        }, {
+          id: 2,
+          value: 'Distinct Count',
+          label: 'Distinct Count'
+        }]
+      }, {
+        label: 'Summary Statistics',
+        options: [{
+          id: 3,
+          value: 'Total Count',
+          label: 'Total Count'
+        }]
+      }, {
+        label: 'Advanced Statistics',
+        options: [{
+          id: 9,
+          value: 'Enum Detection Top10 Count',
+          label: 'Enum Detection Top10 Count'
+        }]
+      }
+      ],
+      treedata: [{ // 左侧默认树数据'
+        icon: 'el-icon-success',
+        name: '煤矿',
+        limit: '',
+        children: [{
+          name: '系统',
+          limit: '',
+          children: [{
+            name: '子系统',
+            limit: '',
+            children: [{
+              name: '设备',
+              limit: '',
+              children: [{
+
+                name: '子设备',
+                limit: ''
+              }]
+            }]
+          }]
+        }]
+      }, {
+        name: '系统666',
+        limit: '',
+        children: [{
+          name: '设备2',
+          limit: ''
+        }]
+      }],
+      defaultProps: {
+        children: 'children',
+        label: 'name',
+        isLeaf: 'leaf'
+      },
+      tableData: [],
+      timezones: [
+        {label: 'UTC-12(IDL)', value: 'GMT-12'},
+        {label: 'UTC-11(MIT)', value: 'GMT-11'},
+        {label: 'UTC-10(HST)', value: 'GMT-10'},
+        {label: 'UTC-9:30(MSIT)', value: 'GMT-9:30'},
+        {label: 'UTC-9(AKST)', value: 'GMT-9'},
+        {label: 'UTC-8(PST)', value: 'GMT-8'},
+        {label: 'UTC-7(MST)', value: 'GMT-7'},
+        {label: 'UTC-6(CST)', value: 'GMT-6'},
+        {label: 'UTC-5(EST)', value: 'GMT-5'},
+        {label: 'UTC-4(AST)', value: 'GMT-4'},
+        {label: 'UTC-3:30(NST)', value: 'GMT-3:30'},
+        {label: 'UTC-3(SAT)', value: 'GMT-3'},
+        {label: 'UTC-2(BRT)', value: 'GMT-2'},
+        {label: 'UTC-1(CVT)', value: 'GMT-1'},
+        {label: 'UTC(WET,GMT)', value: 'GMT'},
+        {label: 'UTC+1(CET)', value: 'GMT+1'},
+        {label: 'UTC+2(EET)', value: 'GMT+2'},
+        {label: 'UTC+3(MSK)', value: 'GMT+3'},
+        {label: 'UTC+3:30(IRT)', value: 'GMT+3:30'},
+        {label: 'UTC+4(META)', value: 'GMT+4'},
+        {label: 'UTC+4:30(AFT)', value: 'GMT+4:30'},
+        {label: 'UTC+5(METB)', value: 'GMT+5'},
+        {label: 'UTC+5:30(IDT)', value: 'GMT+5:30'},
+        {label: 'UTC+5:45(NPT)', value: 'GMT+5:45'},
+        {label: 'UTC+6(BHT)', value: 'GMT+6'},
+        {label: 'UTC+6:30(MRT)', value: 'GMT+6:30'},
+        {label: 'UTC+7(IST)', value: 'GMT+7'},
+        {label: 'UTC+8(EAT)', value: 'GMT+8'},
+        {label: 'UTC+8:30(KRT)', value: 'GMT+8:30'},
+        {label: 'UTC+9(FET)', value: 'GMT+9'},
+        {label: 'UTC+9:30(ACST)', value: 'GMT+9:30'},
+        {label: 'UTC+10(AEST)', value: 'GMT+10'},
+        {label: 'UTC+10:30(FAST)', value: 'GMT+10:30'},
+        {label: 'UTC+11(VTT)', value: 'GMT+11'},
+        {label: 'UTC+11:30(NFT)', value: 'GMT+11:30'},
+        {label: 'UTC+12(PSTB)', value: 'GMT+12'},
+        {label: 'UTC+12:45(CIT)', value: 'GMT+12:45'},
+        {label: 'UTC+13(PSTC)', value: 'GMT+13'},
+        {label: 'UTC+14(PSTD)', value: 'GMT+14'}
+      ]
+
+    }
+  },
+  methods: {
+
+    next () {
+      // if (this.active++ > 2) this.active = 0
+      this.active++
+      switch (this.active) {
+        case 0 :
+          // console.log('000')
+          break
+        case 1 :
+          this.bottonDisable.pre = false
+          break
+        case 2 :
+          break
+        case 3 :
+          this.goal_info.config = this.datacForm
+          this.buttonFinish = true
+          // console.info(this.$refs.buttonFinish)
+          break
+        default :
+          // console.log('000')
+      }
+    },
+    preStey () {
+      // if (this.active-- < 0) this.active = 3
+      this.active--
+      this.buttonFinish = false
+      if (this.active <= 0) {
+        this.bottonDisable.pre = true
+        this.bottonDisable.next = true
+      }
+    },
+    treeNodeClick (data, node) {
+      this.tableData = []
+      if (data.limit === 'children') {
+        // node.data.icon = 'iconfont icon-xitong4'
+        this.chooseEqpment = data
+        console.log(this.chooseEqpment)
+        // 进行ajax 请求
+
+        // table = this.chooseEqpment.hbaseTableName
+        var info = {
+          db: 'db=default',
+          table: 'table=demo_src'
+        }
+        this.$http({
+          url: this.$http.snoopUrl('/v1/metadata/hive/table?') + info.db + '&' + info.table,
+          method: 'get'
+        }).then((data) => {
+          if (data.status === 200) {
+            var res = data.data.sd.cols
+            for (const resKey in res) {
+              var table = {
+                colname: res[resKey].name,
+                type: res[resKey].type,
+                comment: res[resKey].comment
+              }
+              this.tableData.push(table)
+            }
+          } else {
+            Message({
+              message: '获取   ' + this.chooseEqpment.name + '   列数据失败',
+              type: 'error'
+            })
+          }
+        })
+        // this.tableData = [{
+        //   colname: 'id',
+        //   type: 'bigint',
+        //   comment: '测试字段1'
+        // }, {
+        //   colname: 'age',
+        //   type: 'int',
+        //   comment: '测试字段2'
+        // }, {
+        //   colname: 'desc',
+        //   type: 'string',
+        //   comment: '测试字段3'
+        // }]
+      }
+    },
+    handleSelectionChange (data) {
+      if (data.length > 0) {
+        this.bottonDisable.next = false
+      } else {
+        this.bottonDisable.next = true
+      }
+      this.goal_info = {
+        equipment: this.chooseEqpment,
+        chooseCloum: data
+      }
+      // chooseCloum.cloum = data
+      var patt = new RegExp('int|double|float/i')
+      if (patt.test(this.type)) {
+        this.isNum = true
+      }
+      for (let da of data) {
+        if (patt.test(da.type)) {
+          da.isNum = true
+          da.dropdownList = this.options_int
+        } else {
+          da.isNum = false
+          da.dropdownList = this.options_str
+        }
+      }
+    },
+    showrule () {
+      this.isShowRulesDrog = true
+      this.$nextTick(() => {
+        this.$refs.ShowRulesDrogref.init()
+      })
+    },
+    // 向后台提交数据
+    async finallySubmit () {
+      this.newMeasure = {
+        'name': this.goal_info.config.name,
+        'measure.type': 'griffin',
+        'dq.type': 'PROFILING',
+        'rule.description': {
+          'details': this.rulesDesc
+        },
+        'process.type': 'BATCH',
+        'owner': this.userName,
+        'description': this.goal_info.config.description,
+        'data.sources': [
+          {
+            'name': 'source',
+            'connector': {
+              'name': 'source' + new Date().getTime(),
+              'type': 'HIVE',
+              'version': '1.2',
+              'data.unit': this.goal_info.config.num + this.goal_info.config.timetype,
+              'data.time.zone': this.goal_info.config.timezone,
+              'config': {
+                // 'database': 'default',
+                // 'table.name': this.goal_info.equipment.hbaseTableName,
+                'database': 'default',
+                'table.name': 'demo_src',
+                'where': this.goal_info.config.where
+              }
+            }
+          }
+        ],
+        'evaluate.rule': {
+          'out.dataframe.name': 'profiling',
+          rules: []
+        }
+      }
+      this.getGrouprule()
+      console.log(666)
+      console.log(this.newMeasure)
+      await this.$http({
+        url: this.$http.snoopUrl('/v1/measures'),
+        method: 'post',
+        data: this.$http.adornData(this.newMeasure)
+      }).then((datas) => {
+        console.log(datas)
+        if (datas.status === 201) {
+          return true
+        } else {
+          return false
+        }
+      })
+    },
+    submitForm () {
+      var submit = this.finallySubmit()
+      setTimeout(() => {
+        if (submit) {
+          Message({
+            message: '度量标准   ' + this.datacForm.name + '   创建成功',
+            type: 'success'
+          })
+        } else {
+          Message({
+            message: '度量标准   ' + this.datacForm.name + '   创建失败',
+            type: 'error'
+          })
+        }
+        this.$router.replace({path: '/snoop-home', query: {'status': '0'}})
+        this.$destroy()
+      }, 2 * 1000)
+    },
+    getGrouprule () {
+      var selected = {name: ''}
+      var value = ''
+      var nullvalue = ''
+      var nullname = ''
+      var enmvalue = ''
+      var regexvalue = ''
+      var regexname = ''
+      var grpname = ''
+      for (const key in this.goal_info.chooseCloum) {
+        selected.name = this.goal_info.chooseCloum[key].colname
+        let info = ''
+        let otherinfo = ''
+        for (let i = 0; i < this.goal_info.chooseCloum[key].rule.length; i++) {
+          const originrule = this.goal_info.chooseCloum[key].rule[i]
+          info = info + originrule + ','
+
+          if (originrule === 'Enum Detection Top10 Count') {
+            enmvalue = this.transferRule(originrule, selected)
+            grpname = `${selected.name}_top10count`
+            this.transenumrule.push(enmvalue)
+            this.pushEnmRule(enmvalue, grpname)
+          } else if (originrule === 'Null Count') {
+            nullvalue = this.transferRule(originrule, selected)
+            nullname = `${selected.name}_nullcount`
+            this.transnullrule.push(nullvalue)
+            this.pushNullRule(nullvalue, nullname)
+          } else if (originrule === 'Empty Count') {
+            nullvalue = this.transferRule(originrule, selected)
+            nullname = `${selected.name}_emptycount`
+            this.transnullrule.push(nullvalue)
+            this.pushNullRule(nullvalue, nullname)
+          } else if (originrule === 'Regular Expression Detection Count') {
+            selected['regex'] = ''
+            regexvalue = this.transferRule(originrule, selected)
+            regexname = `${selected.name}_regexcount`
+            this.transregexrule.push(regexvalue)
+            this.pushRegexRule(regexvalue, regexname)
+          } else {
+            otherinfo = otherinfo + originrule + ','
+            value = this.transferRule(originrule, selected)
+            this.transrule.push(value)
+          }
+        }
+
+        info = info.substring(0, info.lastIndexOf(','))
+        this.rulesDesc.push({
+          name: this.goal_info.chooseCloum[key].colname,
+          infos: info
+        })
+      }
+      if (this.transrule.length !== 0) {
+        this.getRule(this.transrule)
+      }
+    },
+    getRule (trans) {
+      var rule = ''
+      for (let i of trans) {
+        rule = rule + i + ','
+      }
+      rule = rule.substring(0, rule.lastIndexOf(','))
+      this.pushRule(rule)
+    },
+    pushEnmRule (rule, grpname) {
+      this.newMeasure['evaluate.rule'].rules.push({
+        'dsl.type': 'griffin-dsl',
+        'dq.type': 'PROFILING',
+        rule: rule,
+        'out.dataframe.name': grpname,
+        'out': [
+          {
+            'type': 'metric',
+            'name': grpname,
+            'flatten': 'array'
+          }
+        ]
+      })
+    },
+    pushNullRule (rule, nullname) {
+      this.newMeasure['evaluate.rule'].rules.push({
+        'dsl.type': 'griffin-dsl',
+        'dq.type': 'PROFILING',
+        rule: rule,
+        'out.dataframe.name': nullname
+      })
+    },
+
+    pushRegexRule (rule, nullname) {
+      this.newMeasure['evaluate.rule'].rules.push({
+        'dsl.type': 'griffin-dsl',
+        'dq.type': 'PROFILING',
+        rule: rule,
+        'out.dataframe.name': nullname
+      })
+    },
+
+    pushRule (rule) {
+      this.newMeasure['evaluate.rule'].rules.push({
+        'dsl.type': 'griffin-dsl',
+        'dq.type': 'PROFILING',
+        rule: rule,
+        name: 'profiling'
+      })
+    },
+    transferRule (rule, col) {
+      switch (rule) {
+        case 'Total Count':
+          return (
+            `count(source.${col.name}) AS \`${col.name}_count\``
+          )
+        case 'Distinct Count':
+          return (
+            `approx_count_distinct(source.${col.name}) AS \`${col.name}_distcount\``
+          )
+        case 'Null Count':
+          return (
+            `count(source.${col.name}) AS \`${col.name}_nullcount\` WHERE source.${col.name} IS NULL`
+          )
+        case 'Maximum':
+          return (
+            `max(source.${col.name}) AS \`${col.name}_max\``
+          )
+        case 'Minimum':
+          return (
+            `min(source.${col.name}) AS \`${col.name}_min\``
+          )
+        case 'Average':
+          return (
+            `avg(source.${col.name}) AS \`${col.name}_average\``
+          )
+        case 'Empty Count':
+          return (
+            `count(source.${col.name}) AS \`${col.name}_emptycount\` WHERE source.${col.name} = ''`
+          )
+        case 'Regular Expression Detection Count':
+          return (
+            `count(source.${col.name}) AS \`${col.name}_regexcount\` WHERE source.${col.name} RLIKE '^[0-9]{4}$'`
+          )
+        case 'Enum Detection Top10 Count':
+          return (
+            `source.${col.name} AS ${col.name}, count(*) AS count GROUP BY source.${col.name} ORDER BY count DESC LIMIT 10`
+          )
+      }
+    },
+    getCoal (resolve) {
+      let coalAll = []
+      this.$http({
+        url: this.$http.adornUrl('/dataset/tree/getcoal'),
+        method: 'post'
+      }).then(({data}) => {
+        if (!(data && data.code === 0)) {
+          Message.error(data.msg)
+        } else {
+          const coalContent = data.info
+          for (let sign = 0; sign < coalContent.length; sign++) {
+            var coal = {
+              name: coalContent[sign].name,
+              coalid: coalContent[sign].id,
+              limit: 'coal',
+              hbaseTableName: '',
+              icon: 'iconfont icon-xitongfuwu',
+              leaf: false
+            }
+            coalAll.push(coal)
+          }
+        }
+        return resolve(coalAll)
+        // console.log('***************')
+        // console.log(coalAll)
+      })
+    },
+    getSystem (coalId, resolve) {
+      var coalData = {
+        coalid: coalId
+      }
+      this.$http({
+        url: this.$http.adornUrl('/dataset/tree/getfisystem'),
+        method: 'post',
+        data: this.$http.adornData(coalData, false)
+      }).then(systemRespond => {
+        let systemAll = []
+        if (systemRespond.data.length <= 0) {
+          Message.error(systemRespond.msg)
+        } else {
+          const systemContent = systemRespond.data
+          for (let i = 0; i < systemContent.length; i++) {
+            var system = {
+              name: systemContent[i].name,
+              systemid: systemContent[i].id,
+              limit: 'system',
+              icon: 'icon iconfont icon-xitongfuwu',
+              hbaseTableName: '',
+              leaf: false
+            }
+            systemAll.push(system)
+          }
+        }
+        return resolve(systemAll)
+      })
+    },
+    getSubSystem (resolve) {
+      // const systemData = {
+      //   systemid: systemid
+      // }
+      this.$http({
+        url: this.$http.adornUrl('/dataset/tree/getsubSystem'),
+        method: 'post'
+        // data: this.$http.adornData(systemData, false)
+      }).then(subrespond => {
+        let subSystemAll = []
+        let subSystemContent = subrespond.data
+        if (subSystemContent.length === 0) {
+          Message.error(subrespond.msg)
+        } else {
+          for (let j = 0; j < subSystemContent.length; j++) {
+            var subSystem = {
+              name: subSystemContent[j].name,
+              subSustemid: subSystemContent[j].id,
+              limit: 'subSystem',
+              icon: 'iconfont icon-xitongfuwu',
+              leaf: false
+            }
+            subSystemAll.push(subSystem)
+          }
+        }
+        return resolve(subSystemAll)
+      })
+    },
+    getEquipment (subSustemid, resolve) {
+      const subSystemData = {
+        subSystemid: subSustemid
+      }
+      this.$http({
+        url: this.$http.adornUrl('/dataset/tree/getequipment'),
+        method: 'post',
+        data: this.$http.adornData(subSystemData, false)
+      }).then(eqprespond => {
+        let equipmentAll = []
+        const eqpSystemContent = eqprespond.data
+        if (eqpSystemContent.length === 0) {
+          Message.error(eqprespond.msg)
+        } else {
+          for (let k = 0; k < eqpSystemContent.length; k++) {
+            var equipment = {
+              name: eqpSystemContent[k].name,
+              equipmentid: eqpSystemContent[k].id,
+              limit: 'equipment',
+              hbaseTableName: '',
+              icon: 'iconfont icon-xitongfuwu',
+              leaf: false
+            }
+            equipmentAll.push(equipment)
+          }
+        }
+        return resolve(equipmentAll)
+      })
+    },
+    getSubEquipment (equipmentid, resolve) {
+      const equimentData = {
+        equipment: equipmentid
+      }
+      this.$http({
+        url: this.$http.adornUrl('/dataset/tree/getsubequipment'),
+        method: 'post',
+        data: this.$http.adornData(equimentData, false)
+      }).then(subEqpRespond => {
+        let subEquimentAll = []
+        const subEqpSystemContent = subEqpRespond.data
+        if (subEqpSystemContent.length === 0) {
+          Message.error(subEqpRespond.msg)
+        } else {
+          for (let m = 0; m < subEqpSystemContent.length; m++) {
+            var subEquiment = {
+              name: subEqpSystemContent[m].name,
+              subEquipmentid: subEqpSystemContent[m].id,
+              hbaseTableName: subEqpSystemContent[m].hbaseTableName,
+              limit: 'children',
+              icon: 'iconfont icon-xitong3',
+              leaf: true
+            }
+            subEquimentAll.push(subEquiment)
+          }
+        }
+        return resolve(subEquimentAll)
+      })
+    },
+    // 左侧树的懒加载 五层结构
+    // loadTreeNode (node, resolve) {
+    //   if (node.level === 0) {
+    //     this.getCoal(resolve)
+    //   } else if (node.level === 1) {
+    //     this.getSystem(node.data.coalid, resolve)
+    //   } else if (node.level === 2) {
+    //     this.getSubSystem(node.data.systemid, resolve)
+    //   } else if (node.level === 3) {
+    //     this.getEquipment(node.data.subSustemid, resolve)
+    //   } else {
+    //     this.getSubEquipment(node.data.equipmentid, resolve)
+    //   }
+    // }
+    // 左侧树的懒加载 三层结构
+    loadTreeNode (node, resolve) {
+      if (node.level === 0) {
+        this.getSubSystem(resolve)
+      } else if (node.level === 1) {
+        this.getEquipment(node.data.subSustemid, resolve)
+      } else {
+        this.getSubEquipment(node.data.equipmentid, resolve)
+      }
+    }
+  },
+  watch: {
+    chooseEqpment (newVal, oldVal) {
+      if (oldVal.hasOwnProperty('icon')) {
+        oldVal.icon = 'iconfont icon-xitong3'
+      }
+      newVal.icon = 'iconfont icon-xitong4'
+    }
+  }
+}
+</script>
+<style scoped>
+.divi {
+  display: block;
+  height: 1px;
+  width: 100%;
+  margin: 24px 0;
+  background-color: #dcdfe6;
+  position: relative;
+}
+
+.divi2 {
+  display: block;
+  height: 1px;
+  width: 100%;
+  position: relative;
+}
+
+.showRules {
+  color: #409eff
+}
+</style>

+ 97 - 0
src/views/modules/snoop/measureUserWatch.vue

@@ -0,0 +1,97 @@
+<template>
+<div>
+
+
+
+  <el-dialog :title="'查看度量'" :close-on-click-modal="false" :visible.sync="visible">
+
+    <el-form  :model="goal_info" label-width="100px"  v-loading="measDataListLoading"  style="word-break: break-word">
+      <el-form-item label="度量名称 :" prop="name">
+        <!--                  <el-input v-model="goal_info.config.name"></el-input>-->
+        <span>{{ goal_info.name  }}</span>
+      </el-form-item>
+      <el-form-item label="度量描述 :">
+        <span>{{ goal_info.description }}</span>
+        <!--                  <el-input v-model="goal_info.config.description"></el-input>-->
+      </el-form-item>
+      <el-form-item label="数据源 :">
+        <span>{{ goal_info.dataSources }}</span>
+        <!--                  <el-input v-model="goal_info.equipment.name"></el-input>-->
+      </el-form-item>
+      <!--                <el-form-item label="查询条件 :">-->
+      <!--                  <span>{{goal_info.config.where}}</span>-->
+      <!--&lt;!&ndash;                  <el-input v-model="goal_info.config.where"></el-input>&ndash;&gt;-->
+      <!--                </el-form-item>-->
+      <el-form-item label="分区信息 :">
+        <span>{{goal_info.partition}}</span>
+        <!--                                  <el-input v-model="goal_info.config.num" >{{goal_info.config.num + goal_info.config.timetype}}</el-input>-->
+        <!--                                  <el-input v-model="goal_info.config.timezone"></el-input>-->
+      </el-form-item>
+      <el-form-item label="度量规则 :">
+        <!--                  <el-input-number v-model="datacForm.num" controls-position="right" :min="0"></el-input-number>-->
+<!--        <div style="height: 100px;overflow: auto">-->
+          <template v-for="rule in  goal_info.Cloum">
+            <li>{{ rule.name }} : {{ rule.infos }}</li>
+          </template>
+
+<!--          &lt;!&ndash;    <template v-for="rule in  timezones" >&ndash;&gt;-->
+<!--          &lt;!&ndash;      <li>{{rule.label}} : {{rule.value}}</li>&ndash;&gt;-->
+<!--          &lt;!&ndash;    </template>&ndash;&gt;-->
+<!--        </div>-->
+      </el-form-item>
+    </el-form>
+
+
+    <span slot="footer" class="dialog-footer">
+      <el-button @click="visible = false">取消</el-button>
+      <el-button type="primary" @click="visible=false">确定</el-button>
+    </span>
+  </el-dialog>
+
+</div>
+</template>
+
+<script>
+export default {
+  name: 'measureUserWatch',
+  data () {
+    return {
+      goal_info: {},
+      visible: false,
+      measDataListLoading: false
+    }
+  },
+  methods: {
+    init (info) {
+      this.visible = true
+      this.measDataListLoading = false
+      // console.info(info)
+      this.getMeasureListById(info.measureID)
+    },
+    getMeasureListById (id) {
+      this.measDataListLoading = true
+      this.classificationtag = null
+      this.$http({
+        url: this.$http.snoopUrl('/v1/measures/') + id,
+        methods: 'get'
+      }).then((data) => {
+        if (data && data.status === 200) {
+          var info = data.data
+          this.goal_info.name = info.name
+          this.goal_info.description = info.description
+          var dataScore = info['data.sources'][0].connector.config
+          this.goal_info.dataSources = dataScore.database + '  : ' + dataScore['table.name']
+          this.goal_info.partition = info['data.sources'][0].connector['data.unit']
+          this.goal_info.Cloum = info['rule.description'].details
+        }
+        // console.log(this.goal_info)
+        this.measDataListLoading = false
+      })
+    }
+  }
+}
+</script>
+
+<style scoped>
+
+</style>

+ 593 - 0
src/views/modules/snoop/showRules.vue

@@ -0,0 +1,593 @@
+<template>
+  <div>
+    <el-dialog
+      :title="title"
+      :visible.sync="showRuleVisible"
+      width="60%"
+      append-to-body
+      close-on-click-modal
+      close-on-press-escape
+      center>
+      <div>
+        <el-tabs tab-position="left" style="height: 420px; overflow: auto;">
+
+          <el-tab-pane label="Null Count">
+            <div class="table-style1">
+              <p>Null is a special marker used to indicate that a data value does not exist.</p>
+              <h5 class="table-style2">Example</h5>
+              <p style="text-align: left;">
+                Suppose we have the below data table, then the Null Count of "FIRSTNAME" is
+                <span class="table-style3">2</span>
+              </p>
+              <el-table
+                :data="tableDataNull"
+                style="width: 100%">
+                <el-table-column
+                  prop="id"
+                  label="ID"
+                  width="180">
+                </el-table-column>
+                <el-table-column
+                  prop="FRISTNAME"
+                  label="FRISTNAME"
+                  width="180">
+                  <template slot-scope="scope">
+                    <span v-if="scope.row.FRISTNAME === 'null'" style="color: red">{{ scope.row.FRISTNAME }}</span>
+                    <span v-else>{{ scope.row.FRISTNAME }}</span>
+                  </template>
+                </el-table-column>
+                <el-table-column
+                  prop="LASTNAME"
+                  label="LASTNAME">
+                </el-table-column>
+                <el-table-column
+                  prop="age"
+                  label="AGE">
+                </el-table-column>
+              </el-table>
+            </div>
+          </el-tab-pane>
+
+          <el-tab-pane label="Distinct Count">
+            <div class="table-style1">
+              <p>The Distinct Constraint prevents two records from having identical values in a particular column.</p>
+              <h5 class="table-style2">Example</h5>
+              <p style="text-align: left;">
+                Suppose we have the below data table which has four attributes-ID, NAME, AGE and FAVOURITE FOOD. Then
+                the Distinct Count is
+                <span class="table-style3">2</span>
+              </p>
+              <el-table
+                :data="tableDataDistinct"
+                style="width: 100%">
+                <el-table-column
+                  prop="id"
+                  label="ID">
+                </el-table-column>
+                <el-table-column
+                  prop="name"
+                  label="NAME"
+                  width="180">
+                </el-table-column>
+                <el-table-column
+                  prop="age"
+                  label="AGE">
+                </el-table-column>
+                <el-table-column
+                  prop="food"
+                  label="FAVOURITE FOOD">
+                </el-table-column>
+              </el-table>
+            </div>
+          </el-tab-pane>
+
+          <el-tab-pane label="Total Count">
+            <div class="table-style1">
+              <p>Total Count is a count of the number of values of the selected column.</p>
+              <h5 class="table-style2">Example</h5>
+              <p style="text-align: left;">
+                Suppose we have the below data table, then the total count of ID is:
+                <span class="table-style3">5</span>
+              </p>
+              <el-table
+                :data="tableDataNull"
+                style="width: 100%">
+                <el-table-column
+                  prop="id"
+                  label="ID"
+                  width="180">
+                </el-table-column>
+                <el-table-column
+                  prop="FRISTNAME"
+                  label="FRISTNAME"
+                  width="180">
+                </el-table-column>
+                <el-table-column
+                  prop="LASTNAME"
+                  label="LASTNAME">
+                </el-table-column>
+                <el-table-column
+                  prop="age"
+                  label="AGE">
+                </el-table-column>
+              </el-table>
+            </div>
+          </el-tab-pane>
+
+          <el-tab-pane label="Maximum">
+            <div class="table-style1">
+              <p>Maximum is the biggest value of the selected column.</p>
+              <h5 class="table-style2">Example</h5>
+              <p style="text-align: left;">
+                Suppose we have the below data table, then the maximum is:
+                <span class="table-style3">24</span>
+              </p>
+              <el-table
+                :data="tableDataNull"
+                style="width: 100%">
+                <el-table-column
+                  prop="id"
+                  label="ID"
+                  width="180">
+                </el-table-column>
+                <el-table-column
+                  prop="FRISTNAME"
+                  label="FRISTNAME"
+                  width="180">
+                </el-table-column>
+                <el-table-column
+                  prop="LASTNAME"
+                  label="LASTNAME">
+                </el-table-column>
+                <el-table-column
+                  prop="age"
+                  label="AGE">
+                  <template slot-scope="scope">
+                    <span v-if="scope.row.LASTNAME === 'aaa'" style="color: #ff0000">{{ scope.row.age }}</span>
+                    <span v-else>{{ scope.row.age }}</span>
+                  </template>
+                </el-table-column>
+              </el-table>
+            </div>
+          </el-tab-pane>
+
+          <el-tab-pane label="Minimum">
+            <div class="table-style1">
+              <p>Minimum is smallest value of the selected colum.</p>
+              <h5 class="table-style2">Example</h5>
+              <p style="text-align: left;">
+                Suppose we have the below data table, then the minimum is:
+                <span class="table-style3">20</span>
+              </p>
+              <el-table
+                :data="tableDataNull"
+                style="width: 100%">
+                <el-table-column
+                  prop="id"
+                  label="ID"
+                  width="180">
+                </el-table-column>
+                <el-table-column
+                  prop="FRISTNAME"
+                  label="FRISTNAME"
+                  width="180">
+                </el-table-column>
+                <el-table-column
+                  prop="LASTNAME"
+                  label="LASTNAME">
+                </el-table-column>
+                <el-table-column
+                  prop="age"
+                  label="AGE">
+                  <template slot-scope="scope">
+                    <span v-if="scope.row.LASTNAME === 'zhang'" style="color: #ff0000">{{ scope.row.age }}</span>
+                    <span v-else>{{ scope.row.age }}</span>
+                  </template>
+                </el-table-column>
+              </el-table>
+            </div>
+          </el-tab-pane>
+
+          <el-tab-pane label="Average">
+            <div class="table-style1">
+              <p>Average is the average of the data values.</p>
+              <h5 class="table-style2">Example</h5>
+              <p style="text-align: left;">
+                Suppose we have the below data table, then the Average of AGE is:
+                <span class="table-style3">22</span>
+              </p>
+              <el-table
+                :data="tableDataNull"
+                style="width: 100%">
+                <el-table-column
+                  prop="id"
+                  label="ID"
+                  width="180">
+                </el-table-column>
+                <el-table-column
+                  prop="FRISTNAME"
+                  label="FRISTNAME"
+                  width="180">
+                </el-table-column>
+                <el-table-column
+                  prop="LASTNAME"
+                  label="LASTNAME">
+                </el-table-column>
+                <el-table-column
+                  prop="age"
+                  label="AGE">
+                </el-table-column>
+              </el-table>
+            </div>
+          </el-tab-pane>
+
+          <el-tab-pane label="Median">
+            <div class="table-style1">
+              <p>Median is the middle value.</p>
+              <h5 class="table-style2">Example</h5>
+              <p style="text-align: left;">
+                Suppose we have the below data table, then the median of AGE is:
+                <span class="table-style3">22</span>
+              </p>
+              <el-table
+                :data="tableDataNull"
+                style="width: 100%">
+                <el-table-column
+                  prop="id"
+                  label="ID"
+                  width="180">
+                </el-table-column>
+                <el-table-column
+                  prop="FRISTNAME"
+                  label="FRISTNAME"
+                  width="180">
+                </el-table-column>
+                <el-table-column
+                  prop="LASTNAME"
+                  label="LASTNAME">
+                </el-table-column>
+                <el-table-column
+                  prop="age"
+                  label="AGE">
+                  <template slot-scope="scope">
+                    <span v-if="scope.row.LASTNAME === 'wang'" style="color: #ff0000">{{ scope.row.age }}</span>
+                    <span v-else>{{ scope.row.age }}</span>
+                  </template>
+                </el-table-column>
+              </el-table>
+            </div>
+          </el-tab-pane>
+
+          <el-tab-pane label="TOP 10">
+            <div class="table-style1">
+              <p> The top ten most frequent occurrences in the data.</p>
+              <h5 class="table-style2">Example</h5>
+              <p style="text-align: left;">
+                Suppose we have the below data table, then cloum LASTNAME of  top 18 is:
+                <span class="table-style3" style="font-size: 15px">(cao,3);(fan,2);(ding,2); (huang,2); (hua,1) (han,1) (li,1) (liu,1); (lv,1); (guan,1)</span>
+              </p>
+              <el-table
+                :data="tableDataTop10"
+                style="width: 100%">
+                <el-table-column
+                  prop="id"
+                  label="ID"
+                  width="180">
+                </el-table-column>
+                <el-table-column
+                  prop="FRISTNAME"
+                  label="FRISTNAME"
+                  width="180">
+                </el-table-column>
+                <el-table-column
+                  prop="LASTNAME"
+                  label="LASTNAME">
+                </el-table-column>
+                <el-table-column
+                  prop="age"
+                  label="AGE">
+                </el-table-column>
+              </el-table>
+            </div>
+          </el-tab-pane>
+          <!--          <el-tab-pane label="Rule Detection Count">定时任务补偿</el-tab-pane>-->
+          <el-tab-pane label="Enum Detection Count">
+            <div class="table-style1">
+              <p>The Enum Detection Count is a statement of GROUP BY , which often used with aggregate functions
+                (COUNT, MAX, MIN, SUM, AVG) to group the result-set by one or more columns.</p>
+              <h5 class="table-style2">Example</h5>
+              <p style="text-align: left;">
+                We can use Enum Detection Count to search the lists the number of customers in each country in the
+                following table:
+              </p>
+              <el-table
+                :data="tableDataSQL"
+                style="width: 100%">
+                <el-table-column
+                  prop="id"
+                  label="ID"
+                  width="180">
+                </el-table-column>
+                <el-table-column
+                  prop="name"
+                  label="NAME"
+                  width="180">
+                </el-table-column>
+                <el-table-column
+                  prop="age"
+                  label="AGE">
+                </el-table-column>
+                <el-table-column
+                  prop="country"
+                  label="COUNTRY">
+                </el-table-column>
+              </el-table>
+              <p class="text-left">
+                <strong>Suppose Enum Expression is :</strong> SELECT COUNT(CUSTORMERID), COUNTRY FROM Customers GROUP
+                BY COUNTRY;
+              </p>
+              <p class="text-left">
+                The result is:
+                <br>
+                <template style="margin-left: 10px">
+                  <kbd>COUNTRY |COUNT(CUSTOMERID)
+                    <br> China |2
+                    <br> Mexico |2
+                    <br> UK |1
+                  </kbd>
+                </template>
+              </p>
+            </div>
+          </el-tab-pane>
+          <!--          <el-tab-pane label="Regular Expression Match">定时任务补偿</el-tab-pane>-->
+
+        </el-tabs>
+
+      </div>
+
+      <span slot="footer" class="dialog-footer">
+    <el-button @click="showRuleVisible = false">取 消</el-button>
+    <el-button type="primary" @click="showRuleVisible = false">确 定</el-button>
+  </span>
+    </el-dialog>
+
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'showRules',
+  data () {
+    return {
+      showRuleVisible: false,
+      vaType: null,
+      title: 'rules',
+      tableDataNull: [
+        {
+          id: 1,
+          FRISTNAME: 'san',
+          LASTNAME: 'zhang',
+          age: 20
+        }, {
+          id: 2,
+          FRISTNAME: 'si',
+          LASTNAME: 'li',
+          age: 21
+        }, {
+          id: 3,
+          FRISTNAME: 'null',
+          LASTNAME: 'wang',
+          age: 22
+        }, {
+          id: 4,
+          FRISTNAME: 'liu',
+          LASTNAME: 'tang',
+          age: 23
+        }, {
+          id: 5,
+          FRISTNAME: 'null',
+          LASTNAME: 'aaa',
+          age: 24
+        }
+      ],
+      tableDataTop10: [
+        {
+          id: 1,
+          FRISTNAME: 'cao',
+          LASTNAME: 'cao',
+          age: 60
+        }, {
+          id: 2,
+          FRISTNAME: 'zhi',
+          LASTNAME: 'cao',
+          age: 40
+        }, {
+          id: 3,
+          FRISTNAME: 'hong',
+          LASTNAME: 'cao',
+          age: 20
+        }, {
+          id: 4,
+          FRISTNAME: 'lao',
+          LASTNAME: 'fan',
+          age: 20
+        }, {
+          id: 5,
+          FRISTNAME: 'kang',
+          LASTNAME: 'fan',
+          age: 20
+        },
+        {
+          id: 6,
+          FRISTNAME: 'feng',
+          LASTNAME: 'ding',
+          age: 20
+        }, {
+          id: 7,
+          FRISTNAME: 'yi',
+          LASTNAME: 'ding',
+          age: 20
+        }, {
+          id: 8,
+          FRISTNAME: 'zhong',
+          LASTNAME: 'huang',
+          age: 20
+        }, {
+          id: 9,
+          FRISTNAME: 'gai',
+          LASTNAME: 'huang',
+          age: 20
+        }, {
+          id: 10,
+          FRISTNAME: 'gai',
+          LASTNAME: 'huang',
+          age: 20
+        }, {
+          id: 11,
+          FRISTNAME: 'tuo',
+          LASTNAME: 'hua',
+          age: 20
+        }, {
+          id: 12,
+          FRISTNAME: 'xin',
+          LASTNAME: 'han',
+          age: 20
+        },
+        {
+          id: 13,
+          FRISTNAME: 'tong',
+          LASTNAME: 'li',
+          age: 20
+        },
+        {
+          id: 14,
+          FRISTNAME: 'bei',
+          LASTNAME: 'liu',
+          age: 20
+        },
+        {
+          id: 15,
+          FRISTNAME: 'bu',
+          LASTNAME: 'lv',
+          age: 20
+        }, {
+          id: 16,
+          FRISTNAME: 'yu',
+          LASTNAME: 'guan',
+          age: 20
+        }
+      ],
+      tableDataDistinct: [{
+        id: 1,
+        name: 'Lily',
+        age: 20,
+        food: 'APPLE'
+      }, {
+        id: 2,
+        name: 'Lucy',
+        age: 20,
+        food: 'APPLE'
+      }, {
+        id: 3,
+        name: 'Sam',
+        age: 35,
+        food: 'banana'
+      }, {
+        id: 4,
+        name: 'David',
+        age: 35,
+        food: 'banana'
+      }],
+      tableDataSQL: [{
+        id: 1,
+        name: 'allen',
+        age: 20,
+        country: 'China'
+      }, {
+        id: 2,
+        name: 'allen',
+        age: 20,
+        country: 'China'
+      }, {
+        id: 3,
+        name: 'allen',
+        age: 20,
+        country: 'UK'
+      }, {
+        id: 4,
+        name: 'allen',
+        age: 20,
+        country: 'Mexico'
+      }, {
+        id: 5,
+        name: 'allen',
+        age: 20,
+        country: 'Mexico'
+      }]
+    }
+  },
+  methods: {
+    init () {
+      this.showRuleVisible = true
+    },
+    ngOnInit () {
+      this.vaType = '2'
+    }
+  }
+}
+</script>
+
+<style scoped>
+
+.table > thead > tr.success > td {
+  background-color: #77b300;
+}
+
+mark {
+  background-color: #ff8800;
+  padding: .2em;
+}
+
+h5 {
+  font-size: 20px;
+}
+
+.table-style1 {
+  margin-left: 10px;
+  /*margin-top: -10px;*/
+  word-break: break-word
+}
+
+.table-style2 {
+  text-align: left;
+  margin: 5px 0px 10px 5px;
+}
+
+.table-style3 {
+  font-size: 20px;
+  margin-left: 10px;
+  color: #2f4f46;
+}
+
+.text-left {
+  text-align: left;
+}
+
+.y-scrollable::-webkit-scrollbar-track {
+  -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
+  border-radius: 10px;
+  background-color: #F5F5F5;
+}
+
+.y-scrollable::-webkit-scrollbar {
+  width: 5px;
+  border-radius: 10px;
+  background-color: #F5F5F5;
+}
+
+.y-scrollable::-webkit-scrollbar-thumb {
+  border-radius: 10px;
+  -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, .3);
+  background-color: #AAAAAA;
+}
+</style>

+ 47 - 0
src/views/modules/snoop/snoop-add.vue

@@ -0,0 +1,47 @@
+<template>
+  <el-dialog :title="'新增度量'" :close-on-click-modal="false" :visible.sync="visible">
+    <el-form :model="dataForm" ref ='dataForm'
+      label-width="100px">
+      <el-form-item label="步骤" size="mini">
+        <el-radio-group v-model="datasetStatus">
+          <el-radio :label="1">1.创建度量标准</el-radio>
+          <el-radio :label="2">2.创建任务</el-radio>
+        </el-radio-group>
+      </el-form-item>
+    </el-form>
+    <span slot="footer" class="dialog-footer">
+      <el-button @click="visible = false">取消</el-button>
+      <el-button type="primary" @click="visible=false;creatDataSetHandle()">确定</el-button>
+    </span>
+  </el-dialog>
+</template>
+
+<script>
+export default {
+  data () {
+    return {
+      visible: false,
+      datasetStatus: 1,
+      dataForm: {}
+    }
+  },
+  methods: {
+    init () {
+      this.visible = true
+      this.$nextTick(() => {
+        this.$refs.dataForm.resetFields()
+      })
+    },
+    // 创建measure
+    creatDataSetHandle () {
+      // 如果为传统算法
+      if (this.datasetStatus === 1) {
+        this.$router.replace({ path: '/snoop-measure' })
+      } else {
+        // 如果为智能算法
+        this.$router.replace({ path: '/snoop-job' })
+      }
+    }
+  }
+}
+</script>

+ 94 - 0
src/views/modules/visi/design-create.vue

@@ -0,0 +1,94 @@
+<template>
+  <div class="mod-demo-echarts">
+    <el-breadcrumb class="divi2" separator-class="el-icon-arrow-right">
+      <el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
+      <el-breadcrumb-item :to="{ path: '/visi-design'}">可视化设计</el-breadcrumb-item>
+      <el-breadcrumb-item>实验设置</el-breadcrumb-item>
+    </el-breadcrumb>
+    <el-divider class="divi"></el-divider>
+    <!-- <design-graph></design-graph> -->
+    <design-graph-1 :visible.sync="designgraphvisi" v-if="designgraphvisi" ref="designgraph"></design-graph-1>
+  </div>
+</template>
+
+<script>
+// import DesignGraph from "./design-graph.vue"
+import DesignGraph1 from "./design-graph1.vue";
+export default {
+  components: {
+    // DesignGraph,
+    DesignGraph1,
+  },
+  data() {
+    return {
+      // chartLine: null,
+      // chartBar: null,
+      // chartPie: null,
+      // chartScatter: null,
+      designgraphvisi: false,
+    };
+  },
+  mounted() {
+    
+  },
+  // watch: {    
+	//     '$route' (to, from) {   
+	//          this.$router.go(0);
+	// 		 }
+	// 	},
+  activated() {
+    //自动刷新一次
+    // if (location.href.indexOf("#reloaded") == -1) {
+    //   location.href = location.href + "#reloaded";
+    //   location.reload();
+    // }
+    this.designgraphvisi = true;
+    
+    if(this.$route.query.update==true){
+      this.init(this.$route.query.winfo);
+    }
+    
+  },
+  methods: {
+    init(winfo){
+      this.$nextTick(() => {
+        this.$refs.designgraph.initGraph(winfo);
+      })
+    }
+  },
+};
+</script>
+
+<style lang="scss">
+.mod-demo-echarts {
+  > .el-alert {
+    margin-bottom: 10px;
+  }
+  > .el-row {
+    margin-top: -10px;
+    margin-bottom: -10px;
+    .el-col {
+      padding-top: 10px;
+      padding-bottom: 10px;
+    }
+  }
+  .chart-box {
+    min-height: 400px;
+  }
+}
+.divi {
+  display: block;
+  height: 1px;
+  width: 100%;
+  margin: 24px 0;
+  background-color: #dcdfe6;
+  position: relative;
+}
+.divi2 {
+  display: block;
+  height: 1px;
+  width: 100%;
+  position: relative;
+}
+</style>
+

+ 7 - 3
src/views/modules/visi/design-experconfig.vue

@@ -10,9 +10,9 @@
             ></el-input>
           </el-form-item>
 
-          <!-- <el-form-item :wrapper-col="buttonItemLayout.wrapperCol">
-            <el-button type="primary"> 保存 </el-button>
-          </el-form-item> -->
+          <el-form-item :wrapper-col="buttonItemLayout.wrapperCol">
+            <el-button type="primary" @click="primary"> 保存 </el-button>
+          </el-form-item>
         </el-form>
       </el-tab-pane>
     </el-tabs>
@@ -45,6 +45,10 @@ export default {
       this.visible = true;
       // this.conditionForm.sourcedatalist =sourcedatalist;
     },
+    primary() {
+      
+      this.$emit("primaryExperimentclick", this.experimentName);
+    },
   },
   computed: {
     formItemLayout() {

+ 353 - 141
src/views/modules/visi/design-graph1.vue

@@ -1,117 +1,227 @@
 <template>
-  <a-layout id="components-layout-demo-responsive">
-    <!-- 左侧组件栏 default-expand-all-->
-
-    <a-layout-sider
-      breakpoint="lg"
-      collapsed-width="0"
-      @collapse="onCollapse"
-      @breakpoint="onBreakpoint"
-      theme="light"
-      v-model="collapsed"
-      collapsible
-    >
-      <div>
-        <a-tree
-          show-line
-          show-icon
-          :tree-data="treeData"
-          :default-selected-keys="['0-0-0']"
-          @select="onSelect"
-        >
-          <a-icon slot="icon" type="carry-out" />
-        </a-tree>
-      </div>
-    </a-layout-sider>
-    <!-- <div class="box" ref="box"> -->
-    <!-- <div class="left"> -->
-    <!-- 右侧画布 -->
-    <div class="content">
-      <div class="app-content">
-        <div class="box" ref="box">
-          <div class="left">
-            <!-- <a-layout style="width:'100%',height:'100%',display:'flex'"> -->
-            <el-form class="boxform">
-              <el-form-item class="boxformitem">
-                <!-- 画布上方按钮 undo redo-->
-                <el-row>
-                  <el-button-group>
-                    <el-button
-                      plain
-                      type="primary"
-                      icon="el-icon-arrow-left"
-                      @click="onUndo"
-                    ></el-button>
-                    <el-button type="primary" @click="onRedo" plain
-                      ><i class="el-icon-arrow-right el-icon--right"></i
-                    ></el-button>
-                    <el-button type="primary" @click="onRun">提交</el-button>
-                    <el-button type="primary" @click="onPrimary"
-                      >保存</el-button
-                    >
-                    <el-button type="info" @click="onCancel">取消</el-button>
-                    <el-button type="info" @click="onGetcontour"
-                      >示例</el-button
-                    >
-                    <el-button
-                      type="info"
-                      @click="onCleargraph"
-                      icon="el-icon-delete"
-                      >清空</el-button
-                    >
-
-                    <el-button type="info" @click="getParaTemp()"
-                      >获得代码模板</el-button
+  <div class="mod-demo-echarts">
+    <el-breadcrumb class="divi2" separator-class="el-icon-arrow-right">
+      <el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
+      <el-breadcrumb-item :to="{ path: '/visi-design' }"
+        >可视化设计</el-breadcrumb-item
+      >
+      <el-breadcrumb-item>实验设置</el-breadcrumb-item>
+    </el-breadcrumb>
+    <el-divider class="divi"></el-divider>
+    <!-- <design-graph></design-graph> -->
+    <!-- <design-graph-1 :visible.sync="designgraphvisi" v-if="designgraphvisi" ref="designgraph"></design-graph-1> -->
+
+    <a-layout id="components-layout-demo-responsive">
+      <!-- 左侧组件栏 default-expand-all-->
+
+      <a-layout-sider
+        breakpoint="lg"
+        collapsed-width="0"
+        @collapse="onCollapse"
+        @breakpoint="onBreakpoint"
+        theme="light"
+        v-model="collapsed"
+        collapsible
+      >
+        <div>
+          <a-tree
+            show-line
+            show-icon
+            :tree-data="treeData"
+            :default-selected-keys="['0-0-0']"
+            @select="onSelect"
+          >
+            <a-icon slot="icon" type="carry-out" />
+          </a-tree>
+        </div>
+      </a-layout-sider>
+      <!-- <div class="box" ref="box"> -->
+      <!-- <div class="left"> -->
+      <!-- 右侧画布 -->
+      <div class="content">
+        <div class="app-content">
+          <div class="box" ref="box">
+            <div class="left">
+              <!-- <a-layout style="width:'100%',height:'100%',display:'flex'"> -->
+              <el-form class="boxform">
+                <el-form-item class="boxformitem">
+                  <!-- 画布上方按钮 undo redo-->
+                  <el-row>
+                    <el-tooltip
+                      content="提交"
+                      placement="bottom-end"
+                      effect="dark"
                     >
-                    <el-button
-                      type="info"
-                      @click="getworkflowContent"
-                      icon="el-icon-document"
-                      >日志</el-button
+                      <i
+                        @click="onRun"
+                        style="
+                          height: 50px;
+                          width: 50px;
+                          margin: 10px 5px 10px 10px;
+                          font-size: 23px;
+                        "
+                        class="iconfont icon-yunXang"
+                      ></i>
+                    </el-tooltip>
+                    <el-tooltip
+                      content="保存"
+                      placement="bottom-end"
+                      effect="dark"
                     >
-                    <el-button
-                      type="info"
-                      @click="getgraphContentcenter"
-                      icon="el-icon-document"
-                      >节点居中</el-button
+                      <i
+                        @click="onPrimary"
+                        style="
+                          height: 25px;
+                          width: 25px;
+                          margin: 10px 5px 10px 10px;
+                          font-size: 23px;
+                        "
+                        class="el-icon-document-checked"
+                      >
+                      </i>
+                    </el-tooltip>
+                    <el-tooltip content="取消" effect="dark">
+                      <i
+                        @click="onCancel"
+                        style="
+                          height: 25px;
+                          width: 25px;
+                          margin: 10px 5px 10px 10px;
+                          font-size: 23px;
+                        "
+                        class="el-icon-error"
+                      >
+                      </i>
+                    </el-tooltip>
+                    <el-tooltip content="<" effect="dark">
+                      <i
+                        @click="onUndo"
+                        style="
+                          height: 25px;
+                          width: 25px;
+                          margin: 10px 5px 10px 10px;
+                          font-size: 23px;
+                        "
+                        class="el-icon-arrow-left"
+                      >
+                      </i>
+                    </el-tooltip>
+                    <el-tooltip content=">" effect="dark">
+                      <i
+                        @click="onRedo"
+                        style="
+                          height: 25px;
+                          width: 25px;
+                          margin: 10px 5px 10px 10px;
+                          font-size: 23px;
+                        "
+                        class="el-icon-arrow-right"
+                      >
+                      </i>
+                    </el-tooltip>
+                    <el-tooltip content="示例" effect="dark">
+                      <i
+                        @click="onGetcontour"
+                        style="
+                          height: 25px;
+                          width: 25px;
+                          margin: 10px 5px 10px 10px;
+                          font-size: 23px;
+                        "
+                        class="el-icon-notebook-2"
+                      >
+                      </i>
+                    </el-tooltip>
+                    <el-tooltip content="清空" effect="dark">
+                      <i
+                        @click="onCleargraph"
+                        style="
+                          height: 25px;
+                          width: 25px;
+                          margin: 10px 5px 10px 10px;
+                          font-size: 23px;
+                        "
+                        class="el-icon-delete"
+                      >
+                      </i>
+                    </el-tooltip>
+                    <el-tooltip content="获取代码模板" effect="dark">
+                      <i
+                        @click="getParaTemp()"
+                        style="
+                          height: 25px;
+                          width: 25px;
+                          margin: 10px 5px 10px 10px;
+                          font-size: 23px;
+                        "
+                        class="el-icon-tickets"
+                      >
+                      </i>
+                    </el-tooltip>
+                    <el-tooltip content="日志" effect="dark">
+                      <i
+                        @click="getworkflowContent"
+                        style="
+                          height: 25px;
+                          width: 25px;
+                          margin: 10px 5px 10px 10px;
+                          font-size: 23px;
+                        "
+                        class="el-icon-document"
+                      >
+                      </i>
+                    </el-tooltip>
+                    <el-tooltip content="节点居中" effect="dark">
+                      <i
+                        @click="getgraphContentcenter"
+                        style="
+                          height: 25px;
+                          width: 25px;
+                          margin: 10px 5px 10px 10px;
+                          font-size: 23px;
+                        "
+                        class="iconfont icon-tishi"
+                      >
+                      </i>
+                    </el-tooltip>
+
+                    <el-tag
+                      :key="workflowstatustag.name"
+                      :type="workflowstatustag.type"
+                      @click="getWorkflowStatus"
+                      >{{ workflowstatustag.name }}</el-tag
                     >
-                  </el-button-group>
-                  <el-tag
-                    :key="workflowstatustag.name"
-                    :type="workflowstatustag.type"
-                    @click="getWorkflowStatus"
-                    >{{ workflowstatustag.name }}</el-tag
+                  </el-row>
+                </el-form-item>
+                <el-form-item class="boxformitem">
+                  <!-- 画布具体位置 -->
+                  <!-- <a-layout-content :style="{ margin: '0px 0px 0' }"> -->
+                  <!-- <div :style="{ padding: '24px', background: '#fff', minHeight: '360px' }"> -->
+                  <div
+                    style="width: 100%; height: 100%; display: flex"
+                    :style="{
+                      padding: '0px',
+                      background: '#fff',
+                      minHeight: '800px',
+                    }"
                   >
-                </el-row>
-              </el-form-item>
-              <el-form-item class="boxformitem">
-                <!-- 画布具体位置 -->
-                <!-- <a-layout-content :style="{ margin: '0px 0px 0' }"> -->
-                <!-- <div :style="{ padding: '24px', background: '#fff', minHeight: '360px' }"> -->
-                <div
-                  style="width: 100%; height: 100%; display: flex"
-                  :style="{
-                    padding: '0px',
-                    background: '#fff',
-                    minHeight: '800px',
-                  }"
-                >
-                  <!-- content -->
-                  <!-- 画布                     style="width: 100%; height: 100%"   class="app-content"-->
-                  <div id="container" style="flex: 1"></div>
-                </div>
-                <!-- </a-layout-content> -->
-              </el-form-item>
-            </el-form>
-            <!-- </a-layout> -->
-          </div>
-
-          <div class="resize" title="收缩侧边栏"></div>
-          <div class="right">
-            <!-- 右侧组件栏 width="290px"   style="width: 100%"   width="239px" 309px-->
-            <ExperimentConfig
+                    <!-- content -->
+                    <!-- 画布                     style="width: 100%; height: 100%"   class="app-content"-->
+                    <div id="container" style="flex: 1"></div>
+                  </div>
+                  <!-- </a-layout-content> -->
+                </el-form-item>
+              </el-form>
+              <!-- </a-layout> -->
+            </div>
+
+            <div class="resize" title="收缩侧边栏"></div>
+            <div class="right">
+              <!-- 右侧组件栏 width="290px"   style="width: 100%"   width="239px" 309px-->
+              <ExperimentConfig
                 v-show="experimentVisi"
                 ref="experConfig"
+                @primaryExperimentclick="primaryExperimentConfig(arguments)"
               ></ExperimentConfig>
               <NodeConfig
                 v-show="nodeConfigVisi"
@@ -123,7 +233,7 @@
                 ref="newConNodeConfig"
                 @primaryclick="primaryConNodeConfig(arguments)"
               ></ConNodeConfig>
-            <!-- <a-layout-sider
+              <!-- <a-layout-sider
               breakpoint="lg"
               theme="light"
               width="100%"
@@ -147,24 +257,28 @@
                 @primaryclick="primaryConNodeConfig(arguments)"
               ></ConNodeConfig>
             </a-layout-sider> -->
+            </div>
           </div>
         </div>
       </div>
-    </div>
-    <NodeParaTemp v-if="paraTempVisible" ref="paraTemp"></NodeParaTemp>
-    <InputNodeConfig
-      v-if="inputNodeConVisible"
-      ref="inputNodeConfig"
-      @refreshinputnode="primaryInputnodeConfig(arguments)"
-    ></InputNodeConfig>
-    <OutputNodeConfig
-      v-if="outputNodeConVisible"
-      ref="outputNodeConfig"
-    ></OutputNodeConfig>
-    <Workflowlog v-if="workflowContentVisi" ref="getworkflowlog"></Workflowlog>
-  </a-layout>
-  <!-- 弹窗 -->
-  <!-- <ConWatch v-if="newWatchVisible" ref="newWatch" @refreshDataList="getDataList"></ConWatch> -->
+      <NodeParaTemp v-if="paraTempVisible" ref="paraTemp"></NodeParaTemp>
+      <InputNodeConfig
+        v-if="inputNodeConVisible"
+        ref="inputNodeConfig"
+        @refreshinputnode="primaryInputnodeConfig(arguments)"
+      ></InputNodeConfig>
+      <OutputNodeConfig
+        v-if="outputNodeConVisible"
+        ref="outputNodeConfig"
+      ></OutputNodeConfig>
+      <Workflowlog
+        v-if="workflowContentVisi"
+        ref="getworkflowlog"
+      ></Workflowlog>
+    </a-layout>
+    <!-- 弹窗 -->
+    <!-- <ConWatch v-if="newWatchVisible" ref="newWatch" @refreshDataList="getDataList"></ConWatch> -->
+  </div>
 </template>
 
 
@@ -206,6 +320,9 @@ export default {
       form: this.$form.createForm(this, { name: "coordinated" }),
       collapsed: false, //设置左侧侧边栏可收起
 
+      addorupdate: true,//true表示update,新增  false表示add
+      workflowId: null,//当前工作流id
+      experimentName: "",//当前实验名称
       workflowName: "", //当前画布工作流名称
       workflowContent: { main: "", wait: "", init: "" }, //当前画布工作流整个日志
       workflowContentlog: "",
@@ -310,6 +427,7 @@ export default {
       showLine: true,
       showIcon: false,
       nodedata: [],
+      imageurl: require("@/assets/img/cnnmnist.svg"),
     };
   },
   components: {
@@ -325,6 +443,15 @@ export default {
   },
   activated() {
     this.getalgorithmDataList();
+    this.onCleargraph();
+    this.addorupdate = this.$route.query.update;
+    console.log("addorupdate")
+    console.log(this.addorupdate)
+    //路由跳转--如果是修改,则加载画布信息;如果为新建,则不加载
+    if(this.$route.query.update==true){
+      this.initGraph(this.$route.query.winfo);
+      
+    }
     // this.createGraph();
     // this.addalgorithmdata();
   },
@@ -902,6 +1029,11 @@ export default {
       scroller: {
         enabled: true,
         pannable: true,
+        minVisibleHeight: 800,
+        minVisibleWidth: 800,
+        autoResize: true,
+        height: 800,
+        className: "x6-graph-scroller",
       },
       mousewheel: {
         enabled: true,
@@ -1120,7 +1252,6 @@ export default {
       }
     });
 
-
     //节点删除    边未完成
     graph.on("node:delete", ({ view, e }) => {
       e.stopPropagation();
@@ -3115,8 +3246,20 @@ export default {
     //设置布局左右可拖动
     let me = this;
     me.dragControllerDiv();
+    console.log("yu");
   },
   methods: {
+    initGraph(info) {
+      //修改当前画布
+      //查询画布数据,导入画布
+      this.workflowId = info.workflowId;
+      this.graph.fromJSON(JSON.parse(info.graphJson).cells);
+      console.log("fromJson"+info.graphJson)
+      
+      
+      console.log(JSON.parse(info.graphJson).cells)
+
+    },
     createGraph() {
       const graph = new Graph({
         grid: true,
@@ -3125,9 +3268,9 @@ export default {
         // width: 1200,
         // height: 750,
         autoResize: true,
-        panning: {
-          enabled: true,
-        },
+        // panning: {
+        //   enabled: true,
+        // },
         resizing: {
           enabled: true,
         },
@@ -3342,7 +3485,24 @@ export default {
         type: "warning",
       })
         .then(() => {
+          console.log("任务取消")
+          console.log(this.workflowName);
           //确定取消任务后的操作
+          if(this.workflowstatustag.name == "Running" && this.workflowName!=""){
+            this.$http({
+              url: this.$http.adornUrl("/visi/visiworkflow/stopworkflow"),
+              method: "post",
+              data: this.$http.adornData({workflowName: this.workflowName}),
+            }).then(({ data }) => {
+              if (data && data.code === 0) {
+                this.workflowStatus = data.statusPhase;
+                if(this.workflowStatus == "Failed"){
+                  Message.success("任务已取消");
+                } 
+                console.log("任务已取消")
+              }
+            });
+          }
         })
         .catch(() => {});
     },
@@ -3360,11 +3520,18 @@ export default {
           this.$http({
             url: this.$http.adornUrl("/visi/visiworkflow/submit"),
             method: "post",
-            data: this.$http.adornData(this.graph.toJSON()),
+            data: this.$http.adornData({
+              graphJson: JSON.stringify(this.graph.toJSON()),
+              workflowId: this.workflowId,
+              experimentName: this.experimentName,
+              addorupdate: this.addorupdate,
+              }
+              ),
           }).then(({ data }) => {
             if (data && data.code === 0) {
               this.workflowName = data.workflowName;
               this.idTemplateNameMap = data.idTemplateNameMap; //节点id与 DAG中task和Template 的对应关系
+              this.workflowId = data.workflowId;//若为新增,返回新增的主键ID  workflowId
               // 迭代属性名称:
               for (let nodeid of Object.keys(this.idTemplateNameMap)) {
                 var tempname = this.idTemplateNameMap[nodeid];
@@ -3485,7 +3652,7 @@ export default {
     },
     //20211109  测试  能否保存至数据库
     onPrimary() {
-      MessageBox.confirm(`确定进行[退出]操作?`, "提示", {
+      MessageBox.confirm(`确定进行[保存]操作?`, "提示", {
         confirmButtonText: "确定",
         cancelButtonText: "取消",
         type: "warning",
@@ -3497,7 +3664,7 @@ export default {
             data: this.$http.adornData({
               userId: this.$store.state.user.id,
               workflowId: undefined,
-              experimentName: "实验1",
+              experimentName: this.experimentName,
               workflowtempName: "",
               workflowName: "",
               graphJson: JSON.stringify(this.graph.toJSON()),
@@ -5672,9 +5839,17 @@ export default {
         //   scopedSlots: { icon: "custom" },
         // });
         console.log(this.treeData);
-        var imageurl =
-          "/src/assets/img/" + this.algorithmdataList[i].algonodeName + ".svg";
+        // var imageurl =
+        //   "/src/assets/img/" + this.algorithmdataList[i].algonodeName + ".svg";
         //节点名称后跟随机参数
+        if (
+          this.algorithmdataList[i].algotreetype != "传统算法" &&
+          this.algorithmdataList[i].algotreetype != "智能应用"
+        ) {
+          this.imageurl = require("@/assets/img/visisvg/" +
+            this.algorithmdataList[i].algonodeName +
+            ".svg");
+        }
 
         var newalgonode = this.graph.createNode({
           x: 0,
@@ -5699,16 +5874,9 @@ export default {
             //   fill: "#DA2625",
             // },
             image: {
-              "xlink:href":
-                "https://gw.alipayobjects.com/zos/bmw-prod/6eb71764-18ed-4149-b868-53ad1542c405.svg",
+              "xlink:href": this.imageurl,
+              // "https://gw.alipayobjects.com/zos/bmw-prod/6eb71764-18ed-4149-b868-53ad1542c405.svg",
               // "src/views/modules/visi/visisvg/算法.svg",  /src/assets/img/   ../../../assets/img/
-              // href:
-              //   "src/views/modules/visi/visisvg/" +
-              //   this.algorithmdataList[i].algonodeName +
-              //   ".svg",
-
-              //   "https://gw.alipayobjects.com/zos/bmw-prod/6eb71764-18ed-4149-b868-53ad1542c405.svg",
-              // "xlink:href":  "https://gw.alipayobjects.com/os/s/prod/antv/assets/image/logo-with-text-73b8a.svg",
               //可放图标
             },
           },
@@ -5850,6 +6018,14 @@ export default {
       // })
     },
 
+    //保存实验名称
+    primaryExperimentConfig(args) {
+      console.log("保存实验名称");
+      console.log(args);
+      this.experimentName = args[0];
+      console.log(this.experimentName);
+    },
+
     //20210810  保存条件节点设置
     primaryConNodeConfig(args) {
       this.graph
@@ -6688,5 +6864,41 @@ export default {
   border-width: 1px;
   border-color: #dcdfe6;
 }
+// .el-icon-video-play:before {
+//   content: "提交";
+// }
+.mod-demo-echarts {
+  > .el-alert {
+    margin-bottom: 10px;
+  }
+  > .el-row {
+    margin-top: -10px;
+    margin-bottom: -10px;
+    .el-col {
+      padding-top: 10px;
+      padding-bottom: 10px;
+    }
+  }
+  .chart-box {
+    min-height: 400px;
+  }
+}
+.divi {
+  display: block;
+  height: 1px;
+  width: 100%;
+  margin: 24px 0;
+  background-color: #dcdfe6;
+  position: relative;
+}
+.divi2 {
+  display: block;
+  height: 1px;
+  width: 100%;
+  position: relative;
+}
+.x6-graph-scroller {
+  min-height: 800px;
+}
 </style>
 

+ 2 - 2
src/views/modules/visi/design-node-config.vue

@@ -928,7 +928,7 @@ export default {
               // console.log(this.podcontent.init);
               // console.log(this.podcontent.wait);
               // console.log(this.podphase);
-              
+
               // this.podlogs = data.podlogs;
               // console.log("workflowcontent")
               // console.log(this.workflowContentlog);
@@ -963,7 +963,7 @@ export default {
               window.clearInterval(intervalID);
             }
           });
-      }, 5000);
+      }, 3000);
     },
     podcontainerchange(e) {
       if (this.containertype == "main") {

+ 1 - 1
src/views/modules/visi/design-workflowlog.vue

@@ -122,7 +122,7 @@ export default {
               this.workflowStatus = data.workflowStatus;
               // this.handleLog();
               // this.podlogs = data.podlogs;
-              
+
               // console.log("workflowcontent");
               // console.log(this.workflowContent);
               // console.log(this.workflowContent.main);

+ 349 - 13
src/views/modules/visi/design.vue

@@ -6,13 +6,151 @@
     </el-breadcrumb>
     <el-divider class="divi"></el-divider>
     <!-- <design-graph></design-graph> -->
-    <design-graph-1></design-graph-1>
+    <el-form
+      :inline="true"
+      :model="dataForm"
+      @keyup.enter.native="getDataList()"
+    >
+      <el-form-item>
+        <el-button type="primary" @click="addHandle()">新建实验</el-button>
+        <el-button
+          type="danger"
+          @click="deleteHandle()" :disabled="dataListSelections.length <= 0">批量删除</el-button
+        >
+      </el-form-item>
+      <el-form-item>
+        <el-input
+          v-model="dataForm.workflowName"
+          placeholder="请输入实验名称"
+          clearable
+          @keyup.enter.native="
+            pageIndex = 1;
+            getDataList();
+          "
+        ></el-input>
+      </el-form-item>
+      <el-form-item>
+        <el-button
+          @click="
+            pageIndex = 1;
+            getDataList();
+          "
+          >查询</el-button
+        >
+      </el-form-item>
+
+    </el-form>
+
+    <el-table
+      :data="dataList"
+      border
+      v-loading="dataListLoading"
+      @selection-change="selectionChangeHandle"
+      style="width: 100%"
+    >
+      <el-table-column
+        type="selection"
+        header-align="center"
+        align="center"
+        width="50"
+      >
+      </el-table-column>
+      <!--      <el-table-column prop="datasetId" header-align="center" align="center" width="80" label="数据集ID">-->
+      <!--      </el-table-column>-->
+
+      <el-table-column
+        label="序号"
+        header-align="center"
+        align="center"
+        width="80"
+        type="index"
+        :index="
+          (index) => {
+            return index + 1 + (this.pageIndex - 1) * this.pageSize;
+          }
+        "
+      >
+      </el-table-column>
+
+      <el-table-column
+        prop="experimentName"
+        header-align="center"
+        align="center"
+        label="实验名称"
+      >
+      </el-table-column>
+
+      <!-- <el-table-column
+        prop="username"
+        header-align="center"
+        align="center"
+        label="创建人"
+      >
+      </el-table-column> -->
+      <el-table-column
+        prop="workflowtempName"
+        header-align="center"
+        align="center"
+        label="模板名称"
+      >
+      </el-table-column>
+      <el-table-column
+        prop="workflowName"
+        header-align="center"
+        align="center"
+
+        label="工作流名称"
+      >
+      </el-table-column>
+      <el-table-column
+        fixed="right"
+        header-align="center"
+        align="center"
+
+        label="操作"
+      >
+        <template slot-scope="scope">
+          <el-button
+            type="text"
+            size="small"
+            @click="addOrUpdateHandle(scope.row)"
+            >查看
+          </el-button>
+          <el-button
+            type="text"
+            size="small"
+            @click="addOrUpdateHandle(scope.row)"
+            >修改</el-button
+          >
+          <el-button
+            type="text"
+            size="small"
+            @click="deleteHandle(scope.row)"
+          >
+            删除</el-button
+          >
+        </template>
+      </el-table-column>
+    </el-table>
+    <el-pagination
+      @size-change="sizeChangeHandle"
+      @current-change="currentChangeHandle"
+      :current-page="pageIndex"
+      :page-sizes="[10, 20, 50, 100]"
+      :page-size="pageSize"
+      :total="totalPage"
+      layout="total, sizes, prev, pager, next, jumper"
+    >
+    </el-pagination>
   </div>
 </template>
 
 <script>
+import { info } from '../../../mock/modules/sys-menu';
 // import DesignGraph from "./design-graph.vue"
 import DesignGraph1 from "./design-graph1.vue";
+import { Message } from "element-ui";
+import { MessageBox } from "element-ui";
 export default {
   components: {
     // DesignGraph,
@@ -20,22 +158,220 @@ export default {
   },
   data() {
     return {
-      // chartLine: null,
-      // chartBar: null,
-      // chartPie: null,
-      // chartScatter: null,
+      dataForm: {
+        key: "",
+      },
+      username: this.$store.state.user.name,
+      dataList: [],
+      pageIndex: 1,
+      pageSize: 10,
+      totalPage: 0,
+      dataListLoading: false,
+      dataListSelections: [],
+      addOrUpdateVisible: false,
     };
   },
-  mounted() {
-    
-  },
+  mounted() {},
   activated() {
-    if (location.href.indexOf("#reloaded") == -1) {
-      location.href = location.href + "#reloaded";
-      location.reload();
-    }
+    // if (location.href.indexOf("#reloaded") == -1) {
+    //   location.href = location.href + "#reloaded";
+    //   location.reload();
+    // }
+    this.getDataList();
+  },
+  methods: {
+    addHandle() {
+      this.$router.replace({ path: "/design-create"  ,query: {
+                update: false
+              }});
+    },
+    getDataList() {
+      this.dataListLoading = true;
+      this.$http({
+        url: this.$http.adornUrl("/visi/visiworkflow/list"),
+        method: "get",
+        params: this.$http.adornParams({
+          page: this.pageIndex,
+          limit: this.pageSize,
+          key: this.dataForm.key,
+        }),
+      }).then(({ data }) => {
+        if (data && data.code === 0) {
+          this.dataList = data.page.list;
+          this.totalPage = data.page.totalCount;
+        } else {
+          this.dataList = [];
+          this.totalPage = 0;
+        }
+        this.dataListLoading = false;
+      });
+    },
+    // 筛选查询
+    getDataList2 () {
+      this.dataListLoading = true
+
+      if (this.status === '1') {
+        // 获取静态数据集
+        this.st_dataList = []
+        this.$http({
+          url: this.$http.adornUrl('/dataset/list'),
+          method: 'get',
+          params: this.$http.adornParams({
+            page: this.pageIndex,
+            limit: this.pageSize,
+            modelName: this.dataForm.modelName,
+            // 增加status参数用于筛选查询
+            classificationtag: this.classificationtag,
+            status: this.status
+          })
+        }).then(({ data }) => {
+          if (data && data.code === 0) {
+            this.st_dataList = data.page.list.reverse()
+            this.totalPage = data.page.totalCount
+          } else {
+            this.st_dataList = []
+            this.totalPage = 0
+          }
+          this.dataListLoading = false
+        })
+      } else {
+        this.dy_dataList = []
+        // 获取动态数据集
+        this.$http({
+          url: this.$http.adornUrl('/datasetdy/list'),
+          method: 'get',
+          params: this.$http.adornParams({
+            page: this.pageIndex,
+            limit: this.pageSize,
+            modelName: this.dataForm.modelName,
+            // 增加status参数用于筛选查询
+            classificationtag: this.classificationtag,
+            status: this.status
+          })
+        }).then(({ data }) => {
+          if (data && data.code === 0) {
+            this.dy_dataList = data.page.list.reverse()
+            this.totalPage = data.page.totalCount
+          } else {
+            this.dy_dataList = []
+            this.totalPage = 0
+          }
+          this.dataListLoading = false
+        })
+        this.dataListLoading = false
+      }
+    },
+    
+    // 每页数
+    sizeChangeHandle(val) {
+      this.pageSize = val;
+      this.pageIndex = 1;
+      this.getDataList();
+    },
+    // 当前页
+    currentChangeHandle(val) {
+      this.pageIndex = val;
+      this.getDataList();
+    },
+    // 多选
+    selectionChangeHandle(val) {
+      this.dataListSelections = val;
+    },
+    // 新增 / 修改
+    addOrUpdateHandle(info) {
+      // this.addOrUpdateVisible = true;
+      // this.$nextTick(() => {
+      //   this.$refs.addOrUpdate.init(info);
+      // });
+
+      this.$router.replace({ path: '/design-create' ,query: {
+                winfo: info,update: true
+              },})
+    },
+    // // 删除
+    // deleteHandle (info) {
+    //   var datasetId = info.datasetId
+    //     ? [info.datasetId] : this.dataListSelections.map((item) => {
+    //       return item.datasetId
+    //     })
+    //   var datasetName = info.datasetName ? [info.datasetName] : this.dataListSelections.map(item => {
+    //     return item.datasetName
+    //   })
+
+    //   MessageBox.confirm(
+    //     `确定对[数据集=${datasetName.join(' , ')}]进行[${info.datasetId ? '删除' : '批量删除'}]操作?`,
+    //     '提示',
+    //     {
+    //       confirmButtonText: '确定',
+    //       cancelButtonText: '取消',
+    //       type: 'warning'
+    //     }
+    //   )
+    //     .then(() => {
+    //       this.dataListLoading = true
+    //       this.$http({
+    //         url: this.$http.adornUrl('/dataset/delete'),
+    //         method: 'post',
+    //         data: this.$http.adornData(datasetId, false)
+    //       }).then(({ data }) => {
+    //         if (data && data.code === 0) {
+    //           this.dataListLoading = false
+    //           Message({
+    //             message: '操作成功',
+    //             type: 'success',
+    //             duration: 1500,
+    //             onClose: () => {
+    //               this.getDataList()
+    //             }
+    //           })
+    //           this.pageIndex = 1
+    //         } else {
+    //           Message.error(data.msg)
+    //         }
+    //       })
+    //     })
+    //     .catch(() => {})
+    // },
+    // 删除
+    deleteHandle(info) {
+      var ids = info.workflowId
+        ? [info.workflowId]
+        : this.dataListSelections.map((item) => {
+            return item.workflowId;
+          });
+      var experimentName = info.experimentName ? [info.experimentName] : this.dataListSelections.map(item => {
+        return item.experimentName
+      })
+      MessageBox.confirm(
+        `确定对[实验=${experimentName.join(' , ')}]进行[${info.workflowId ? "删除" : "批量删除"}]操作?`,
+        "提示",
+        {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning",
+        }
+      ).then(() => {
+        this.$http({
+          url: this.$http.adornUrl("/visi/visiworkflow/delete"),
+          method: "post",
+          data: this.$http.adornData(ids, false),
+        }).then(({ data }) => {
+          if (data && data.code === 0) {
+            this.$message({
+              message: "操作成功",
+              type: "success",
+              duration: 1500,
+              onClose: () => {
+                this.getDataList();
+              },
+            });
+          } else {
+            this.$message.error(data.msg);
+          }
+        });
+      });
+    },
   },
-  methods: {},
 };
 </script>
 

+ 2 - 1
src/views/new-menue.vue

@@ -282,7 +282,8 @@ export default {
 .site-navbar__brand {
     display: table-cell;
     vertical-align: middle;
-    width: 230px;
+    /*width: 230px;*/
+  width: 200px;
     height: 60px;
     margin: 0;
     line-height: 60px;

Неке датотеке нису приказане због велике количине промена