YaolongHan %!s(int64=4) %!d(string=hai) anos
pai
achega
9075eb193a

+ 257 - 9
package-lock.json

@@ -4,6 +4,28 @@
   "lockfileVersion": 1,
   "requires": true,
   "dependencies": {
+    "@ant-design/colors": {
+      "version": "3.2.2",
+      "resolved": "http://dev.dp.sagacloud.cn:8082/repository/npm-saga/@ant-design/colors/-/colors-3.2.2.tgz",
+      "integrity": "sha512-YKgNbG2dlzqMhA9NtI3/pbY16m3Yl/EeWBRa+lB1X1YaYxHrxNexiQYCLTWO/uDvAjLFMEDU+zR901waBtMtjQ==",
+      "requires": {
+        "tinycolor2": "^1.4.1"
+      }
+    },
+    "@ant-design/icons": {
+      "version": "2.1.1",
+      "resolved": "http://dev.dp.sagacloud.cn:8082/repository/npm-saga/@ant-design/icons/-/icons-2.1.1.tgz",
+      "integrity": "sha512-jCH+k2Vjlno4YWl6g535nHR09PwCEmTBKAG6VqF+rhkrSPRLfgpU2maagwbZPLjaHuU5Jd1DFQ2KJpQuI6uG8w=="
+    },
+    "@ant-design/icons-vue": {
+      "version": "2.0.0",
+      "resolved": "http://dev.dp.sagacloud.cn:8082/repository/npm-saga/@ant-design/icons-vue/-/icons-vue-2.0.0.tgz",
+      "integrity": "sha512-2c0QQE5hL4N48k5NkPG5sdpMl9YnvyNhf0U7YkdZYDlLnspoRU7vIA0UK9eHBs6OpFLcJB6o8eJrIl2ajBskPg==",
+      "requires": {
+        "@ant-design/colors": "^3.1.0",
+        "babel-runtime": "^6.26.0"
+      }
+    },
     "@babel/code-frame": {
       "version": "7.8.3",
       "resolved": "https://registry.npm.taobao.org/@babel/code-frame/download/@babel/code-frame-7.8.3.tgz",
@@ -1983,6 +2005,14 @@
       "integrity": "sha1-NF8N/61cc15zc9L+yaECPmpEuD4=",
       "dev": true
     },
+    "add-dom-event-listener": {
+      "version": "1.1.0",
+      "resolved": "http://dev.dp.sagacloud.cn:8082/repository/npm-saga/add-dom-event-listener/-/add-dom-event-listener-1.1.0.tgz",
+      "integrity": "sha512-WCxx1ixHT0GQU9hb0KI/mhgRQhnU+U3GvwY6ZvVjYq8rsihIGoaIOUbY0yMPBxLH5MDtr0kz3fisWGNcbWW7Jw==",
+      "requires": {
+        "object-assign": "4.x"
+      }
+    },
     "address": {
       "version": "1.1.2",
       "resolved": "https://registry.npm.taobao.org/address/download/address-1.1.2.tgz",
@@ -2073,6 +2103,42 @@
         "color-convert": "^1.9.0"
       }
     },
+    "ant-design-vue": {
+      "version": "1.6.0",
+      "resolved": "http://dev.dp.sagacloud.cn:8082/repository/npm-saga/ant-design-vue/-/ant-design-vue-1.6.0.tgz",
+      "integrity": "sha512-Mbm2woWBGUWdKEj9VHVI025BX5dMquL+9WCFyMjOBP2lAt0/kn0yA5ouuTk9NxgbHCo//Yuny7p6h3KpCHSEMw==",
+      "requires": {
+        "@ant-design/icons": "^2.1.1",
+        "@ant-design/icons-vue": "^2.0.0",
+        "add-dom-event-listener": "^1.0.2",
+        "array-tree-filter": "^2.1.0",
+        "async-validator": "^3.0.3",
+        "babel-helper-vue-jsx-merge-props": "^2.0.3",
+        "babel-runtime": "6.x",
+        "classnames": "^2.2.5",
+        "component-classes": "^1.2.6",
+        "dom-align": "^1.10.4",
+        "dom-closest": "^0.2.0",
+        "dom-scroll-into-view": "^2.0.0",
+        "enquire.js": "^2.1.6",
+        "intersperse": "^1.0.0",
+        "is-mobile": "^2.2.1",
+        "is-negative-zero": "^2.0.0",
+        "ismobilejs": "^1.0.0",
+        "json2mq": "^0.2.0",
+        "lodash": "^4.17.5",
+        "moment": "^2.21.0",
+        "mutationobserver-shim": "^0.3.2",
+        "node-emoji": "^1.10.0",
+        "omit.js": "^1.0.0",
+        "raf": "^3.4.0",
+        "resize-observer-polyfill": "^1.5.1",
+        "shallow-equal": "^1.0.0",
+        "shallowequal": "^1.0.2",
+        "vue-ref": "^2.0.0",
+        "warning": "^4.0.0"
+      }
+    },
     "any-promise": {
       "version": "1.3.0",
       "resolved": "https://registry.npm.taobao.org/any-promise/download/any-promise-1.3.0.tgz",
@@ -2134,6 +2200,11 @@
       "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=",
       "dev": true
     },
+    "array-tree-filter": {
+      "version": "2.1.0",
+      "resolved": "http://dev.dp.sagacloud.cn:8082/repository/npm-saga/array-tree-filter/-/array-tree-filter-2.1.0.tgz",
+      "integrity": "sha512-4ROwICNlNw/Hqa9v+rk5h22KjmzB1JGTMVKP2AKJBOCgb0yL0ASf0+YvCcLNNwquOHNX48jkeZIJ3a+oOQqKcw=="
+    },
     "array-union": {
       "version": "1.0.2",
       "resolved": "https://registry.npm.taobao.org/array-union/download/array-union-1.0.2.tgz",
@@ -2256,6 +2327,11 @@
       "integrity": "sha1-3TeelPDbgxCwgpH51kwyCXZmF/0=",
       "dev": true
     },
+    "async-validator": {
+      "version": "3.3.0",
+      "resolved": "http://dev.dp.sagacloud.cn:8082/repository/npm-saga/async-validator/-/async-validator-3.3.0.tgz",
+      "integrity": "sha512-cAHGD9EL8aCqWXjnb44q94MWiDFzUo1tMhvLb2WzcpWqGiKugsjWG9cvl+jPgkPca7asNbsBU3fa0cwkI/P+Xg=="
+    },
     "asynckit": {
       "version": "0.4.0",
       "resolved": "https://registry.npm.taobao.org/asynckit/download/asynckit-0.4.0.tgz",
@@ -2354,6 +2430,11 @@
         }
       }
     },
+    "babel-helper-vue-jsx-merge-props": {
+      "version": "2.0.3",
+      "resolved": "http://dev.dp.sagacloud.cn:8082/repository/npm-saga/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-2.0.3.tgz",
+      "integrity": "sha512-gsLiKK7Qrb7zYJNgiXKpXblxbV5ffSwR0f5whkPAaBAR4fhi6bwRZxX9wBlIc5M/v8CCkXUbXZL4N/nSE97cqg=="
+    },
     "babel-loader": {
       "version": "8.1.0",
       "resolved": "https://registry.npm.taobao.org/babel-loader/download/babel-loader-8.1.0.tgz?cache=0&sync_timestamp=1584715959282&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fbabel-loader%2Fdownload%2Fbabel-loader-8.1.0.tgz",
@@ -2376,6 +2457,27 @@
         "object.assign": "^4.1.0"
       }
     },
+    "babel-runtime": {
+      "version": "6.26.0",
+      "resolved": "http://dev.dp.sagacloud.cn:8082/repository/npm-saga/babel-runtime/-/babel-runtime-6.26.0.tgz",
+      "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
+      "requires": {
+        "core-js": "^2.4.0",
+        "regenerator-runtime": "^0.11.0"
+      },
+      "dependencies": {
+        "core-js": {
+          "version": "2.6.11",
+          "resolved": "http://dev.dp.sagacloud.cn:8082/repository/npm-saga/core-js/-/core-js-2.6.11.tgz",
+          "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg=="
+        },
+        "regenerator-runtime": {
+          "version": "0.11.1",
+          "resolved": "http://dev.dp.sagacloud.cn:8082/repository/npm-saga/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
+          "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg=="
+        }
+      }
+    },
     "balanced-match": {
       "version": "1.0.0",
       "resolved": "https://registry.npm.taobao.org/balanced-match/download/balanced-match-1.0.0.tgz",
@@ -3127,6 +3229,11 @@
         }
       }
     },
+    "classnames": {
+      "version": "2.2.6",
+      "resolved": "http://dev.dp.sagacloud.cn:8082/repository/npm-saga/classnames/-/classnames-2.2.6.tgz",
+      "integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q=="
+    },
     "clean-css": {
       "version": "4.2.3",
       "resolved": "https://registry.npm.taobao.org/clean-css/download/clean-css-4.2.3.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fclean-css%2Fdownload%2Fclean-css-4.2.3.tgz",
@@ -3353,12 +3460,25 @@
       "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=",
       "dev": true
     },
+    "component-classes": {
+      "version": "1.2.6",
+      "resolved": "http://dev.dp.sagacloud.cn:8082/repository/npm-saga/component-classes/-/component-classes-1.2.6.tgz",
+      "integrity": "sha1-xkI5TDYYpNiwuJGe/Mu9kw5c1pE=",
+      "requires": {
+        "component-indexof": "0.0.3"
+      }
+    },
     "component-emitter": {
       "version": "1.3.0",
       "resolved": "https://registry.npm.taobao.org/component-emitter/download/component-emitter-1.3.0.tgz",
       "integrity": "sha1-FuQHD7qK4ptnnyIVhT7hgasuq8A=",
       "dev": true
     },
+    "component-indexof": {
+      "version": "0.0.3",
+      "resolved": "http://dev.dp.sagacloud.cn:8082/repository/npm-saga/component-indexof/-/component-indexof-0.0.3.tgz",
+      "integrity": "sha1-EdCRMSI5648yyPJa6csAL/6NPCQ="
+    },
     "compressible": {
       "version": "2.0.18",
       "resolved": "https://registry.npm.taobao.org/compressible/download/compressible-2.0.18.tgz",
@@ -4329,6 +4449,19 @@
         "esutils": "^2.0.2"
       }
     },
+    "dom-align": {
+      "version": "1.11.1",
+      "resolved": "http://dev.dp.sagacloud.cn:8082/repository/npm-saga/dom-align/-/dom-align-1.11.1.tgz",
+      "integrity": "sha512-hN42DmUgtweBx0iBjDLO4WtKOMcK8yBmPx/fgdsgQadLuzPu/8co3oLdK5yMmeM/vnUd3yDyV6qV8/NzxBexQg=="
+    },
+    "dom-closest": {
+      "version": "0.2.0",
+      "resolved": "http://dev.dp.sagacloud.cn:8082/repository/npm-saga/dom-closest/-/dom-closest-0.2.0.tgz",
+      "integrity": "sha1-69n5HRvyLo1vR3h2u80+yQIWwM8=",
+      "requires": {
+        "dom-matches": ">=1.0.1"
+      }
+    },
     "dom-converter": {
       "version": "0.2.0",
       "resolved": "https://registry.npm.taobao.org/dom-converter/download/dom-converter-0.2.0.tgz",
@@ -4338,6 +4471,16 @@
         "utila": "~0.4"
       }
     },
+    "dom-matches": {
+      "version": "2.0.0",
+      "resolved": "http://dev.dp.sagacloud.cn:8082/repository/npm-saga/dom-matches/-/dom-matches-2.0.0.tgz",
+      "integrity": "sha1-0nKLQWqHUzmA6wibhI0lPPI6dYw="
+    },
+    "dom-scroll-into-view": {
+      "version": "2.0.1",
+      "resolved": "http://dev.dp.sagacloud.cn:8082/repository/npm-saga/dom-scroll-into-view/-/dom-scroll-into-view-2.0.1.tgz",
+      "integrity": "sha512-bvVTQe1lfaUr1oFzZX80ce9KLDlZ3iU+XGNE/bz9HnGdklTieqsbmsLHe+rT2XWqopvL0PckkYqN7ksmm5pe3w=="
+    },
     "dom-serializer": {
       "version": "0.2.2",
       "resolved": "https://registry.npm.taobao.org/dom-serializer/download/dom-serializer-0.2.2.tgz",
@@ -4533,6 +4676,11 @@
         }
       }
     },
+    "enquire.js": {
+      "version": "2.1.6",
+      "resolved": "http://dev.dp.sagacloud.cn:8082/repository/npm-saga/enquire.js/-/enquire.js-2.1.6.tgz",
+      "integrity": "sha1-PoeAybi4NQhMP2DhZtvDwqPImBQ="
+    },
     "entities": {
       "version": "2.0.2",
       "resolved": "https://registry.npm.taobao.org/entities/download/entities-2.0.2.tgz?cache=0&sync_timestamp=1589061925947&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fentities%2Fdownload%2Fentities-2.0.2.tgz",
@@ -6247,6 +6395,11 @@
         }
       }
     },
+    "intersperse": {
+      "version": "1.0.0",
+      "resolved": "http://dev.dp.sagacloud.cn:8082/repository/npm-saga/intersperse/-/intersperse-1.0.0.tgz",
+      "integrity": "sha1-8lYfsc/vn1J3zDNHoiiGtDUaUYE="
+    },
     "invariant": {
       "version": "2.2.4",
       "resolved": "https://registry.npm.taobao.org/invariant/download/invariant-2.2.4.tgz",
@@ -6440,6 +6593,16 @@
         "is-extglob": "^2.1.1"
       }
     },
+    "is-mobile": {
+      "version": "2.2.1",
+      "resolved": "http://dev.dp.sagacloud.cn:8082/repository/npm-saga/is-mobile/-/is-mobile-2.2.1.tgz",
+      "integrity": "sha512-6zELsfVFr326eq2CI53yvqq6YBanOxKBybwDT+MbMS2laBnK6Ez8m5XHSuTQQbnKRfpDzCod1CMWW5q3wZYMvA=="
+    },
+    "is-negative-zero": {
+      "version": "2.0.0",
+      "resolved": "http://dev.dp.sagacloud.cn:8082/repository/npm-saga/is-negative-zero/-/is-negative-zero-2.0.0.tgz",
+      "integrity": "sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE="
+    },
     "is-number": {
       "version": "3.0.0",
       "resolved": "https://registry.npm.taobao.org/is-number/download/is-number-3.0.0.tgz",
@@ -6574,6 +6737,11 @@
       "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
       "dev": true
     },
+    "ismobilejs": {
+      "version": "1.1.1",
+      "resolved": "http://dev.dp.sagacloud.cn:8082/repository/npm-saga/ismobilejs/-/ismobilejs-1.1.1.tgz",
+      "integrity": "sha512-VaFW53yt8QO61k2WJui0dHf4SlL8lxBofUuUmwBo0ljPk0Drz2TiuDW4jo3wDcv41qy/SxrJ+VAzJ/qYqsmzRw=="
+    },
     "isobject": {
       "version": "3.0.1",
       "resolved": "https://registry.npm.taobao.org/isobject/download/isobject-3.0.1.tgz",
@@ -6637,8 +6805,7 @@
     "js-tokens": {
       "version": "4.0.0",
       "resolved": "https://registry.npm.taobao.org/js-tokens/download/js-tokens-4.0.0.tgz",
-      "integrity": "sha1-GSA/tZmR35jjoocFDUZHzerzJJk=",
-      "dev": true
+      "integrity": "sha1-GSA/tZmR35jjoocFDUZHzerzJJk="
     },
     "js-yaml": {
       "version": "3.13.1",
@@ -6692,6 +6859,14 @@
       "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=",
       "dev": true
     },
+    "json2mq": {
+      "version": "0.2.0",
+      "resolved": "http://dev.dp.sagacloud.cn:8082/repository/npm-saga/json2mq/-/json2mq-0.2.0.tgz",
+      "integrity": "sha1-tje9O6nqvhIsg+lyBIOusQ0skEo=",
+      "requires": {
+        "string-convert": "^0.2.0"
+      }
+    },
     "json3": {
       "version": "3.3.3",
       "resolved": "https://registry.npm.taobao.org/json3/download/json3-3.3.3.tgz",
@@ -6941,8 +7116,7 @@
     "lodash": {
       "version": "4.17.15",
       "resolved": "https://registry.npm.taobao.org/lodash/download/lodash-4.17.15.tgz",
-      "integrity": "sha1-tEf2ZwoEVbv+7dETku/zMOoJdUg=",
-      "dev": true
+      "integrity": "sha1-tEf2ZwoEVbv+7dETku/zMOoJdUg="
     },
     "lodash.defaultsdeep": {
       "version": "4.6.1",
@@ -6968,6 +7142,11 @@
       "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=",
       "dev": true
     },
+    "lodash.toarray": {
+      "version": "4.4.0",
+      "resolved": "http://dev.dp.sagacloud.cn:8082/repository/npm-saga/lodash.toarray/-/lodash.toarray-4.4.0.tgz",
+      "integrity": "sha1-JMS/zWsvuji/0FlNsRedjptlZWE="
+    },
     "lodash.transform": {
       "version": "4.6.0",
       "resolved": "https://registry.npm.taobao.org/lodash.transform/download/lodash.transform-4.6.0.tgz",
@@ -6999,7 +7178,6 @@
       "version": "1.4.0",
       "resolved": "https://registry.npm.taobao.org/loose-envify/download/loose-envify-1.4.0.tgz",
       "integrity": "sha1-ce5R+nvkyuwaY4OffmgtgTLTDK8=",
-      "dev": true,
       "requires": {
         "js-tokens": "^3.0.0 || ^4.0.0"
       }
@@ -7346,6 +7524,11 @@
         "minimist": "^1.2.5"
       }
     },
+    "moment": {
+      "version": "2.26.0",
+      "resolved": "http://dev.dp.sagacloud.cn:8082/repository/npm-saga/moment/-/moment-2.26.0.tgz",
+      "integrity": "sha512-oIixUO+OamkUkwjhAVE18rAMfRJNsNe/Stid/gwHSOfHrOtw9EhAY2AHvdKZ/k/MggcYELFCJz/Sn2pL8b8JMw=="
+    },
     "move-concurrently": {
       "version": "1.0.1",
       "resolved": "https://registry.npm.taobao.org/move-concurrently/download/move-concurrently-1.0.1.tgz",
@@ -7382,6 +7565,11 @@
       "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=",
       "dev": true
     },
+    "mutationobserver-shim": {
+      "version": "0.3.5",
+      "resolved": "http://dev.dp.sagacloud.cn:8082/repository/npm-saga/mutationobserver-shim/-/mutationobserver-shim-0.3.5.tgz",
+      "integrity": "sha512-YAMuSp4Oi19SYQF04dGnRajyFp4Wyam+jKKWzm5roPcNh1Rip8dnHPxls5F/xBgY0H2gV+3IzWuIvYQPDAvmBQ=="
+    },
     "mute-stream": {
       "version": "0.0.8",
       "resolved": "https://registry.npm.taobao.org/mute-stream/download/mute-stream-0.0.8.tgz",
@@ -7458,6 +7646,14 @@
         "lower-case": "^1.1.1"
       }
     },
+    "node-emoji": {
+      "version": "1.10.0",
+      "resolved": "http://dev.dp.sagacloud.cn:8082/repository/npm-saga/node-emoji/-/node-emoji-1.10.0.tgz",
+      "integrity": "sha512-Yt3384If5H6BYGVHiHwTL+99OzJKHhgp82S8/dktEK73T26BazdgZ4JZh92xSVtGNJvz9UbXdNAc5hcrXV42vw==",
+      "requires": {
+        "lodash.toarray": "^4.4.0"
+      }
+    },
     "node-forge": {
       "version": "0.9.0",
       "resolved": "https://registry.npm.taobao.org/node-forge/download/node-forge-0.9.0.tgz",
@@ -7583,8 +7779,7 @@
     "object-assign": {
       "version": "4.1.1",
       "resolved": "https://registry.npm.taobao.org/object-assign/download/object-assign-4.1.1.tgz",
-      "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
-      "dev": true
+      "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
     },
     "object-copy": {
       "version": "0.1.0",
@@ -7703,6 +7898,14 @@
       "integrity": "sha1-Cb6jND1BhZ69RGKS0RydTbYZCE4=",
       "dev": true
     },
+    "omit.js": {
+      "version": "1.0.2",
+      "resolved": "http://dev.dp.sagacloud.cn:8082/repository/npm-saga/omit.js/-/omit.js-1.0.2.tgz",
+      "integrity": "sha512-/QPc6G2NS+8d4L/cQhbk6Yit1WTB6Us2g84A7A/1+w9d/eRGHyEqC5kkQtHVoHZ5NFWGG7tUGgrhVZwgZanKrQ==",
+      "requires": {
+        "babel-runtime": "^6.23.0"
+      }
+    },
     "on-finished": {
       "version": "2.3.0",
       "resolved": "https://registry.npm.taobao.org/on-finished/download/on-finished-2.3.0.tgz",
@@ -8045,8 +8248,7 @@
     "performance-now": {
       "version": "2.1.0",
       "resolved": "https://registry.npm.taobao.org/performance-now/download/performance-now-2.1.0.tgz",
-      "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=",
-      "dev": true
+      "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
     },
     "picomatch": {
       "version": "2.2.2",
@@ -8957,6 +9159,14 @@
       "integrity": "sha1-YOWl/WSn+L+k0qsu1v30yFutFU4=",
       "dev": true
     },
+    "raf": {
+      "version": "3.4.1",
+      "resolved": "http://dev.dp.sagacloud.cn:8082/repository/npm-saga/raf/-/raf-3.4.1.tgz",
+      "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==",
+      "requires": {
+        "performance-now": "^2.1.0"
+      }
+    },
     "randombytes": {
       "version": "2.1.0",
       "resolved": "https://registry.npm.taobao.org/randombytes/download/randombytes-2.1.0.tgz",
@@ -9272,6 +9482,11 @@
       "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=",
       "dev": true
     },
+    "resize-observer-polyfill": {
+      "version": "1.5.1",
+      "resolved": "http://dev.dp.sagacloud.cn:8082/repository/npm-saga/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz",
+      "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg=="
+    },
     "resolve": {
       "version": "1.17.0",
       "resolved": "https://registry.npm.taobao.org/resolve/download/resolve-1.17.0.tgz",
@@ -9614,6 +9829,16 @@
         "safe-buffer": "^5.0.1"
       }
     },
+    "shallow-equal": {
+      "version": "1.2.1",
+      "resolved": "http://dev.dp.sagacloud.cn:8082/repository/npm-saga/shallow-equal/-/shallow-equal-1.2.1.tgz",
+      "integrity": "sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA=="
+    },
+    "shallowequal": {
+      "version": "1.1.0",
+      "resolved": "http://dev.dp.sagacloud.cn:8082/repository/npm-saga/shallowequal/-/shallowequal-1.1.0.tgz",
+      "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ=="
+    },
     "shebang-command": {
       "version": "1.2.0",
       "resolved": "https://registry.npm.taobao.org/shebang-command/download/shebang-command-1.2.0.tgz",
@@ -10111,6 +10336,11 @@
       "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=",
       "dev": true
     },
+    "string-convert": {
+      "version": "0.2.1",
+      "resolved": "http://dev.dp.sagacloud.cn:8082/repository/npm-saga/string-convert/-/string-convert-0.2.1.tgz",
+      "integrity": "sha1-aYLMMEn7tM2F+LJFaLnZvznu/5c="
+    },
     "string-width": {
       "version": "4.2.0",
       "resolved": "https://registry.npm.taobao.org/string-width/download/string-width-4.2.0.tgz",
@@ -10453,6 +10683,11 @@
       "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=",
       "dev": true
     },
+    "tinycolor2": {
+      "version": "1.4.1",
+      "resolved": "http://dev.dp.sagacloud.cn:8082/repository/npm-saga/tinycolor2/-/tinycolor2-1.4.1.tgz",
+      "integrity": "sha1-9PrTM0R7wLB9TcjpIJ2POaisd+g="
+    },
     "tmp": {
       "version": "0.0.33",
       "resolved": "https://registry.npm.taobao.org/tmp/download/tmp-0.0.33.tgz?cache=0&sync_timestamp=1588178571895&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ftmp%2Fdownload%2Ftmp-0.0.33.tgz",
@@ -11101,6 +11336,11 @@
         "vue-class-component": "^7.1.0"
       }
     },
+    "vue-ref": {
+      "version": "2.0.0",
+      "resolved": "http://dev.dp.sagacloud.cn:8082/repository/npm-saga/vue-ref/-/vue-ref-2.0.0.tgz",
+      "integrity": "sha512-uKNKpFOVeWNqS2mrBZqnpLyXJo5Q+vnkex6JvpENvhXHFNBW/SJTP8vJywLuVT3DpxwXcF9N0dyIiZ4/NpTexQ=="
+    },
     "vue-router": {
       "version": "3.2.0",
       "resolved": "https://registry.npm.taobao.org/vue-router/download/vue-router-3.2.0.tgz",
@@ -11145,6 +11385,14 @@
       "resolved": "https://registry.npm.taobao.org/vuex/download/vuex-3.4.0.tgz",
       "integrity": "sha1-IMwIYGLXUHafzh/rs05/zurr3kU="
     },
+    "warning": {
+      "version": "4.0.3",
+      "resolved": "http://dev.dp.sagacloud.cn:8082/repository/npm-saga/warning/-/warning-4.0.3.tgz",
+      "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==",
+      "requires": {
+        "loose-envify": "^1.0.0"
+      }
+    },
     "watchpack": {
       "version": "1.7.2",
       "resolved": "https://registry.npm.taobao.org/watchpack/download/watchpack-1.7.2.tgz",

+ 2 - 0
package.json

@@ -8,6 +8,7 @@
     "lint": "vue-cli-service lint"
   },
   "dependencies": {
+    "ant-design-vue": "^1.6.0",
     "core-js": "^3.6.4",
     "vue": "^2.6.11",
     "vue-class-component": "^7.2.3",
@@ -30,6 +31,7 @@
     "less": "^3.0.4",
     "less-loader": "^5.0.0",
     "typescript": "~3.8.3",
+    "vue-svg-loader": "^0.15.0",
     "vue-template-compiler": "^2.6.11"
   }
 }

+ 12 - 22
src/App.vue

@@ -1,32 +1,22 @@
 <template>
   <div id="app">
-    <div id="nav">
-      <router-link to="/">Home</router-link> |
-      <router-link to="/about">About</router-link>
-    </div>
-    <router-view/>
+    <router-view />
   </div>
 </template>
 
 <style lang="less">
 #app {
-  font-family: Avenir, Helvetica, Arial, sans-serif;
-  -webkit-font-smoothing: antialiased;
-  -moz-osx-font-smoothing: grayscale;
-  text-align: center;
-  color: #2c3e50;
+  width: 100%;
+  height: 100%;
 }
-
-#nav {
-  padding: 30px;
-
-  a {
-    font-weight: bold;
-    color: #2c3e50;
-
-    &.router-link-exact-active {
-      color: #42b983;
-    }
-  }
+html {
+  margin: 0;
+  width: 100%;
+  height: 100%;
+}
+body {
+  margin: 0;
+  width: 100%;
+  height: 100%
 }
 </style>

BIN=BIN
src/assets/images/t-select.png


+ 0 - 61
src/components/HelloWorld.vue

@@ -1,61 +0,0 @@
-<template>
-  <div class="hello">
-    <h1>{{ msg }}</h1>
-    <p>
-      For a guide and recipes on how to configure / customize this project,<br>
-      check out the
-      <a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
-    </p>
-    <h3>Installed CLI Plugins</h3>
-    <ul>
-      <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li>
-      <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-typescript" target="_blank" rel="noopener">typescript</a></li>
-      <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint" target="_blank" rel="noopener">eslint</a></li>
-      <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-router" target="_blank" rel="noopener">router</a></li>
-      <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-vuex" target="_blank" rel="noopener">vuex</a></li>
-    </ul>
-    <h3>Essential Links</h3>
-    <ul>
-      <li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
-      <li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
-      <li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
-      <li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
-      <li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
-    </ul>
-    <h3>Ecosystem</h3>
-    <ul>
-      <li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
-      <li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
-      <li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
-      <li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
-      <li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
-    </ul>
-  </div>
-</template>
-
-<script lang="ts">
-import { Component, Prop, Vue } from 'vue-property-decorator';
-
-@Component
-export default class HelloWorld extends Vue {
-  @Prop() private msg!: string;
-}
-</script>
-
-<!-- Add "scoped" attribute to limit CSS to this component only -->
-<style scoped lang="less">
-h3 {
-  margin: 40px 0 0;
-}
-ul {
-  list-style-type: none;
-  padding: 0;
-}
-li {
-  display: inline-block;
-  margin: 0 10px;
-}
-a {
-  color: #42b983;
-}
-</style>

+ 250 - 0
src/components/Tree/Tree.vue

@@ -0,0 +1,250 @@
+<template>
+  <div class="p-tree">
+    <TreeNode
+      :multiple="multiple"
+      :linkage="linkage"
+      :lastStage="lastStage"
+      v-for="(item, ind) in treeData"
+      :key="item.id+'-'+ind"
+      :treeItem="item"
+      :triangleShow="!!(item.children&&item.children.length)"
+      :index="String(ind)"
+      :change="change"
+      :leftPosition="leftPosition"
+    />
+  </div>
+</template>
+
+<script>
+import TreeNode from "./depend/treeNode";
+export default {
+  name: "Tree",
+  components: { TreeNode },
+  props: {
+    /**
+     * 是否开启多选
+     */
+    multiple: {
+      type: Boolean,
+      default: false
+    },
+    /**
+     * 是否联动选择
+     */
+    linkage: {
+      type: Boolean,
+      default: true
+    },
+    /**
+     * 只能选择末级
+     */
+    lastStage: {
+      type: Boolean,
+      default: false
+    },
+    /**
+     * 是否返回半选状态的id
+     */
+    notNull: {
+      type: Boolean,
+      default: false
+    },
+    /**
+     * 树形结构数据列表
+     */
+    data: {
+      type: Array,
+      default: () => []
+    },
+    // 左侧距离
+    leftPosition: {
+      type: Number,
+      default: 12
+    }
+  },
+  computed: {
+    treeData: {
+      get() {
+        return this.data;
+      },
+      set(newData) {
+        return newData;
+      }
+    }
+  },
+  methods: {
+    /**
+     * 点击某项
+     * @param obj 返回当前点击对象
+     * @param index 索引串
+     */
+    change(obj, index) {
+      const { id } = obj;
+      if (this.multiple) {
+        const iArr = index.split("-"); // 拿到索引值
+        iArr.pop(); // 这里不需要遍历最后一个索引的数据
+        const data = this.treeData;
+        if (this.linkage) this.changeParentChecked(data, iArr);
+        const checkedObj = this.filterIds(data);
+        const checkedIds = checkedObj.map(d => d.id);
+        /**
+         * 点击某项返回的数据
+         * @param id
+         * @param checkedIds 选择的id组,多选时才返回
+         * @param obj 选择的当前对象,多选时才返回
+         * @param checkedObj 选择的对象组,多选时才返回
+         * @type Function
+         */
+        this.$emit("change", { id, checkedIds, obj, checkedObj });
+      } else {
+        this.treeData = this.changeCheckedItem(this.treeData, id);
+        /**
+         * 点击某项返回的数据
+         * @param id
+         * @type Function
+         */
+        this.$emit("change", obj);
+      }
+    },
+    /**
+     * 单选改变状态
+     * @param data
+     * @param id
+     * @return {*}
+     */
+    changeCheckedItem(data, id) {
+      return data.map(d => {
+        if (d.id === id) {
+          d.checked = "checked";
+        } else {
+          d.checked = "uncheck";
+        }
+        if (d.children && d.children.length)
+          d.children = this.changeCheckedItem(d.children, id);
+        return d;
+      });
+    },
+    /**
+     * 递归筛选子项有选中的数据
+     * @param data
+     * @param iArr
+     * @param curr 筛选到的数据放入数组
+     */
+    currentData(data, iArr, curr) {
+      const ind = iArr.shift();
+      data.forEach((d, i) => {
+        if (ind && i === Number(ind)) {
+          curr.unshift(d);
+          if (d.children && d.children.length)
+            this.currentData(d.children, iArr, curr);
+        }
+      });
+    },
+    /**
+     *  筛选选中的id
+     */
+    filterIds(data) {
+      const arr = [];
+      this.recursionIds(data, arr);
+
+      return arr;
+    },
+    /**
+     * 筛选选中的id
+     * @param data
+     * @param arr
+     */
+    recursionIds(data, arr) {
+      data.forEach(d => {
+        if (this.notNull) {
+          if (d.checked === "checked" || d.checked === "notNull") arr.push(d);
+        } else {
+          if (d.checked === "checked") arr.push(d);
+        }
+        if (d.children && d.children.length) this.recursionIds(d.children, arr);
+      });
+    }
+  }
+};
+</script>
+
+<style lang="less">
+.p-tree {
+  width: 100%;
+  overflow-x: hidden;
+  font-size: 0;
+}
+.p-tree-node {
+  width: 100%;
+}
+
+.p-tree-node-content {
+  position: relative;
+  width: 100%;
+  cursor: pointer;
+  &:hover {
+    background-color: #f5f6f7;
+  }
+  &.p-tree-node-content-checked {
+    background-color: #e1f2ff;
+    .p-tree-node-check {
+      .p-tree-node-title {
+        .p-tree-node-name {
+          color: #0091ff;
+        }
+      }
+    }
+  }
+}
+
+.p-tree-svg {
+  display: inline-block;
+  vertical-align: middle;
+  margin-right: 8px;
+  width: 16px;
+  height: 16px;
+  line-height: 16px;
+  text-align: center;
+  .p-tree-icon-svg {
+    vertical-align: text-bottom;
+    transform: rotate(90deg);
+    transition: transform 0.3s;
+  }
+
+  .p-tree-icon-rotate {
+    transform: rotate(180deg);
+  }
+}
+.p-tree-node-check {
+  display: inline-block;
+  vertical-align: middle;
+  width: calc(100% - 24px);
+  .p-tree-node-title {
+    position: relative;
+    display: inline-block;
+    vertical-align: middle;
+    user-select: none;
+    width: calc(100% - 24px);
+    .p-tree-node-name {
+      width: 100%;
+      height: 38px;
+      line-height: 38px;
+      white-space: nowrap;
+      text-overflow: ellipsis;
+      overflow: hidden;
+      font-size: 14px;
+      color: #1F2329;
+    }
+  }
+}
+.p-tree-node-content-disabled {
+  // pointer-events none
+  cursor: pointer;
+  .p-tree-node-name {
+    color: #004275 !important;
+  }
+}
+.p-tree-child {
+  width: 100%;
+}
+</style>

+ 14 - 0
src/components/Tree/depend/arrow_triangle.svg

@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <path
+            fill="#C3C6CB"
+            d="
+                M7.36397105,6.47904167
+                C7.71544566,6.05570759 8.29167643,6.06338938 8.63677321,6.47904167
+                L10.9236602,9.23348584
+                C11.2751348,9.65681992 11.1147123,10 10.555128,10
+                L5.44561621,10 C4.89060692,10 4.7319873,9.64913813 5.07708407,9.23348584
+                L7.36397105,6.47904167
+                Z"
+    ></path>
+</svg>

+ 172 - 0
src/components/Tree/depend/treeNode.vue

@@ -0,0 +1,172 @@
+<template>
+	<div class="p-tree-node">
+		<div
+			:class="['p-tree-node-content', !multiple&&treeItem.checked==='checked'&&'p-tree-node-content-checked', treeItem.disabled&&'p-tree-node-content-disabled']"
+			:style="{paddingLeft: paddingLeft+'px'}"
+		>
+			<section class="p-tree-svg" @click="openChild" >
+				<ArrowTriangle
+					:class="['p-tree-icon-svg', (treeItem.open)&&'p-tree-icon-rotate']"
+					v-if="triangleShow"
+				/>
+			</section>
+			<div class="p-tree-node-check" @click="handleCheck(treeItem, index)">
+					<!-- v-if="multiple&&(!lastStage||!triangleShow)" -->
+				<section class="p-tree-node-title">
+					<article class="p-tree-node-name" @mouseenter="treeItemEnter" v-html="treeItem.name" />
+				</section>
+			</div>
+		</div>
+		<div class="p-tree-child" v-if="triangleShow" v-show="treeItem.open">
+			<TreeNode
+				:multiple="multiple"
+				:linkage="linkage"
+				:lastStage="lastStage"
+				v-for="(item, ind) in treeItem.children"
+				:key="item.id+'-'+ind"
+				:treeItem="item"
+				:triangleShow="!!(item.children&&item.children.length)"
+				:index="`${index}-${ind}`"
+				:change="change"
+				:leftPosition="leftPosition"
+			/>
+		</div>
+	</div>
+</template>
+
+<script>
+    import ArrowTriangle from './arrow_triangle.svg';
+    export default {
+        name: 'TreeNode',
+        components: { ArrowTriangle},
+        props: {
+            /**
+             * 是否开启多选
+             */
+            multiple: {
+                type: Boolean,
+                default: false
+            },
+            /**
+             * 是否联动选择
+             */
+            linkage: {
+                type: Boolean,
+                default: true
+            },
+            /**
+             * 只能选择末级
+             */
+            lastStage: {
+                type: Boolean,
+                default: false
+            },
+            /**
+             * 树形结构子项数据列表
+             */
+            treeItem: {
+                type: Object,
+                default: {}
+            },
+            /**
+             * 点击某项
+             */
+            change: {
+                type: Function,
+                default: () => false
+            },
+            /**
+             * 下拉三角形是否显示
+             */
+            triangleShow: {
+                type: Boolean,
+                default: false
+            },
+            /**
+             * 索引
+             */
+            index: {
+                type: String,
+                default: ''
+			},
+			leftPosition: {
+				type: Number,
+				default: 12
+			}
+        },
+        computed: {
+            // 左边内边距
+            paddingLeft() {
+                return (this.index.split('-').length-1)*24+Number(this.leftPosition);
+			},
+
+			checkboxShow() {
+                const item = this.treeItem
+                debugger
+				// const flag = item.hasOwnProperty('isleaf') ? item.isleaf : true
+				return this.multiple && (!this.triangleShow || !this.lastStage) && flag
+			}
+		},
+        methods: {
+            // 展开/收起
+            openChild() {
+                // if (!this.disabledOpen && this.treeItem.disabled ) return
+                this.treeItem.open=!this.treeItem.open
+            },
+            // 鼠标hover
+            treeItemEnter(e) {
+                const target=e.target;
+                const {clientWidth, scrollWidth, title}=target;
+                if (!title && scrollWidth > clientWidth) target.title=target.innerText;
+            },
+            // 选择
+            handleCheck(obj, index) {
+                if (obj.disabled) return;
+                if (this.multiple) {
+					if(this.checkboxShow) {
+						let status='';
+						const treeItem=this.treeItem;
+						const {checked, children}=treeItem;
+
+						if (checked === 'checked') {
+							status='uncheck';
+						} else {
+							//  if (checked === 'uncheck' || checked === 'notNull')
+							status='checked';
+						}
+
+						if (this.linkage) {
+							// 上下级联动
+							if (children && children.length) treeItem.children=this.setCheckedStatus(children, status);
+
+							treeItem.checked=status;
+							this.treeItem=treeItem;
+							this.change(obj, index);
+						} else {
+							// 上下级不联动 this.lastStage为true-表示只能选择末级节点
+							if (this.lastStage && children && children.length) return;
+							this.treeItem=treeItem;
+							treeItem.checked=status;
+
+							this.change(obj, index);
+						}
+					}
+                } else {
+					// const notLastNode = obj.hasOwnProperty('children') || (obj.hasOwnProperty('isleaf') ? !obj.isleaf : false)
+					if(this.lastStage && notLastNode) return
+                    // 执行父级的函数
+                    this.change(obj, index);
+                }
+            },
+            // 设置checked状态
+            setCheckedStatus(data, status) {
+                return data.map(d => {
+                    d.checked=status;
+                    if (d.children && d.children.length)
+                        d.children=this.setCheckedStatus(d.children, status);
+                    return d;
+                })
+            }
+        }
+    }
+</script>

+ 10 - 0
src/components/baseEditer.vue

@@ -0,0 +1,10 @@
+<template>
+  <div id="baseEditer"></div>
+</template>
+<style lang="less" scoped>
+#baseEditer {
+  background: #ccc;
+  width: 100%;
+  height: 100%;
+}
+</style>

+ 165 - 0
src/components/edit/left_toolbar.vue

@@ -0,0 +1,165 @@
+<template>
+  <div id="left_toolbar">
+    <ul class="list-1">
+      <li>
+        <div class="item">
+          <img src="./../../assets/images/t-select.png" alt />
+        </div>
+      </li>
+      <li>
+        <div class="item">
+          <img src="./../../assets/images/t-select.png" alt />
+        </div>
+        <div class="tooltip">
+          <a-card style="width: 300px">
+            <p>Card content</p>
+            <p>Card content</p>
+            <p>Card content</p>
+          </a-card>
+        </div>
+      </li>
+      <li>
+        <div class="item">
+          <img src="./../../assets/images/t-select.png" alt />
+        </div>
+      </li>
+      <li>
+        <div class="item">
+          <img src="./../../assets/images/t-select.png" alt />
+        </div>
+      </li>
+    </ul>
+    <ul class="list-2">
+      <li>
+        <div class="item">
+          <a-icon type="team" />
+          <div>消防系统</div>
+        </div>
+        <div class="tooltip">
+          <a-card style="width: 300px">
+            <p>Card content</p>
+            <p>Card content</p>
+            <p>Card content</p>
+          </a-card>
+        </div>
+      </li>
+      <li>
+        <div class="item">
+          <a-icon type="team" />
+          <div>弱电系统</div>
+        </div>
+      </li>
+      <li>
+        <div class="item">
+          <a-icon type="team" />
+          <div>暖通系统</div>
+        </div>
+      </li>
+      <li>
+        <div class="item">
+          <a-icon type="team" />
+          <div>电梯系统</div>
+        </div>
+      </li>
+    </ul>
+    <div class="bottom-item">
+      <a-icon type="ellipsis" />
+      <span>选择原件</span>
+    </div>
+  </div>
+</template>
+<style lang="less">
+#left_toolbar {
+  width: 68px;
+  height: 707px;
+  background: rgba(255, 255, 255, 1);
+  box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.11);
+  padding: 0 0 12px 0;
+  box-sizing: border-box;
+  position: relative;
+  ul,
+  li {
+    padding: 0;
+    margin: 0;
+    list-style: none;
+  }
+  .list-1 {
+    padding-top: 1px;
+    box-sizing: border-box;
+    border-bottom: 1px solid #c3c7cb;
+    li {
+      width: 64px;
+      min-height: 42px;
+      margin: 6px auto;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      position: relative;
+      .item {
+        margin: 0 auto;
+        display: flex;
+        flex-direction: column;
+        position: relative;
+        cursor: pointer;
+      }
+      &:hover {
+        background: #e1f2ff;
+        border-radius: 8px;
+        opacity: 0.89;
+        color: #fff;
+      }
+      .tooltip {
+        position: absolute;
+        left: 90px;
+        top: 0;
+      }
+    }
+  }
+  .list-2 {
+    padding-top: 1px;
+    box-sizing: border-box;
+    li {
+      width: 64px;
+      min-height: 42px;
+      margin: 6px auto;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      position: relative;
+      .item {
+        margin: 0 auto;
+        display: flex;
+        flex-direction: column;
+        position: relative;
+        cursor: pointer;
+      }
+      &:hover {
+        background: #e1f2ff;
+        border-radius: 8px;
+        opacity: 0.89;
+        color: #fff;
+      }
+      .tooltip {
+        position: absolute;
+        left: 90px;
+        top: 0;
+      }
+    }
+  }
+  .bottom-item {
+    position: absolute;
+    font-size: 18px;
+    width: 100%;
+    bottom: 12px;
+    left: 0;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    flex-direction: column;
+    cursor: pointer;
+    span {
+      font-size: 12px;
+    }
+  }
+}
+</style>

+ 75 - 0
src/components/edit/right_toolbar.vue

@@ -0,0 +1,75 @@
+<template>
+  <div id="right_toolbar">
+    <!-- 右侧侧编辑器 -->
+    <a-tabs default-active-key="1" @change="callback">
+      <a-tab-pane key="1" tab="属性">
+        <div class="property">
+          <ul class="formatting">
+            <li v-for="i in 6" :key="i">a</li>
+          </ul>
+          <ul class="position">
+            <li v-for="i in 5" :key="i">
+              <a-input size="small" placeholder="" suffix="x"/>
+            </li>
+          </ul>
+        </div>
+      </a-tab-pane>
+      <a-tab-pane key="2" tab="元素" force-render>Content of Tab Pane 2</a-tab-pane>
+    </a-tabs>
+  </div>
+</template>
+<script>
+export default {
+  data() {
+    return {};
+  },
+  methods: {
+    callback(key) {
+      console.log(key);
+    }
+  }
+};
+</script>
+<style lang="less" scoped>
+ul,
+li {
+  margin: 0;
+  padding: 0;
+  list-style: none;
+}
+#right_toolbar {
+  width: 280px;
+  height: 708px;
+  background: rgba(255, 255, 255, 1);
+  box-shadow: 1px 2px 10px 0px rgba(0, 0, 0, 0.11);
+  .property {
+    width: 100%;
+    .formatting {
+      display: flex;
+      height: 50px;
+      padding: 0 12px 0 12px;
+      box-sizing: border-box;
+      align-items: center;
+      justify-content: space-around;
+      li {
+        width: 16px;
+        height: 16px;
+        background: red;
+        cursor: pointer;
+      }
+    }
+    .position {
+      display: flex;
+      padding: 0 12px 0 12px;
+      box-sizing: border-box;
+      display: flex;
+      flex-wrap: wrap;
+      li {
+        margin-top: 10px;
+        width: 30%;
+        margin-right: 8px
+      }
+    }
+  }
+}
+</style>

+ 113 - 0
src/components/edit/top_toolbar.vue

@@ -0,0 +1,113 @@
+<template>
+  <div id="top_toolbar">
+    <!-- 顶部编辑器 -->
+    <div class="tit">
+      <a-icon type="left" />消防系统-4F
+    </div>
+    <div class="tool">
+      <ul>
+        <li>
+          <a-icon type="edit" />
+          <span>保存</span>
+        </li>
+        <li>
+          <a-icon type="edit" />
+          <span>撤销</span>
+        </li>
+        <li>
+          <a-icon type="edit" />
+          <span>重做</span>
+        </li>
+        <li>缩放窗口</li>
+        <li>
+          <a-icon type="edit" />
+          <span>对齐</span>
+        </li>
+        <li>
+          <a-icon type="edit" />
+          <span>图层</span>
+        </li>
+        <li>
+          <a-icon type="edit" />
+          <span>组合</span>
+        </li>
+        <li>
+          <a-icon type="edit" />
+          <span>打散</span>
+        </li>
+        <li>
+          <a-icon type="edit" />
+          <span>锁定</span>
+        </li>
+        <li>
+          <a-icon type="edit" />
+          <span>解锁</span>
+        </li>
+      </ul>
+    </div>
+    <div class="btn-list">
+      <div class="btn-list-item">
+        <a-icon type="delete" />
+        <span>发布</span>
+      </div>
+      <div class="btn-list-item">
+        <a-icon type="delete" />
+        <span>下载</span>
+      </div>
+    </div>
+  </div>
+</template>
+<style lang="less" scoped>
+ul,
+li {
+  margin: 0;
+  padding: 0;
+  list-style: none;
+}
+#top_toolbar {
+  width: 100%;
+  height: 60px;
+  background: rgba(255, 255, 255, 1);
+  box-shadow: 0px 2px 10px 0px rgba(31, 35, 41, 0.1);
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  padding: 0 24px 0 24px;
+  .tit {
+    // flex: 1;
+    font-size: 18px;
+    font-weight: bold;
+    color: #1f2429;
+  }
+  .tool {
+    ul {
+      display: flex;
+      li {
+        display: flex;
+        justify-content: center;
+        flex-direction: column;
+        width: 48px;
+        font-size: 12px;
+        align-items: center;
+        text-align: center;
+        cursor: pointer;
+      }
+    }
+  }
+  .btn-list {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    width: 72px;
+    .btn-list-item {
+      display: flex;
+      justify-content: center;
+      flex-direction: column;
+      span {
+        font-size: 12px;
+      }
+      cursor: pointer;
+    }
+  }
+}
+</style>

+ 6 - 0
src/main.ts

@@ -3,6 +3,12 @@ import App from './App.vue'
 import router from './router'
 import store from './store'
 
+
+import Antd from 'ant-design-vue'
+import 'ant-design-vue/dist/antd.css'
+Vue.config.productionTip = false
+
+Vue.use(Antd)
 Vue.config.productionTip = false
 
 new Vue({

+ 7 - 10
src/router/index.ts

@@ -1,22 +1,19 @@
 import Vue from 'vue'
 import VueRouter, { RouteConfig } from 'vue-router'
-import Home from '../views/Home.vue'
-
+import editer from '../views/editer.vue'
+import drafts from '../views/drafts.vue'
 Vue.use(VueRouter)
 
   const routes: Array<RouteConfig> = [
   {
     path: '/',
-    name: 'Home',
-    component: Home
+    name: 'editer',
+    component: editer
   },
   {
-    path: '/about',
-    name: 'About',
-    // route level code-splitting
-    // this generates a separate chunk (about.[hash].js) for this route
-    // which is lazy-loaded when the route is visited.
-    component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
+    path: '/drafts',
+    name: 'drafts',
+    component: drafts
   }
 ]
 

+ 0 - 5
src/views/About.vue

@@ -1,5 +0,0 @@
-<template>
-  <div class="about">
-    <h1>This is an about page</h1>
-  </div>
-</template>

+ 0 - 18
src/views/Home.vue

@@ -1,18 +0,0 @@
-<template>
-  <div class="home">
-    <img alt="Vue logo" src="../assets/logo.png">
-    <HelloWorld msg="Welcome to Your Vue.js App"/>
-  </div>
-</template>
-
-<script>
-// @ is an alias to /src
-import HelloWorld from '@/components/HelloWorld.vue'
-
-export default {
-  name: 'Home',
-  components: {
-    HelloWorld
-  }
-}
-</script>

+ 147 - 0
src/views/drafts.vue

@@ -0,0 +1,147 @@
+<template>
+  <div id="drafts">
+    <div class="tit">草稿箱</div>
+    <div class="conent">
+      <div class="left-nav">
+        <Tree :data="treeData" @change="change"></Tree>
+      </div>
+      <div class="conent-right">
+        <div class="conent-tit">
+          <div class="tit-left">消防系统-4F</div>
+          <div class="tit-right">
+            <a-button>发布</a-button>
+            <a-button type="primary">编辑</a-button>
+          </div>
+        </div>
+        <div class="map"></div>
+      </div>
+    </div>
+  </div>
+</template>
+<script>
+const dataArr = [
+  {
+    id: "0",
+    name: "顶级顶级顶级顶级顶级顶级顶级顶级顶级顶级顶级顶级",
+    open: false,
+    checked: "uncheck",
+    children: [
+      {
+        id: "1",
+        name: "一级1",
+        open: false,
+        checked: "uncheck",
+        children: [
+          { id: "12", name: "二级2", checked: "uncheck" },
+          { id: "121", name: "二级3", checked: "uncheck" },
+          { id: "122", name: "二级4", checked: "uncheck" },
+          {
+            id: "1321",
+            name: "二级1",
+            open: false,
+            checked: "uncheck",
+            children: [
+              { id: "13", name: "三级2", checked: "uncheck" },
+              { id: "131", name: "三级3", checked: "uncheck" },
+              { id: "132", name: "三级4", checked: "uncheck" }
+            ]
+          }
+        ]
+      },
+      {
+        id: "2",
+        name: "一级2",
+        open: false,
+        checked: "uncheck",
+        children: [
+          { id: "222", name: "二级2", checked: "uncheck" },
+          { id: "2221", name: "二级1", checked: "uncheck" },
+          { id: "2222", name: "二级3", checked: "uncheck" }
+        ]
+      },
+      {
+        id: "3",
+        name: "一级3",
+        open: false,
+        checked: "uncheck",
+        children: [
+          { id: "322", name: "二级2", checked: "uncheck" },
+          { id: "3220", name: "二级0", checked: "uncheck" },
+          { id: "3221", name: "二级1", checked: "uncheck" }
+        ]
+      }
+    ]
+  }
+];
+import Tree from "./../components/Tree/Tree.vue";
+export default {
+  components: { Tree },
+  data() {
+    return {
+      treeData:JSON.parse(JSON.stringify(dataArr))
+    };
+  },
+  methods: {
+    change() {}
+  }
+};
+</script>
+<style lang="less" scoped>
+#drafts {
+  widows: 100%;
+  height: 100%;
+  background: #f7f9fa;
+  position: relative;
+  .tit {
+    width: 100%;
+    height: 48px;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    border-bottom: #e4e5e7 solid 1px;
+    font-size: 16px;
+    font-weight: bold;
+  }
+  .conent {
+    width: 100%;
+    height: calc(100% - 48px);
+    display: flex;
+    position: relative;
+
+    .left-nav {
+      width: 224px;
+      height: 100%;
+    }
+    .conent-right {
+      flex: 1;
+      height: 100%;
+      background: #fff;
+      .conent-tit {
+        width: 100%;
+        display: flex;
+        height: 59px;
+        border: 1px solid #eff0f1;
+        align-items: center;
+        justify-content: space-between;
+        padding: 0 16px 0 16px;
+        box-sizing: border-box;
+        .tit-left {
+          font-size: 16px;
+          font-weight: bold;
+          color: rgba(31, 35, 41, 1);
+        }
+        .tit-right {
+          width: 146px;
+          display: flex;
+          justify-content: space-between;
+        }
+      }
+      .map {
+        width: 100%;
+        height: calc(100% - 61px);
+        background: red;
+      }
+    }
+  }
+}
+</style>

+ 69 - 0
src/views/editer.vue

@@ -0,0 +1,69 @@
+<template>
+  <div class="wandaEditer">
+    <!-- 顶部工具栏 -->
+    <div class="top_toolbar">
+      <topToolbar></topToolbar>
+    </div>
+    <div class="content">
+      <!-- 左侧工具栏 -->
+      <div class="left_toolbar">
+        <leftToolbar></leftToolbar>
+      </div>
+      <!-- 绘制界面 -->
+      <div class="baseEdit">
+        <baseEditer></baseEditer>
+      </div>
+      <!-- 右侧工具栏 -->
+      <div class="right_toolbar">
+        <rightToolbar></rightToolbar>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import baseEditer from "@/components/baseEditer.vue";
+import leftToolbar from "@/components/edit/left_toolbar.vue";
+import topToolbar from "@/components/edit/top_toolbar.vue";
+import rightToolbar from "@/components/edit/right_toolbar.vue";
+export default {
+  name: "wandaEditer",
+  components: {
+    baseEditer,
+    leftToolbar,
+    topToolbar,
+    rightToolbar
+  }
+};
+</script>
+<style lang="less" scoped>
+.wandaEditer {
+  width: 100%;
+  height: 100%;
+  .top_toolbar {
+    width: 100%;
+    height: 60px;
+    background: rgba(255, 255, 255, 1);
+    box-shadow: 0px 2px 10px 0px rgba(31, 35, 41, 0.1);
+  }
+  .content {
+    width: 100%;
+    height: calc(100% - 60px);
+    display: flex;
+    position: relative;
+    .baseEdit {
+      flex: 1;
+    }
+    .right_toolbar {
+      width: 336px;
+      height: 100%;
+      background: #fff;
+    }
+    .left_toolbar {
+      position: absolute;
+      left: 12px;
+      top: 12px;
+    }
+  }
+}
+</style>

+ 21 - 0
vue.config.js

@@ -0,0 +1,21 @@
+module.exports = {
+    devServer: {
+        // 关闭esline
+        overlay: {
+            warnings: false,
+            errors: false
+        },
+    },
+    chainWebpack: (config) => {
+        const svgRule = config.module.rule('svg');
+
+        svgRule.uses.clear();
+
+        svgRule
+            .use('babel-loader')
+            .loader('babel-loader')
+            .end()
+            .use('vue-svg-loader')
+            .loader('vue-svg-loader');
+    },
+}