lex-xin пре 3 година
родитељ
комит
0fc7b89340

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


+ 3 - 0
package.json

@@ -19,10 +19,13 @@
     "vue-router": "^4.0.12"
   },
   "devDependencies": {
+    "@types/js-cookie": "^3.0.1",
     "@types/node": "^17.0.17",
+    "@types/webpack-env": "^1.16.3",
     "@vitejs/plugin-legacy": "^1.7.1",
     "@vitejs/plugin-vue": "^2.2.0",
     "@vitejs/plugin-vue-jsx": "^1.3.7",
+    "less": "^4.1.2",
     "typescript": "^4.5.4",
     "vite": "^2.8.0",
     "vite-plugin-pwa": "^0.11.13",

+ 31 - 2
src/App.vue

@@ -12,13 +12,42 @@
   </router-view>
 </template>
 
-<style>
+<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;
-  margin-top: 60px;
+}
+
+* {
+  margin: 0;
+  padding: 0;
+  touch-action: none !important;
+}
+[v-cloak] {
+  display: none !important;
+}
+html {
+  --color-primary: #00a79d;
+}
+body {
+  background-color: #eef4f9 !important;
+}
+
+.el-dialog {
+  margin-bottom: 10vh;
+  .el-dialog__header {
+    // background: #363d55;
+    background: var(--color-primary);
+    padding: 15px 20px 15px;
+    .el-dialog__title {
+      color: #fff;
+    }
+    .el-dialog__headerbtn .el-dialog__close {
+      color: #fff;
+    }
+  }
 }
 </style>

+ 13 - 0
src/components/SvgIcon/index.module.less

@@ -0,0 +1,13 @@
+.svgIcon {
+  width: 1em;
+  height: 1em;
+  vertical-align: -0.15em;
+  fill: currentColor;
+  overflow: hidden;
+}
+
+.svgExternalIcon {
+  background-color: currentColor;
+  mask-size: cover !important;
+  display: inline-block;
+}

+ 121 - 0
src/components/SvgIcon/index.tsx

@@ -0,0 +1,121 @@
+import { defineComponent } from "vue";
+import styles from "./index.module.less";
+import { isExternal } from '/src/utils/validate'
+export default defineComponent({
+  name: 'SvgIcon',
+  props: {
+    iconClass: {
+      type: String,
+      required: true
+    },
+    className: {
+      type: String,
+      default: ''
+    }
+  },
+  computed: {
+    isExternal () {
+      return isExternal(this.iconClass)
+    },
+    iconName () {
+      return `#icon-${this.iconClass}`
+    },
+    svgClass () {
+      if (this.className) {
+        return 'svg-icon ' + this.className
+      } else {
+        return 'svg-icon'
+      }
+    },
+    styleExternalIcon () {
+      return {
+        mask: `url(${this.iconClass}) no-repeat 50% 50%`,
+        '-webkit-mask': `url(${this.iconClass}) no-repeat 50% 50%`
+      }
+    }
+  },
+  render() {
+    return (
+      <div>
+        <div v-if="isExternal"
+          style={this.styleExternalIcon}
+          class={[styles.svgExternalIcon, styles.svgIcon]}
+          v-on="$listeners" />
+        <svg v-else
+            class={styles.svgClass}
+            aria-hidden="true"
+            v-on="$listeners">
+          <use xlinkHref={this.iconName} />
+        </svg>
+      </div>
+    );
+  }
+})
+
+{/* <template>
+  <div v-if="isExternal"
+       :style="styleExternalIcon"
+       class="svg-external-icon svg-icon"
+       v-on="$listeners" />
+  <svg v-else
+       :class="svgClass"
+       aria-hidden="true"
+       v-on="$listeners">
+    <use :xlink:href="iconName" />
+  </svg>
+</template>
+
+<script>
+import { isExternal } from '@/utils/validate'
+
+export default {
+  name: 'SvgIcon',
+  props: {
+    iconClass: {
+      type: String,
+      required: true
+    },
+    className: {
+      type: String,
+      default: ''
+    }
+  },
+  computed: {
+    isExternal () {
+      return isExternal(this.iconClass)
+    },
+    iconName () {
+      return `#icon-${this.iconClass}`
+    },
+    svgClass () {
+      if (this.className) {
+        return 'svg-icon ' + this.className
+      } else {
+        return 'svg-icon'
+      }
+    },
+    styleExternalIcon () {
+      return {
+        mask: `url(${this.iconClass}) no-repeat 50% 50%`,
+        '-webkit-mask': `url(${this.iconClass}) no-repeat 50% 50%`
+      }
+    }
+  }
+}
+</script>
+
+<style scoped>
+.svg-icon {
+  width: 1em;
+  height: 1em;
+  vertical-align: -0.15em;
+  fill: currentColor;
+  overflow: hidden;
+}
+
+.svg-external-icon {
+  background-color: currentColor;
+  mask-size: cover !important;
+  display: inline-block;
+}
+</style> */}

+ 36 - 0
src/icons/index.ts

@@ -0,0 +1,36 @@
+// import Vue from 'vue'
+
+import SvgIcon from '/src/components/SvgIcon'// svg component
+
+// register globally
+// Vue.component('svg-icon', SvgIcon)
+
+// const req = import.meta.globEager("./svg/*.svg")
+// console.log(req)
+// // const requireAll = (requireContext: any) => requireContext.keys().map(requireContext)
+// const requireAll = (requireContext: any) => {
+//   return requireContext.keys().map(requireContext)
+// }
+// requireAll(req)
+
+const files = import.meta.globEager("./svg/*.svg")
+
+let modules: any = {}
+for (const key in files) {
+    modules[key.replace(/(\.\/module\/|\.js)/g, '')] = files[key].default
+}
+
+Object.keys(modules).forEach(item => {
+    modules[item] = true
+})
+console.log(modules)
+// const requireAll = (requireContext: any) => {
+//   return requireContext.keys().map(requireContext)
+// }
+// requireAll(modules)
+
+export default {
+  install(Vue: any) {
+    Vue.component('svg-icon', SvgIcon)
+  }
+}

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


+ 1 - 0
src/icons/svg/example.svg

@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M96.258 57.462h31.421C124.794 27.323 100.426 2.956 70.287.07v31.422a32.856 32.856 0 0 1 25.971 25.97zm-38.796-25.97V.07C27.323 2.956 2.956 27.323.07 57.462h31.422a32.856 32.856 0 0 1 25.97-25.97zm12.825 64.766v31.421c30.46-2.885 54.507-27.253 57.713-57.712H96.579c-2.886 13.466-13.146 23.726-26.292 26.291zM31.492 70.287H.07c2.886 30.46 27.253 54.507 57.713 57.713V96.579c-13.466-2.886-23.726-13.146-26.291-26.292z"/></svg>

+ 1 - 0
src/icons/svg/eye-open.svg

@@ -0,0 +1 @@
+<svg class="icon" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" width="128" height="128"><defs><style/></defs><path d="M512 128q69.675 0 135.51 21.163t115.498 54.997 93.483 74.837 73.685 82.006 51.67 74.837 32.17 54.827L1024 512q-2.347 4.992-6.315 13.483T998.87 560.17t-31.658 51.669-44.331 59.99-56.832 64.34-69.504 60.16-82.347 51.5-94.848 34.687T512 896q-69.675 0-135.51-21.163t-115.498-54.826-93.483-74.326-73.685-81.493-51.67-74.496-32.17-54.997L0 513.707q2.347-4.992 6.315-13.483t18.816-34.816 31.658-51.84 44.331-60.33 56.832-64.683 69.504-60.331 82.347-51.84 94.848-34.816T512 128.085zm0 85.333q-46.677 0-91.648 12.331t-81.152 31.83-70.656 47.146-59.648 54.485-48.853 57.686-37.675 52.821-26.325 43.99q12.33 21.674 26.325 43.52t37.675 52.351 48.853 57.003 59.648 53.845T339.2 767.02t81.152 31.488T512 810.667t91.648-12.331 81.152-31.659 70.656-46.848 59.648-54.186 48.853-57.344 37.675-52.651T927.957 512q-12.33-21.675-26.325-43.648t-37.675-52.65-48.853-57.345-59.648-54.186-70.656-46.848-81.152-31.659T512 213.334zm0 128q70.656 0 120.661 50.006T682.667 512 632.66 632.661 512 682.667 391.339 632.66 341.333 512t50.006-120.661T512 341.333zm0 85.334q-35.328 0-60.33 25.002T426.666 512t25.002 60.33T512 597.334t60.33-25.002T597.334 512t-25.002-60.33T512 426.666z"/></svg>

+ 1 - 0
src/icons/svg/eye.svg

@@ -0,0 +1 @@
+<svg width="128" height="64" xmlns="http://www.w3.org/2000/svg"><path d="M127.072 7.994c1.37-2.208.914-5.152-.914-6.87-2.056-1.717-4.797-1.226-6.396.982-.229.245-25.586 32.382-55.74 32.382-29.24 0-55.74-32.382-55.968-32.627-1.6-1.963-4.57-2.208-6.397-.49C-.17 3.086-.399 6.275 1.2 8.238c.457.736 5.94 7.36 14.62 14.72L4.17 35.96c-1.828 1.963-1.6 5.152.228 6.87.457.98 1.6 1.471 2.742 1.471s2.284-.49 3.198-1.472l12.564-13.983c5.94 4.416 13.021 8.587 20.788 11.53l-4.797 17.418c-.685 2.699.686 5.397 3.198 6.133h1.37c2.057 0 3.884-1.472 4.341-3.68L52.6 42.83c3.655.736 7.538 1.227 11.422 1.227 3.883 0 7.767-.49 11.422-1.227l4.797 17.173c.457 2.208 2.513 3.68 4.34 3.68.457 0 .914 0 1.143-.246 2.513-.736 3.883-3.434 3.198-6.133l-4.797-17.172c7.767-2.944 14.848-7.114 20.788-11.53l12.336 13.738c.913.981 2.056 1.472 3.198 1.472s2.284-.49 3.198-1.472c1.828-1.963 1.828-4.906.228-6.87l-11.65-13.001c9.366-7.36 14.849-14.474 14.849-14.474z"/></svg>

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


+ 1 - 0
src/icons/svg/link.svg

@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M115.625 127.937H.063V12.375h57.781v12.374H12.438v90.813h90.813V70.156h12.374z"/><path d="M116.426 2.821l8.753 8.753-56.734 56.734-8.753-8.745z"/><path d="M127.893 37.982h-12.375V12.375H88.706V0h39.187z"/></svg>

+ 7 - 0
src/icons/svg/loading.svg

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="33px" height="52px" viewBox="0 0 33 52" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>形状_2_备份</title>
+    <g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <path d="M11.5216853,33.799691 C10.913674,35.4502333 11.1645993,37.3644718 12.3516691,38.7903841 C14.1177973,40.919486 17.2833168,41.1734156 19.435484,39.3470759 C21.5780003,37.5207361 21.8868314,34.3173167 20.1207032,32.1882148 C18.6151512,30.3716416 16.096247,29.9223815 14.0502405,30.9576329 C15.1118477,30.7427694 16.2410116,31.1041308 16.9744856,31.9831178 C18.0553947,33.2918318 17.8720262,35.2549029 16.5498428,36.3682865 C15.2373103,37.4816701 13.2974645,37.3351722 12.2165554,36.0264582 C11.6761009,35.3818677 11.4541285,34.5810128 11.5216853,33.799691 L11.5216853,33.799691 Z M16.2348555,44.6301565 C11.2321335,44.6301565 7.17614166,40.5335994 7.17614166,35.4893314 C7.17614166,30.4450634 11.2321335,26.3485064 16.2348555,26.3485064 C21.2375776,26.3485064 25.2935694,30.4450634 25.2935694,35.4893314 C25.2935694,40.5437899 21.2375776,44.6301565 16.2348555,44.6301565 Z M21.8545098,19.8009017 C27.9805287,22.1371362 32.3392358,28.1724088 32.3392358,35.2528389 C32.3392358,44.3518577 25.1309867,51.7396871 16.2348555,51.7396871 C7.33872441,51.7396871 0.130475303,44.3621043 0.130475303,35.2528389 C0.130475303,27.4141572 5.47212547,20.8563059 12.630731,19.1861031 L12.630731,2.93492779 C12.630731,1.83853702 13.4945294,0.957325747 14.566831,0.957325747 C20.4644893,0.957325747 25.26006,5.82448104 25.26006,11.8392603 C25.2501313,14.9849796 23.9395405,17.813053 21.8545098,19.8009017 L21.8545098,19.8009017 Z M16.2348555,47.6770982 C22.909183,47.6770982 28.3131407,41.9898865 28.3131407,34.9815078 C28.3131407,27.9731291 22.909183,22.2859175 16.2348555,22.2859175 C9.56052805,22.2859175 4.15657036,27.9731291 4.15657036,34.9815078 C4.15657036,41.9898865 9.56052805,47.6770982 16.2348555,47.6770982 Z M16.2348555,18.2233286 C19.1495386,17.3854973 21.2674744,14.7407767 21.2674744,11.6216216 C21.2674744,8.50246649 19.1495386,5.86784032 16.2348555,5.01991465 L16.2348555,18.2233286 Z" id="形状_2_备份" fill="#01C1B5"></path>
+    </g>
+</svg>

+ 1 - 0
src/icons/svg/nested.svg

@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M.002 9.2c0 5.044 3.58 9.133 7.998 9.133 4.417 0 7.997-4.089 7.997-9.133 0-5.043-3.58-9.132-7.997-9.132S.002 4.157.002 9.2zM31.997.066h95.981V18.33H31.997V.066zm0 45.669c0 5.044 3.58 9.132 7.998 9.132 4.417 0 7.997-4.088 7.997-9.132 0-3.263-1.524-6.278-3.998-7.91-2.475-1.63-5.524-1.63-7.998 0-2.475 1.632-4 4.647-4 7.91zM63.992 36.6h63.986v18.265H63.992V36.6zm-31.995 82.2c0 5.043 3.58 9.132 7.998 9.132 4.417 0 7.997-4.089 7.997-9.132 0-5.044-3.58-9.133-7.997-9.133s-7.998 4.089-7.998 9.133zm31.995-9.131h63.986v18.265H63.992V109.67zm0-27.404c0 5.044 3.58 9.133 7.998 9.133 4.417 0 7.997-4.089 7.997-9.133 0-3.263-1.524-6.277-3.998-7.909-2.475-1.631-5.524-1.631-7.998 0-2.475 1.632-4 4.646-4 7.91zm31.995-9.13h31.991V91.4H95.987V73.135z"/></svg>

+ 1 - 0
src/icons/svg/password.svg

@@ -0,0 +1 @@
+<svg width="128" height="128" fill="#999" xmlns="http://www.w3.org/2000/svg"><path d="M108.8 44.322H89.6v-5.36c0-9.04-3.308-24.163-25.6-24.163-23.145 0-25.6 16.881-25.6 24.162v5.361H19.2v-5.36C19.2 15.281 36.798 0 64 0c27.202 0 44.8 15.281 44.8 38.961v5.361zm-32 39.356c0-5.44-5.763-9.832-12.8-9.832-7.037 0-12.8 4.392-12.8 9.832 0 3.682 2.567 6.808 6.407 8.477v11.205c0 2.718 2.875 4.962 6.4 4.962 3.524 0 6.4-2.244 6.4-4.962V92.155c3.833-1.669 6.393-4.795 6.393-8.477zM128 64v49.201c0 8.158-8.645 14.799-19.2 14.799H19.2C8.651 128 0 121.359 0 113.201V64c0-8.153 8.645-14.799 19.2-14.799h89.6c10.555 0 19.2 6.646 19.2 14.799z"/></svg>

+ 1 - 0
src/icons/svg/table.svg

@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M.006.064h127.988v31.104H.006V.064zm0 38.016h38.396v41.472H.006V38.08zm0 48.384h38.396v41.472H.006V86.464zM44.802 38.08h38.396v41.472H44.802V38.08zm0 48.384h38.396v41.472H44.802V86.464zM89.598 38.08h38.396v41.472H89.598zm0 48.384h38.396v41.472H89.598z"/><path d="M.006.064h127.988v31.104H.006V.064zm0 38.016h38.396v41.472H.006V38.08zm0 48.384h38.396v41.472H.006V86.464zM44.802 38.08h38.396v41.472H44.802V38.08zm0 48.384h38.396v41.472H44.802V86.464zM89.598 38.08h38.396v41.472H89.598zm0 48.384h38.396v41.472H89.598z"/></svg>

+ 1 - 0
src/icons/svg/tree.svg

@@ -0,0 +1 @@
+<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M126.713 90.023c.858.985 1.287 2.134 1.287 3.447v29.553c0 1.423-.429 2.6-1.287 3.53-.858.93-1.907 1.395-3.146 1.395H97.824c-1.145 0-2.146-.465-3.004-1.395-.858-.93-1.287-2.107-1.287-3.53V93.47c0-.875.19-1.696.572-2.462.382-.766.906-1.368 1.573-1.806a3.84 3.84 0 0 1 2.146-.657h9.725V69.007a3.84 3.84 0 0 0-.43-1.806 3.569 3.569 0 0 0-1.143-1.313 2.714 2.714 0 0 0-1.573-.492h-36.47v23.149h9.725c1.144 0 2.145.492 3.004 1.478.858.985 1.287 2.134 1.287 3.447v29.553c0 .876-.191 1.696-.573 2.463-.38.766-.905 1.368-1.573 1.806a3.84 3.84 0 0 1-2.145.656H51.915a3.84 3.84 0 0 1-2.145-.656c-.668-.438-1.216-1.04-1.645-1.806a4.96 4.96 0 0 1-.644-2.463V93.47c0-1.313.43-2.462 1.288-3.447.858-.986 1.907-1.478 3.146-1.478h9.582v-23.15h-37.9c-.953 0-1.74.356-2.359 1.068-.62.711-.93 1.56-.93 2.544v19.538h9.726c1.239 0 2.264.492 3.074 1.478.81.985 1.216 2.134 1.216 3.447v29.553c0 1.423-.405 2.6-1.216 3.53-.81.93-1.835 1.395-3.074 1.395H4.29c-.476 0-.93-.082-1.358-.246a4.1 4.1 0 0 1-1.144-.657 4.658 4.658 0 0 1-.93-1.067 5.186 5.186 0 0 1-.643-1.395 5.566 5.566 0 0 1-.215-1.56V93.47c0-.437.048-.875.143-1.313a3.95 3.95 0 0 1 .429-1.15c.19-.328.429-.656.715-.984.286-.329.572-.602.858-.821.286-.22.62-.383 1.001-.493.382-.11.763-.164 1.144-.164h9.726V61.619c0-.985.31-1.833.93-2.544.619-.712 1.358-1.068 2.216-1.068h44.335V39.62h-9.582c-1.24 0-2.288-.492-3.146-1.477a5.09 5.09 0 0 1-1.287-3.448V5.14c0-1.423.429-2.627 1.287-3.612.858-.985 1.907-1.477 3.146-1.477h25.743c.763 0 1.478.246 2.145.739a5.17 5.17 0 0 1 1.573 1.888c.382.766.573 1.587.573 2.462v29.553c0 1.313-.43 2.463-1.287 3.448-.859.985-1.86 1.477-3.004 1.477h-9.725v18.389h42.762c.954 0 1.74.355 2.36 1.067.62.711.93 1.56.93 2.545v26.925h9.582c1.239 0 2.288.492 3.146 1.478z"/></svg>

+ 1 - 0
src/icons/svg/user.svg

@@ -0,0 +1 @@
+<svg width="130" height="130" fill="#999" xmlns="http://www.w3.org/2000/svg"><path d="M63.444 64.996c20.633 0 37.359-14.308 37.359-31.953 0-17.649-16.726-31.952-37.359-31.952-20.631 0-37.36 14.303-37.358 31.952 0 17.645 16.727 31.953 37.359 31.953zM80.57 75.65H49.434c-26.652 0-48.26 18.477-48.26 41.27v2.664c0 9.316 21.608 9.325 48.26 9.325H80.57c26.649 0 48.256-.344 48.256-9.325v-2.663c0-22.794-21.605-41.271-48.256-41.271z" stroke="#979797"/></svg>

+ 22 - 0
src/icons/svgo.yml

@@ -0,0 +1,22 @@
+# replace default config
+
+# multipass: true
+# full: true
+
+plugins:
+
+  # - name
+  #
+  # or:
+  # - name: false
+  # - name: true
+  #
+  # or:
+  # - name:
+  #     param1: 1
+  #     param2: 2
+
+- removeAttrs:
+    attrs:
+      - 'fill'
+      - 'fill-rule'

+ 2 - 1
src/main.ts

@@ -1,8 +1,9 @@
 import { createApp } from 'vue'
 import App from './App.vue'
 import router from './router'
-
+import 'element-plus/dist/index.css'
 import './permission'
+import './icons' // icon
 
 createApp(App)
   .use(router).mount('#app')

BIN
src/pages/login/images/icon_checkbox.png


BIN
src/pages/login/images/icon_checkbox_default.png


BIN
src/pages/login/images/login-bg.png


BIN
src/pages/login/images/login-logo.png


+ 349 - 0
src/pages/login/index.module.less

@@ -0,0 +1,349 @@
+body {
+  background: #fff !important;
+}
+
+.loginContainer {
+  :global {
+    .el-input__inner {
+      background-color: transparent !important;
+      border: 1px solid transparent !important
+    }
+
+    .el-input input:-webkit-autofill {
+      background-color: transparent !important;
+    }
+  }
+}
+
+.loginInput {
+  background-color: transparent !important;
+}
+
+/* 修复input 背景不协调 和光标变色 */
+/* Detail see https://github.com/PanJiaChen/vue-element-admin/pull/927 */
+.loginBtn {
+  background-color: #22B4A9;
+  text-align: center;
+  margin: 0 auto;
+  width: 85%;
+  height: 50px;
+  line-height: 50px;
+  color: #fff;
+  border-radius: 5px;
+  cursor: pointer;
+}
+
+.loginBtn.disabled {
+  background-color: rgba(34, 180, 169, .5);
+}
+
+// :global {
+//   ::-webkit-input-placeholder {
+//     color: #444;
+//     font-size: 14px;
+//   }
+
+//   ::-moz-placeholder {
+//     color: #444;
+//     font-size: 14px;
+//   }
+
+//   :-ms-input-placeholder {
+//     color: #444;
+//     font-size: 14px;
+//   }
+// }
+
+.loginContainer {
+  :global {
+    .el-input input {
+      color: #444 !important;
+      caret-color: #444 !important;
+    }
+  }
+}
+
+.remberBox {
+  display: flex;
+  flex-direction: row;
+  justify-content: flex-start;
+  margin-bottom: 30px;
+  padding-top: 10px;
+  align-items: center;
+  cursor: pointer;
+  color: #6D7278;
+  font-size: 16px;
+
+  .dotWrap {
+    width: 21px;
+    height: 21px;
+    background: url('./images/icon_checkbox_default.png') no-repeat center;
+    background-size: contain;
+    margin-right: 8px;
+    position: relative;
+    overflow: hidden;
+
+    &.checked {
+      background: url('./images/icon_checkbox.png') no-repeat center;
+      background-size: contain;
+    }
+  }
+}
+
+@bg: #fff;
+@light_gray: #000;
+@cursor: #000;
+
+// @supports (-webkit-mask: none) and (not (cater-color: @cursor)) {
+//   .loginContainer {
+//     :global {
+//       .el-input input {
+//         color: @cursor;
+
+//         &::first-line {
+//           color: @light_gray;
+//         }
+//       }
+//     }
+//   }
+// }
+
+// @supports (-webkit-mask: none) and (not (cater-color: @cursor)) {
+//   .loginContainer {
+//     :global {
+//       .el-input input {
+//         color: @cursor;
+//       }
+//     }
+//   }
+// }
+
+/* reset element-ui css */
+.loginContainer {
+  :global {
+    .el-input {
+      display: inline-block;
+      height: 47px;
+      width: 85%;
+
+      input {
+        background: transparent !important;
+        border: 0px;
+        -webkit-appearance: none;
+        border-radius: 0px;
+        padding: 12px 5px 12px 15px;
+        color: @light_gray;
+        height: 47px;
+        caret-color: @cursor;
+
+        &:-webkit-autofill {
+          box-shadow: 0 0 0px 1000px @bg inset !important;
+          -webkit-text-fill-color: @cursor  !important;
+        }
+      }
+    }
+
+    .el-form-item {
+      border: 1px solid #E5E6E8;
+      border-radius: 8px;
+      color: #454545;
+    }
+  }
+
+}
+
+@bg: #fff;
+@dark_gray: #000;
+@light_gray: #eee;
+
+.loginContainer {
+  height: 100vh;
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  background: url("./images/login-bg.png") no-repeat center left #fff;
+  background-size: cover;
+
+  .loginForm {
+    border-radius: 15px;
+    padding: 50px 60px 70px;
+    background-color: #fff;
+    box-shadow: 0px 0px 16px 1px #ebf6f5;
+  }
+
+  .tips {
+    font-size: 14px;
+    color: #fff;
+    margin-bottom: 10px;
+
+    span {
+      &:first-of-type {
+        margin-right: 16px;
+      }
+    }
+  }
+
+  .svgContainer {
+    padding: 6px 5px 6px 15px;
+    color: #999999;
+    vertical-align: middle;
+    width: 30px;
+    display: inline-block;
+    .icon {
+      width: 1em;
+      height: 1em;
+      vertical-align: -0.15em;
+      fill: currentColor;
+      overflow: hidden;
+    }
+  }
+
+  .titleContainer {
+    position: relative;
+    display: flex;
+    flex-direction: column;
+    align-items: flex-start;
+    font-size: 26px;
+    color: #333;
+    font-weight: 600;
+    margin-bottom: 30px;
+    border-bottom: 1px solid #E5E6E8;
+
+    &::after {
+      margin-top: 12px;
+      display: inline-block;
+      content: ' ';
+      width: 25px;
+      height: 4px;
+      background: #22B4A9;
+      margin-bottom: -2px;
+      margin-left: 13px;
+    }
+  }
+
+  .showPwd {
+    position: absolute;
+    right: 10px;
+    top: 7px;
+    font-size: 14px;
+    color: #6D7278;
+    cursor: pointer;
+    user-select: none;
+    .icon {
+      width: 1em;
+      // height: 1em;
+      vertical-align: -0.15em;
+      fill: currentColor;
+      overflow: hidden;
+    }
+  }
+
+  .loginHeader {
+    margin-top: 80px;
+    font-size: 18px;
+    color: #333333;
+    display: flex;
+    align-items: center;
+    justify-content: flex-start;
+    margin-bottom: 30px;
+
+    .logo {
+      img {
+        height: 40px;
+      }
+    }
+
+    .line {
+      display: inline-block;
+      width: 1px;
+      height: 20px;
+      background: #979797;
+      margin: 0 20px;
+    }
+  }
+
+  .loginLeft {
+    display: flex;
+    flex-direction: column;
+    justify-content: space-between;
+    height: 100%;
+    margin-left: 170px;
+
+    .footer {
+      margin-bottom: 30px;
+      font-size: 14px;
+      position: absolute;
+      color: #B2B2B2;
+      bottom: 0;
+      width: 100%;
+      left: 0;
+      text-align: center;
+    }
+  }
+}
+
+.loginSection {
+  margin-right: 250px;
+  width: 500px;
+}
+
+/* 大屏幕(大桌面显示器,大于等于 1200px) */
+@media screen and (max-width: 1600px) {
+  .loginSection {
+    margin-right: 200px;
+  }
+
+  .loginContainer .login-left {
+    margin-left: 100px;
+  }
+
+  // .loginContainer .login-left .footer {
+  //   margin-left: 120px;
+  // }
+}
+
+/* 大屏幕(大桌面显示器,大于等于 1200px) */
+@media screen and (max-width: 1200px) {
+  .loginSection {
+    margin-right: 100px;
+  }
+
+  .loginContainer .login-left {
+    margin-left: 50px;
+  }
+
+  // .loginContainer .login-left .footer {
+  //   margin-left: 100px;
+  // }
+}
+
+/* 中等屏幕(桌面显示器,大于等于 992px) */
+@media screen and (max-width: 992px) {
+  .loginSection {
+    margin-right: 100px;
+  }
+
+  .loginContainer .login-left {
+    margin-left: 20px;
+  }
+
+  // .loginContainer .login-left .footer {
+  //   margin-left: 50px;
+  // }
+}
+
+/* 小屏幕(平板,大于等于 768px) */
+@media screen and (max-width: 768px) {
+  .loginSection {
+    margin-right: 50px;
+  }
+
+  .loginContainer .login-left {
+    margin-left: 10px;
+    display: none;
+  }
+
+  // .loginContainer .login-left .footer {
+  //   margin-left: 20px;
+  // }
+}

+ 148 - 13
src/pages/login/index.tsx

@@ -1,24 +1,159 @@
 import { defineComponent } from "vue"
+import { ElForm, ElFormItem, ElInput, ElMessage } from "element-plus";
+import styles from './index.module.less'
+import request from "/src/helpers/request";
+
 
 export default defineComponent({
+  data() {
+    const validateUsername = (rule: any, value: any, callback: () => void) => {
+      if (!value) {
+        // @ts-ignore
+        callback(new Error("请输入用户名"));
+      } else {
+        callback();
+      }
+    }
+    const validatePassword = (rule: any, value: string | any[], callback: () => void) => {
+      if (value.length < 6) {
+        // @ts-ignore
+        callback(new Error("密码必须大于六位"));
+      } else {
+        callback();
+      }
+    }
+    return {
+      loginForm: {
+        username: null,
+        password: null
+      } as any,
+      loginRules: {
+        username: [
+          { required: true, trigger: "blur", validator: validateUsername }
+        ],
+        password: [
+          { required: true, trigger: "blur", validator: validatePassword }
+        ]
+      },
+      passwordType: "password",
+      redirect: undefined,
+      isSaveUserInfo: true
+    }
+  },
+  mounted() {
+    this.loginForm.username = localStorage.getItem('username');
+    this.loginForm.password = localStorage.getItem('password');
+  },
+  methods: {
+    showPwd() {
+      if (this.passwordType === "password") {
+        this.passwordType = "";
+      } else {
+        this.passwordType = "password";
+      }
+      this.$nextTick(() => {
+        (this as any).$refs.password.focus();
+      });
+    },
+    handleLogin() {
+      // 判断是否点击了记住密码 =>  存储密码
+      const loginForm = this.loginForm;
+      if (this.isSaveUserInfo) {
+        localStorage.setItem('username', loginForm.username);
+        localStorage.setItem('password', loginForm.password);
+      } else {
+        localStorage.setItem('username', '');
+        localStorage.setItem('password', '');
+      }
+      (this as any).$refs.loginForm.validate(async (valid: any) => {
+        if (valid) {
+          try {
+            const res = await request.post('/api-auth/usernameLogin', {
+              data: {
+                username: loginForm.username,
+                password: loginForm.password,
+                clientId: "teacher",
+                clientSecret: "teacher"
+              }
+            })
+            ElMessage.success('登录成功')
+            this.$router.push({ path: "/main/main" });
+            console.log(res)
+          } catch (error) {
+            // console.log(error)
+          }
+        } else {
+          return false;
+        }
+      });
+    },
+    saveUserInfo() {
+      this.isSaveUserInfo = !this.isSaveUserInfo;
+    }
+  },
   render() {
     return (
-      <div>
-        <div class="login-container">
-          <div class="login-title">
-          </div>
-          <div class="login-form">
-            <div class="login-input">
-              <input type="text" placeholder="用户名" />
-            </div>
-            <div class="login-input">
-              <input type="password" placeholder="密码" />
-            </div>
-            <div class="login-button">
-              <button>登录</button>
+      <div class={styles.loginContainer}>
+        <div class={styles.loginLeft}>
+          <div class={styles.loginHeader}>
+            <div class={styles.logo}>
+              <img src="/src/pages/login/images/login-logo.png" alt="" />
             </div>
+            <i class={styles.line}></i>
+            <div class={styles.logoName}>乐团管理系统</div>
+          </div>
+          <div class={styles.footer}>
+            Copyright © 2022 管乐迷, Inc.ALL Rights Reserved
           </div>
         </div>
+
+        <div class={styles.loginSection}>
+          <ElForm ref="loginForm"
+            model={this.loginForm}
+            rules={this.loginRules}
+            class={styles.loginForm}
+            auto-complete="on"
+            label-position="left">
+            <div class={styles.titleContainer}>登录</div>
+            <ElFormItem prop="username"
+              class={styles.logitem}>
+              <span class={styles.svgContainer}>
+                <img class={styles.icon} src="/src/icons/svg/user.svg" alt="" />
+              </span>
+              <ElInput ref="username"
+                class={styles.loginInput}
+                v-model={this.loginForm.username}
+                placeholder="请输入用户名"
+                type="text"
+                tabindex="1"
+                auto-complete="off" />
+            </ElFormItem>
+            <ElFormItem prop="password"
+              class={styles.logitem}>
+              <span class={styles.svgContainer}>
+                <img class={styles.icon} src="/src/icons/svg/password.svg" alt="" />
+              </span>
+              <ElInput
+                ref="password"
+                class={styles.loginInput}
+                v-model={this.loginForm.password}
+                type={this.passwordType}
+                placeholder="请输入密码"
+                tabindex="2"
+                auto-complete="off" />
+              <span class={styles.showPwd} onClick={this.showPwd}>
+                { this.passwordType === 'password' ? <img class={styles.icon} src="/src/icons/svg/eye.svg" alt="" /> : <img class={styles.icon} src="/src/icons/svg/eye-open.svg" alt="" /> }
+              </span>
+            </ElFormItem>
+            <div class={styles.remberBox} onClick={() => { this.isSaveUserInfo = !this.isSaveUserInfo }}>
+              <div class={[this.isSaveUserInfo ? styles.checked : '', styles.dotWrap]}></div>
+              记住密码
+            </div>
+            <div class={[!this.loginForm.username || !this.loginForm.password ? styles.disabled : '', styles.loginBtn]}
+              onClick={this.handleLogin}>登录</div>
+          </ElForm>
+
+        </div>
       </div>
     )
   }

+ 7 - 7
src/permission.ts

@@ -3,19 +3,19 @@ import router from "./router";
 import request from '/src/helpers/request'
 import { ElMessage } from "element-plus";
 import { state } from "./state";
-// import NProgress from "nprogress"; // progress bar
-// import "nprogress/nprogress.css"; // progress bar style
+import NProgress from "nprogress"; // progress bar
+import "nprogress/nprogress.css"; // progress bar style
 import { getToken } from "./utils/auth";
 // import getPageTitle from '@/utils/get-page-title'
 
-// NProgress.configure({ showSpinner: false }); // NProgress Configuration
+NProgress.configure({ showSpinner: false }); // NProgress Configuration
 
 const whiteList = ["/login"]; // no redirect whitelist
 
 router.beforeEach(async (to, from, next) => {
   // from.query = to.query
   // start progress bar
-  // NProgress.start();
+  NProgress.start();
   const hasToken = getToken();
   console.log(hasToken)
   if (hasToken) {
@@ -23,7 +23,7 @@ router.beforeEach(async (to, from, next) => {
       // 如果有tonken直接跳转到首页
       next({ path: "/" });
 
-      // NProgress.done();
+      NProgress.done();
     } else {
       const hasGetUserInfo = state.user?.phone;
       // 有名字 说明有用户信息 跳走
@@ -43,7 +43,7 @@ router.beforeEach(async (to, from, next) => {
             ElMessage.error(error.msg);
           }
           next(`/login`);
-          // NProgress.done();
+          NProgress.done();
         }
       }
     }
@@ -61,5 +61,5 @@ router.beforeEach(async (to, from, next) => {
 
 router.afterEach(() => {
   // finish progress bar
-  // NProgress.done();
+  NProgress.done();
 });

+ 25 - 0
src/utils/auth.ts

@@ -1,3 +1,28 @@
+import Cookies from 'js-cookie'
+const TokenKeyMain = 'dy_admin_token'
+
+const TokenKey = 'live_admin_token'
+
 export const getToken = () => {
+
   return localStorage.getItem('Authorization')
+}
+
+export function setToken (token) {
+  return Cookies.set(TokenKey, token)
+}
+
+export function removeToken () {
+  return Cookies.remove(TokenKey)
+}
+
+export function removeTenant() {
+  // 移除跟机构相关信息
+  sessionStorage.removeItem('tenantRenewStatus')
+  sessionStorage.removeItem('tenantConfig')
+  sessionStorage.removeItem('baseTenantId')
+}
+
+export function removeCrossToken () {
+  return Cookies.remove(CrossTokenKey, { domain: getCookieDomain() })
 }

+ 7 - 0
src/utils/validate.ts

@@ -0,0 +1,7 @@
+/**
+ * @param {string} path
+ * @returns {Boolean}
+ */
+ export function isExternal(path: string) {
+  return /^(https?:|mailto:|tel:)/.test(path)
+}

+ 5 - 2
tsconfig.json

@@ -17,6 +17,9 @@
       ]
     },
   },
-  "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
-  "references": [{ "path": "./tsconfig.node.json" }]
+  "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue", "src/icons/index.js"],
+  "references": [{ "path": "./tsconfig.node.json" }],
+  "exclude": [
+    "node_modules"
+  ]
 }

+ 17 - 1
vite.config.ts

@@ -12,7 +12,19 @@ export default defineConfig({
   // '/src': resolve(__dirname, './src')
   resolve: {
     alias: {
-      '/src': resolve(__dirname, './src'),
+      // '/src': resolve(__dirname, './src'),
+    }
+  },
+  css: {
+    preprocessorOptions: {
+      less: {
+        // lessOptions: {
+        //   modifyVars: {
+        //     '@blue': '#14928A',
+        //     '@nav-bar-icon-color': '#14928A'
+        //   }
+        // }
+      }
     }
   },
   plugins: [
@@ -53,6 +65,10 @@ export default defineConfig({
       '/api-web': {
         target: proxyUrl,
         changeOrigin: true
+      },
+      '/api-auth': {
+        target: proxyUrl,
+        changeOrigin: true
       }
     }
   }

+ 225 - 4
yarn.lock

@@ -939,6 +939,16 @@
     "@babel/helper-validator-identifier" "^7.16.7"
     to-fast-properties "^2.0.0"
 
+"@ctrl/tinycolor@^3.4.0":
+  version "3.4.0"
+  resolved "https://registry.npmmirror.com/@ctrl/tinycolor/-/tinycolor-3.4.0.tgz#c3c5ae543c897caa9c2a68630bed355be5f9990f"
+  integrity sha512-JZButFdZ1+/xAfpguQHoabIXkcqRRKpMrWKBkpEZZyxfY9C1DpADFB8PEqGSTeFr135SaTRfKqGKx5xSCLI7ZQ==
+
+"@element-plus/icons-vue@^0.2.6":
+  version "0.2.7"
+  resolved "https://registry.npmmirror.com/@element-plus/icons-vue/-/icons-vue-0.2.7.tgz#c0b75363098bf1fba414e18706604bfe5057ae1b"
+  integrity sha512-S8kDbfVaWkQvbUYQE1ui448tzaHfUvyESCep9J6uPRlViyQPXjdIfwLBhV6AmQSOfFS8rL+xehJGhvzPXLrSBg==
+
 "@emmetio/abbreviation@^2.2.3":
   version "2.2.3"
   resolved "https://registry.npmmirror.com/@emmetio/abbreviation/-/abbreviation-2.2.3.tgz#2b3c0383c1a4652f677d5b56fb3f1616fe16ef10"
@@ -997,6 +1007,11 @@
     "@nodelib/fs.scandir" "2.1.5"
     fastq "^1.6.0"
 
+"@popperjs/core@^2.11.2":
+  version "2.11.2"
+  resolved "https://registry.npmmirror.com/@popperjs/core/-/core-2.11.2.tgz#830beaec4b4091a9e9398ac50f865ddea52186b9"
+  integrity sha512-92FRmppjjqz29VMJ2dn+xdyXZBrMlE42AV6Kq6BwjWV7CNUW1hs2FtxSNLQE+gJhaZ6AAmYuO9y8dshhcBl7vA==
+
 "@rollup/plugin-babel@^5.2.0":
   version "5.3.0"
   resolved "https://registry.npmmirror.com/@rollup/plugin-babel/-/plugin-babel-5.3.0.tgz#9cb1c5146ddd6a4968ad96f209c50c62f92f9879"
@@ -1042,6 +1057,23 @@
     estree-walker "^2.0.1"
     picomatch "^2.2.2"
 
+"@rongcloud/engine@~5.1.1":
+  version "5.1.1"
+  resolved "https://registry.npmmirror.com/@rongcloud/engine/-/engine-5.1.1.tgz#42cecf082c4cd0575129b671f866459162afd4c1"
+  integrity sha512-saNt2P6LBeWd60GYDZ5x4vx62yMKIjDB54hWw+Kejy8Fu762o7ZFfiHWR8XzTd5hObkNmiT8HOTN47cySTNofg==
+
+"@rongcloud/imlib-next@^5.1.1":
+  version "5.1.1"
+  resolved "https://registry.npmmirror.com/@rongcloud/imlib-next/-/imlib-next-5.1.1.tgz#cd389493c5f47c60f2f6ca52ab2024bdc10b8315"
+  integrity sha512-EKo8ZracIqyuV6s7KlXmTtEp/aa8KRQJyeE70AyGlekWY37TxnSVkKla1M8v4b8WShTacW6DyWpyrkRu3qpBMg==
+  dependencies:
+    "@rongcloud/engine" "~5.1.1"
+
+"@rongcloud/plugin-rtc@^5.3.1":
+  version "5.3.1"
+  resolved "https://registry.npmmirror.com/@rongcloud/plugin-rtc/-/plugin-rtc-5.3.1.tgz#1477fd09268cbee7f47e30b399d4139a62dc7163"
+  integrity sha512-v/OffS9hbGYdnJ18vUIShfIl0oC91cJ0HW6RO5pGN7IskEreQzIS3pOmbDqmU1i0YQa/Z5QhZq1sy+rNOxM6Rg==
+
 "@surma/rollup-plugin-off-main-thread@^2.2.3":
   version "2.2.3"
   resolved "https://registry.npmmirror.com/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz#ee34985952ca21558ab0d952f00298ad2190c053"
@@ -1074,6 +1106,11 @@
   resolved "https://registry.npmmirror.com/@types/trusted-types/-/trusted-types-2.0.2.tgz#fc25ad9943bcac11cceb8168db4f275e0e72e756"
   integrity sha512-F5DIZ36YVLE+PN+Zwws4kJogq47hNgX3Nx6WyDJ3kcplxyke3XIzB8uK5n/Lpm1HBsbGzd6nmGehL8cPekP+Tg==
 
+"@types/webpack-env@^1.16.3":
+  version "1.16.3"
+  resolved "https://registry.npmmirror.com/@types/webpack-env/-/webpack-env-1.16.3.tgz#b776327a73e561b71e7881d0cd6d34a1424db86a"
+  integrity sha512-9gtOPPkfyNoEqCQgx4qJKkuNm/x0R2hKR7fdl7zvTJyHnIisuE/LfvXOsYWL0o3qq6uiBnKZNNNzi3l0y/X+xw==
+
 "@vitejs/plugin-legacy@^1.7.1":
   version "1.7.1"
   resolved "https://registry.npmmirror.com/@vitejs/plugin-legacy/-/plugin-legacy-1.7.1.tgz#6236d2f5ea5f11f6406070bb69e700e781f86125"
@@ -1284,6 +1321,21 @@
   resolved "https://registry.npmmirror.com/@vue/shared/-/shared-3.2.31.tgz#c90de7126d833dcd3a4c7534d534be2fb41faa4e"
   integrity sha512-ymN2pj6zEjiKJZbrf98UM2pfDd6F2H7ksKw7NDt/ZZ1fh5Ei39X5tABugtT03ZRlWd9imccoK0hE8hpjpU7irQ==
 
+"@vueuse/core@^7.6.0":
+  version "7.6.2"
+  resolved "https://registry.npmmirror.com/@vueuse/core/-/core-7.6.2.tgz#1b9aa92048991189fac31577ff439296efa5fb4a"
+  integrity sha512-bjAbXJVJO6aElMaZtDz2B70C0L6jFk/jGVqJxWZS5huffxA6dW5DN6tQQJwzOnx9B9rDhePHJIFKsix0qZIH2Q==
+  dependencies:
+    "@vueuse/shared" "7.6.2"
+    vue-demi "*"
+
+"@vueuse/shared@7.6.2":
+  version "7.6.2"
+  resolved "https://registry.npmmirror.com/@vueuse/shared/-/shared-7.6.2.tgz#6d83bdb003cd8a56dc779fe501e73a4cb755b802"
+  integrity sha512-ThDld4Mx501tahRuHV6qJGkwCr17GknZrOzlD02Na9qJcH7Pq0quNTLx5cNDou7b1CKNvE3BXi2w/hz9KuPNTQ==
+  dependencies:
+    vue-demi "*"
+
 acorn@^7.1.1:
   version "7.4.1"
   resolved "https://registry.npmmirror.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa"
@@ -1316,6 +1368,11 @@ assert-never@^1.2.1:
   resolved "https://registry.npmmirror.com/assert-never/-/assert-never-1.2.1.tgz#11f0e363bf146205fb08193b5c7b90f4d1cf44fe"
   integrity sha512-TaTivMB6pYI1kXwrFlEhLeGfOqoDNdTxjCdwRfFFkEA30Eu+k48W34nlok2EYWJfFFzqaEmichdNM7th6M5HNw==
 
+async-validator@^4.0.7:
+  version "4.0.7"
+  resolved "https://registry.npmmirror.com/async-validator/-/async-validator-4.0.7.tgz#034a0fd2103a6b2ebf010da75183bec299247afe"
+  integrity sha512-Pj2IR7u8hmUEDOwB++su6baaRi+QvsgajuFB9j95foM1N2gy5HM4z60hfusIO0fBPG5uLAEl6yCJr1jNSVugEQ==
+
 async@0.9.x:
   version "0.9.2"
   resolved "https://registry.npmmirror.com/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d"
@@ -1490,6 +1547,13 @@ convert-source-map@^1.7.0:
   dependencies:
     safe-buffer "~5.1.1"
 
+copy-anything@^2.0.1:
+  version "2.0.6"
+  resolved "https://registry.npmmirror.com/copy-anything/-/copy-anything-2.0.6.tgz#092454ea9584a7b7ad5573062b2a87f5900fc480"
+  integrity sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==
+  dependencies:
+    is-what "^3.14.1"
+
 core-js-compat@^3.20.2, core-js-compat@^3.21.0:
   version "3.21.0"
   resolved "https://registry.npmmirror.com/core-js-compat/-/core-js-compat-3.21.0.tgz#bcc86aa5a589cee358e7a7fa0a4979d5a76c3885"
@@ -1518,6 +1582,13 @@ dayjs@^1.10.7:
   resolved "https://registry.npmmirror.com/dayjs/-/dayjs-1.10.7.tgz#2cf5f91add28116748440866a0a1d26f3a6ce468"
   integrity sha512-P6twpd70BcPK34K26uJ1KT3wlhpuOAPoMwJzpsIWUxHZ7wpmbdZL/hQqBDfz7hGurYSa5PhzdhDHtt319hL3ig==
 
+debug@^3.2.6:
+  version "3.2.7"
+  resolved "https://registry.npmmirror.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a"
+  integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==
+  dependencies:
+    ms "^2.1.1"
+
 debug@^4.1.0, debug@^4.1.1, debug@^4.3.3:
   version "4.3.3"
   resolved "https://registry.npmmirror.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664"
@@ -1584,6 +1655,23 @@ electron-to-chromium@^1.4.17:
   resolved "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.4.69.tgz#d52eb7887d2ec5ba62a8cb3491b990983cb6d2e0"
   integrity sha512-0rxK21MqWhN/fVUXNOeBksRlw79Wq26y6R8lxEEL2v7vwzRWbYhXI7Id5msee7/q1NNgu4mG78qaablN2xtfTQ==
 
+element-plus@^2.0.2:
+  version "2.0.2"
+  resolved "https://registry.npmmirror.com/element-plus/-/element-plus-2.0.2.tgz#1e4a29fbc6629255b96845a99202773e774223a1"
+  integrity sha512-URjC0HwwiqtlLxqTmHXQ31WXrdAq4ChWyyn52OcQs3PRsnMPfahGVq2AWnfzzlzlhVeI5lY3HQiuB1zDathS+g==
+  dependencies:
+    "@ctrl/tinycolor" "^3.4.0"
+    "@element-plus/icons-vue" "^0.2.6"
+    "@popperjs/core" "^2.11.2"
+    "@vueuse/core" "^7.6.0"
+    async-validator "^4.0.7"
+    dayjs "^1.10.7"
+    lodash "^4.17.21"
+    lodash-es "^4.17.21"
+    lodash-unified "^1.0.1"
+    memoize-one "^6.0.0"
+    normalize-wheel-es "^1.1.1"
+
 emmet@^2.3.0:
   version "2.3.6"
   resolved "https://registry.npmmirror.com/emmet/-/emmet-2.3.6.tgz#1d93c1ac03164da9ddf74864c1f341ed6ff6c336"
@@ -1609,6 +1697,13 @@ entities@^3.0.1:
   resolved "https://registry.npmmirror.com/entities/-/entities-3.0.1.tgz#2b887ca62585e96db3903482d336c1006c3001d4"
   integrity sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==
 
+errno@^0.1.1:
+  version "0.1.8"
+  resolved "https://registry.npmmirror.com/errno/-/errno-0.1.8.tgz#8bb3e9c7d463be4976ff888f76b4809ebc2e811f"
+  integrity sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==
+  dependencies:
+    prr "~1.0.1"
+
 es-abstract@^1.19.1:
   version "1.19.1"
   resolved "https://registry.npmmirror.com/es-abstract/-/es-abstract-1.19.1.tgz#d4885796876916959de78edaa0df456627115ec3"
@@ -1907,7 +2002,7 @@ globals@^11.1.0:
   resolved "https://registry.npmmirror.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e"
   integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==
 
-graceful-fs@^4.1.6, graceful-fs@^4.2.0:
+graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0:
   version "4.2.9"
   resolved "https://registry.npmmirror.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96"
   integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==
@@ -1966,6 +2061,13 @@ htmlparser2@^7.1.2:
     domutils "^2.8.0"
     entities "^3.0.1"
 
+iconv-lite@^0.4.4:
+  version "0.4.24"
+  resolved "https://registry.npmmirror.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
+  integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
+  dependencies:
+    safer-buffer ">= 2.1.2 < 3"
+
 iconv-lite@^0.6.2:
   version "0.6.3"
   resolved "https://registry.npmmirror.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501"
@@ -1978,6 +2080,11 @@ idb@^6.1.4:
   resolved "https://registry.npmmirror.com/idb/-/idb-6.1.5.tgz#dbc53e7adf1ac7c59f9b2bf56e00b4ea4fce8c7b"
   integrity sha512-IJtugpKkiVXQn5Y+LteyBCNk1N8xpGV3wWZk9EVtZWH8DYkjBn0bX1XnGP9RkyZF0sAcywa6unHqSWKe7q4LGw==
 
+image-size@~0.5.0:
+  version "0.5.5"
+  resolved "https://registry.npmmirror.com/image-size/-/image-size-0.5.5.tgz#09dfd4ab9d20e29eb1c3e80b8990378df9e3cb9c"
+  integrity sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==
+
 inflight@^1.0.4:
   version "1.0.6"
   resolved "https://registry.npmmirror.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
@@ -2135,6 +2242,11 @@ is-weakref@^1.0.1:
   dependencies:
     call-bind "^1.0.2"
 
+is-what@^3.14.1:
+  version "3.14.1"
+  resolved "https://registry.npmmirror.com/is-what/-/is-what-3.14.1.tgz#e1222f46ddda85dead0fd1c9df131760e77755c1"
+  integrity sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==
+
 isomorphic-fetch@^2.2.1:
   version "2.2.1"
   resolved "https://registry.npmmirror.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9"
@@ -2162,6 +2274,11 @@ jest-worker@^26.2.1:
     merge-stream "^2.0.0"
     supports-color "^7.0.0"
 
+js-cookie@^3.0.1:
+  version "3.0.1"
+  resolved "https://registry.npmmirror.com/js-cookie/-/js-cookie-3.0.1.tgz#9e39b4c6c2f56563708d7d31f6f5f21873a92414"
+  integrity sha512-+0rgsUXZu4ncpPxRL+lNEptWMOWl9etvPHc/koSRp6MPwpRYAhmk0dUG00J4bxVV3r9uUzfo24wW0knS07SKSw==
+
 js-stringify@^1.0.2:
   version "1.0.2"
   resolved "https://registry.npmmirror.com/js-stringify/-/js-stringify-1.0.2.tgz#1736fddfd9724f28a3682adc6230ae7e4e9679db"
@@ -2231,11 +2348,38 @@ jstransformer@1.0.0:
     is-promise "^2.0.0"
     promise "^7.0.1"
 
+less@^4.1.2:
+  version "4.1.2"
+  resolved "https://registry.npmmirror.com/less/-/less-4.1.2.tgz#6099ee584999750c2624b65f80145f8674e4b4b0"
+  integrity sha512-EoQp/Et7OSOVu0aJknJOtlXZsnr8XE8KwuzTHOLeVSEx8pVWUICc8Q0VYRHgzyjX78nMEyC/oztWFbgyhtNfDA==
+  dependencies:
+    copy-anything "^2.0.1"
+    parse-node-version "^1.0.1"
+    tslib "^2.3.0"
+  optionalDependencies:
+    errno "^0.1.1"
+    graceful-fs "^4.1.2"
+    image-size "~0.5.0"
+    make-dir "^2.1.0"
+    mime "^1.4.1"
+    needle "^2.5.2"
+    source-map "~0.6.0"
+
 leven@^3.1.0:
   version "3.1.0"
   resolved "https://registry.npmmirror.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2"
   integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==
 
+lodash-es@^4.17.21:
+  version "4.17.21"
+  resolved "https://registry.npmmirror.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee"
+  integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==
+
+lodash-unified@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.npmmirror.com/lodash-unified/-/lodash-unified-1.0.1.tgz#7c57e139ab475292c1731725386b929c819628a1"
+  integrity sha512-Py+twfpWn+2dFQWCuGcp21WiQRwZwnm1cyE3piSt/VtBVKVyxlR58WgOVRzXtmdmDRGJKH8F8GPaA29WK/yK8g==
+
 lodash.debounce@^4.0.8:
   version "4.0.8"
   resolved "https://registry.npmmirror.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
@@ -2261,7 +2405,7 @@ lodash.transform@^4.6.0:
   resolved "https://registry.npmmirror.com/lodash.transform/-/lodash.transform-4.6.0.tgz#12306422f63324aed8483d3f38332b5f670547a0"
   integrity sha512-LO37ZnhmBVx0GvOU/caQuipEh4GN82TcWv3yHlebGDgOxbxiwwzW5Pcx2AcvpIv2WmvmSMoC492yQFNhy/l/UQ==
 
-lodash@^4.17.20:
+lodash@^4.17.20, lodash@^4.17.21:
   version "4.17.21"
   resolved "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
   integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
@@ -2280,6 +2424,19 @@ magic-string@^0.25.0, magic-string@^0.25.7:
   dependencies:
     sourcemap-codec "^1.4.4"
 
+make-dir@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.npmmirror.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5"
+  integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==
+  dependencies:
+    pify "^4.0.1"
+    semver "^5.6.0"
+
+memoize-one@^6.0.0:
+  version "6.0.0"
+  resolved "https://registry.npmmirror.com/memoize-one/-/memoize-one-6.0.0.tgz#b2591b871ed82948aee4727dc6abceeeac8c1045"
+  integrity sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==
+
 merge-stream@^2.0.0:
   version "2.0.0"
   resolved "https://registry.npmmirror.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60"
@@ -2298,6 +2455,11 @@ micromatch@^4.0.4:
     braces "^3.0.1"
     picomatch "^2.2.3"
 
+mime@^1.4.1:
+  version "1.6.0"
+  resolved "https://registry.npmmirror.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
+  integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==
+
 minimatch@^3.0.4:
   version "3.1.1"
   resolved "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.1.tgz#879ad447200773912898b46cd516a7abbb5e50b0"
@@ -2315,11 +2477,25 @@ ms@2.1.2:
   resolved "https://registry.npmmirror.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
   integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
 
+ms@^2.1.1:
+  version "2.1.3"
+  resolved "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
+  integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
+
 nanoid@^3.2.0:
   version "3.2.0"
   resolved "https://registry.npmmirror.com/nanoid/-/nanoid-3.2.0.tgz#62667522da6673971cca916a6d3eff3f415ff80c"
   integrity sha512-fmsZYa9lpn69Ad5eDn7FMcnnSR+8R34W9qJEijxYhTbfOWzr22n1QxCMzXLK+ODyW2973V3Fux959iQoUxzUIA==
 
+needle@^2.5.2:
+  version "2.9.1"
+  resolved "https://registry.npmmirror.com/needle/-/needle-2.9.1.tgz#22d1dffbe3490c2b83e301f7709b6736cd8f2684"
+  integrity sha512-6R9fqJ5Zcmf+uYaFgdIHmLwNldn5HbK8L5ybn7Uz+ylX/rnOsSp1AHcvQSrCaFN+qNM1wpymHqD7mVasEOlHGQ==
+  dependencies:
+    debug "^3.2.6"
+    iconv-lite "^0.4.4"
+    sax "^1.2.4"
+
 node-fetch@^1.0.1:
   version "1.7.3"
   resolved "https://registry.npmmirror.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef"
@@ -2333,6 +2509,16 @@ node-releases@^2.0.1:
   resolved "https://registry.npmmirror.com/node-releases/-/node-releases-2.0.2.tgz#7139fe71e2f4f11b47d4d2986aaf8c48699e0c01"
   integrity sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg==
 
+normalize-wheel-es@^1.1.1:
+  version "1.1.1"
+  resolved "https://registry.npmmirror.com/normalize-wheel-es/-/normalize-wheel-es-1.1.1.tgz#a8096db6a56f94332d884fd8ebeda88f2fc79569"
+  integrity sha512-157VNH4CngrcsvF8xOVOe22cwniIR3nxSltdctvQeHZj8JttEeOXffK28jucWfWBXs0QNetAumjc1GiInnwX4w==
+
+nprogress@^0.2.0:
+  version "0.2.0"
+  resolved "https://registry.npmmirror.com/nprogress/-/nprogress-0.2.0.tgz#cb8f34c53213d895723fcbab907e9422adbcafb1"
+  integrity sha512-I19aIingLgR1fmhftnbWWO3dXc0hSxqHQHQb3H8m+K3TnEn/iSeTZZOyvKXWqQESMwuUVnatlCnZdLBZZt2VSA==
+
 object-assign@^4.1.1:
   version "4.1.1"
   resolved "https://registry.npmmirror.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
@@ -2365,6 +2551,11 @@ once@^1.3.0:
   dependencies:
     wrappy "1"
 
+parse-node-version@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.npmmirror.com/parse-node-version/-/parse-node-version-1.0.1.tgz#e2b5dbede00e7fa9bc363607f53327e8b073189b"
+  integrity sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==
+
 path-is-absolute@^1.0.0:
   version "1.0.1"
   resolved "https://registry.npmmirror.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
@@ -2385,6 +2576,11 @@ picomatch@^2.2.2, picomatch@^2.2.3:
   resolved "https://registry.npmmirror.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
   integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
 
+pify@^4.0.1:
+  version "4.0.1"
+  resolved "https://registry.npmmirror.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231"
+  integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==
+
 postcss@^8.1.10, postcss@^8.4.6:
   version "8.4.6"
   resolved "https://registry.npmmirror.com/postcss/-/postcss-8.4.6.tgz#c5ff3c3c457a23864f32cb45ac9b741498a09ae1"
@@ -2406,6 +2602,11 @@ promise@^7.0.1:
   dependencies:
     asap "~2.0.3"
 
+prr@~1.0.1:
+  version "1.0.1"
+  resolved "https://registry.npmmirror.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476"
+  integrity sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==
+
 pug-attrs@^3.0.0:
   version "3.0.0"
   resolved "https://registry.npmmirror.com/pug-attrs/-/pug-attrs-3.0.0.tgz#b10451e0348165e31fad1cc23ebddd9dc7347c41"
@@ -2647,16 +2848,26 @@ safe-buffer@~5.1.1:
   resolved "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
   integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
 
-"safer-buffer@>= 2.1.2 < 3.0.0":
+"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0":
   version "2.1.2"
   resolved "https://registry.npmmirror.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
   integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
 
+sax@^1.2.4:
+  version "1.2.4"
+  resolved "https://registry.npmmirror.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
+  integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==
+
 semver@7.0.0:
   version "7.0.0"
   resolved "https://registry.npmmirror.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e"
   integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==
 
+semver@^5.6.0:
+  version "5.7.1"
+  resolved "https://registry.npmmirror.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
+  integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
+
 semver@^6.1.1, semver@^6.1.2, semver@^6.3.0:
   version "6.3.0"
   resolved "https://registry.npmmirror.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
@@ -2708,7 +2919,7 @@ source-map@^0.5.0:
   resolved "https://registry.npmmirror.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
   integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==
 
-source-map@^0.6.0, source-map@^0.6.1:
+source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0:
   version "0.6.1"
   resolved "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
   integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
@@ -2851,6 +3062,11 @@ tr46@^1.0.1:
   dependencies:
     punycode "^2.1.0"
 
+tslib@^2.3.0:
+  version "2.3.1"
+  resolved "https://registry.npmmirror.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01"
+  integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==
+
 type-fest@^0.16.0:
   version "0.16.0"
   resolved "https://registry.npmmirror.com/type-fest/-/type-fest-0.16.0.tgz#3240b891a78b0deae910dbeb86553e552a148860"
@@ -3089,6 +3305,11 @@ vscode-vue-languageservice@0.29.8:
     vscode-pug-languageservice "0.29.8"
     vscode-typescript-languageservice "0.29.8"
 
+vue-demi@*:
+  version "0.12.1"
+  resolved "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.12.1.tgz#f7e18efbecffd11ab069d1472d7a06e319b4174c"
+  integrity sha512-QL3ny+wX8c6Xm1/EZylbgzdoDolye+VpCXRhI2hug9dJTP3OUJ3lmiKN3CsVV3mOJKwFi0nsstbgob0vG7aoIw==
+
 vue-router@^4.0.12:
   version "4.0.12"
   resolved "https://registry.npmmirror.com/vue-router/-/vue-router-4.0.12.tgz#8dc792cddf5bb1abcc3908f9064136de7e13c460"

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