scorpio 2 anni fa
parent
commit
aeeb3853ec

+ 6 - 9
.eslintrc.cjs

@@ -3,20 +3,17 @@ module.exports = {
     browser: true,
     es2021: true
   },
-  extends: [
-    'plugin:vue/vue3-essential',
-    'standard'
-  ],
+  extends: ['plugin:vue/vue3-essential', 'standard', 'prettier'],
   parserOptions: {
     ecmaVersion: 'latest',
     sourceType: 'module'
   },
-  plugins: [
-    'vue'
-  ],
+  plugins: ['vue', 'prettier'],
   rules: {
     'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
     'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
-    "vue/multi-word-component-names":"off",
-  }
+    'vue/multi-word-component-names': 'off',
+    'prettier/prettier': 'error'
+  },
+  ignorePatterns: ['**/index.html']
 }

+ 19 - 0
.prettierrc.cjs

@@ -0,0 +1,19 @@
+module.exports = {
+  // 一行的字符数,如果超过会进行换行,默认为80
+  printWidth: 80,
+  // 一个tab代表几个空格数,默认为80
+  tabWidth: 2,
+  // 是否使用tab进行缩进,默认为false,表示用空格进行缩减
+  useTabs: false,
+  // 字符串是否使用单引号,默认为false,使用双引号
+  singleQuote: true,
+  // 行位是否使用分号,默认为true
+  semi: false,
+  // 是否使用尾逗号,有三个可选值"<none|es5|all>"
+  trailingComma: 'none',
+  // 对象大括号直接是否有空格,默认为true,效果:{ foo: bar }
+  bracketSpacing: true,
+  arrowParens: 'avoid',
+  // 开启 eslint 支持
+  eslintIntegration: true,
+}

+ 9 - 0
jsconfig.json

@@ -0,0 +1,9 @@
+{
+  "compilerOptions": {
+    "baseUrl": ".",
+    "module": "commonjs",
+    "target": "es6"
+  },
+  "include": ["src/**/*"],
+  "exclude": ["node_modules", "dist"]
+}

+ 5 - 1
package.json

@@ -32,13 +32,17 @@
   "devDependencies": {
     "@vitejs/plugin-vue": "^3.0.0",
     "axios": "^0.27.2",
-    "eslint": "^8.0.1",
+    "eslint": "^8.37.0",
+    "eslint-config-prettier": "^8.8.0",
     "eslint-config-standard": "^17.0.0",
     "eslint-plugin-import": "^2.25.2",
     "eslint-plugin-n": "^15.0.0",
+    "eslint-plugin-prettier": "^4.2.1",
     "eslint-plugin-promise": "^6.0.0",
     "eslint-plugin-vue": "^9.2.0",
     "js-cookie": "^3.0.1",
+    "prettier": "^2.8.7",
+    "prettier-eslint": "^15.0.1",
     "sass": "^1.54.8",
     "sass-loader": "^13.0.2",
     "vite": "^3.0.0"

+ 9 - 4
src/App.vue

@@ -1,5 +1,5 @@
 <template>
-  <div id='app'>
+  <div id="app">
     <router-view />
   </div>
 </template>
@@ -9,13 +9,18 @@
 // Check out https://vuejs.org/api/sfc-script-setup.html#script-setup
 
 export default {
-  data () {
+  data() {
     return {
       data: ''
     }
   },
-  created () {
-    console.info('%c由%c梧桐研究院%c提供技术支持,版本号: v1.0.0', 'font-size: 14px; margin-bottom: 2px; padding: 6px 8px; color: #fff; background: #707070;', 'font-size: 14px; margin-bottom: 2px; padding: 6px 8px; color: #fff; background: orange;', 'font-size: 14px; margin-bottom: 2px; padding: 6px 8px; color: #fff; background: #707070;')
+  created() {
+    console.info(
+      '%c由%c梧桐研究院%c提供技术支持,版本号: v1.0.0',
+      'font-size: 14px; margin-bottom: 2px; padding: 6px 8px; color: #fff; background: #707070;',
+      'font-size: 14px; margin-bottom: 2px; padding: 6px 8px; color: #fff; background: orange;',
+      'font-size: 14px; margin-bottom: 2px; padding: 6px 8px; color: #fff; background: #707070;'
+    )
   }
 }
 </script>

+ 18 - 18
src/api/login/index.js

@@ -2,46 +2,46 @@ import fetch from '../fetch.js'
 
 export default {
   /**
-     * 获取验证码
-     * @returns {*}
-     */
-  captcha () {
+   * 获取验证码
+   * @returns {*}
+   */
+  captcha() {
     return fetch('/blade-auth/oauth/captcha')
   },
-  login (param, hader) {
+  login(param, hader) {
     return fetch('/blade-auth/oauth/token', param, 'post', 'form', {
       'Tenant-Id': '000000',
       'Captcha-Key': hader.captchaKey,
       'Captcha-Code': hader.captchaCode
     })
   },
-  sendSMS (params) {
+  sendSMS(params) {
     return fetch('/blade-pc-applet/wechat/home/getHomeNewList', params)
   },
   /**
-     * 退出登录
-     * @returns {Promise<unknown>}
-     */
-  logout () {
+   * 退出登录
+   * @returns {Promise<unknown>}
+   */
+  logout() {
     return fetch('/blade-auth/oauth/logout')
   },
-  getUserInfo () {
+  getUserInfo() {
     return fetch('/blade-project-manage-v2/other/v2/getUserInfo')
   },
   /**
-     * 获取按钮权限
-     * @returns {Promise | Promise<unknown>}
-     */
-  getPermission () {
+   * 获取按钮权限
+   * @returns {Promise | Promise<unknown>}
+   */
+  getPermission() {
     return fetch('/blade-system/menu/buttons?clientId=project_web')
   },
-  qrCode () {
+  qrCode() {
     return fetch('/wutong-base/oauth/qrcodeLogin')
   },
-  qrCodeLogin (params) {
+  qrCodeLogin(params) {
     return fetch('/wutong-base/oauth/getUserInfo', params)
   },
-  loginByCode (param) {
+  loginByCode(param) {
     return fetch('/blade-auth/oauth/token', param, 'post', 'form', {
       'Tenant-Id': '000000'
     })

+ 9 - 6
src/components/base-button.vue

@@ -1,14 +1,17 @@
 <template>
-  <div :class="type === '1' ? 'btn' : 'btn1'" :style='`width:${width}px`' class="flex flex-center mr-5 font-12 pointer">
+  <div
+    :class="type === '1' ? 'btn' : 'btn1'"
+    :style="`width:${width}px`"
+    class="flex flex-center mr-5 font-12 pointer"
+  >
     <el-icon :color="type === '1' ? 'white' : '#E9A856'" size="16px">
       <component :is="icon"></component>
     </el-icon>
-    <div class="ml-5 nowrap"> {{ title }}</div>
+    <div class="ml-5 nowrap">{{ title }}</div>
   </div>
 </template>
 
 <script>
-
 export default {
   name: 'base-button',
   props: {
@@ -44,7 +47,7 @@ export default {
   padding: 8px 16px;
   height: 18px;
   font-size: 14px;
-  background-color: #AB7630;
+  background-color: #ab7630;
   color: white;
 }
 
@@ -54,7 +57,7 @@ export default {
   height: 18px;
   font-size: 14px;
   background-color: white;
-  color: #AB7630;
-  border: 1px solid #ECAB56;
+  color: #ab7630;
+  border: 1px solid #ecab56;
 }
 </style>

+ 9 - 6
src/components/main-button.vue

@@ -1,9 +1,12 @@
 <template>
-  <div :style='`width:${width}px`' class="flex flex-center mr-10 mt-5 font-12 main pointer">
+  <div
+    :style="`width:${width}px`"
+    class="flex flex-center mr-10 mt-5 font-12 main pointer"
+  >
     <el-icon v-if="type === '1'" class="mr-5" color="#E9A956">
       <component :is="icon"></component>
     </el-icon>
-    <div class="nowrap bold" style="color: #707070"> {{ title }}</div>
+    <div class="nowrap bold" style="color: #707070">{{ title }}</div>
   </div>
 </template>
 
@@ -29,7 +32,7 @@ export default {
     }
   },
   methods: {
-    click () {
+    click() {
       this.$emit('click')
     }
   }
@@ -39,9 +42,9 @@ export default {
 <style lang="scss" scoped>
 .main {
   border-radius: 20px;
-  border: 1px solid #AB7630;
-  color: #ECAB56;
+  border: 1px solid #ab7630;
+  color: #ecab56;
   height: 32px;
-  line-height: 34px
+  line-height: 34px;
 }
 </style>

+ 77 - 52
src/components/upload-file.vue

@@ -1,49 +1,70 @@
 <template>
-  <div class='full-width custom'>
-    <el-upload ref='upload'
-               :accept="accept"
-               :action="action"
-               :auto-upload='false'
-               :data='data'
-               :file-list="tmpFileList"
-               :headers="headers"
-               :limit="max"
-               :list-type="listType"
-               :multiple="max > 1"
-               :on-change="handleChange"
-               :on-exceed="maxChange"
-               :on-progress="progress"
-               :on-remove="remove"
-               :on-success="success"
-               :show-file-list="showList"
-               style='width: 100%;'>
-      <div class=' flex flex-col flex-justify-start full-width'>
-        <div class='flex flex-align-center flex-justify-start'>
-          <el-button slot="trigger" size="small" type="primary">选取文件</el-button>
-          <span class='ml-10'>共{{ tmpFileList.length }}个文件,上传速度:{{ speed }}</span>
+  <div class="full-width custom">
+    <el-upload
+      ref="upload"
+      :accept="accept"
+      :action="action"
+      :auto-upload="false"
+      :data="data"
+      :file-list="tmpFileList"
+      :headers="headers"
+      :limit="max"
+      :list-type="listType"
+      :multiple="max > 1"
+      :on-change="handleChange"
+      :on-exceed="maxChange"
+      :on-progress="progress"
+      :on-remove="remove"
+      :on-success="success"
+      :show-file-list="showList"
+      style="width: 100%"
+    >
+      <div class="flex flex-col flex-justify-start full-width">
+        <div class="flex flex-align-center flex-justify-start">
+          <el-button slot="trigger" size="small" type="primary"
+            >选取文件</el-button
+          >
+          <span class="ml-10"
+            >共{{ tmpFileList.length }}个文件,上传速度:{{ speed }}</span
+          >
         </div>
-        <el-divider/>
+        <el-divider />
       </div>
     </el-upload>
 
-    <div class='custom full-width' style='height: 300px'>
-      <el-empty v-if='tmpFileList.length === 0' description='暂无文件'/>
-      <div v-else class='box'>
-        <div v-for="item in tmpFileList" :key="item.name"
-             class="flex flex-col full-width border-bottom padding-bottom ">
-          <div class='full-width flex flex-justify-between'>
-            <span class="margin  text-left font-12 " style="flex:3">{{ item.name }}</span>
-            <span class="margin  font-12  text-right" style="flex:1">文件大小:{{ bytesToSize(item.size) }}</span>
+    <div class="custom full-width" style="height: 300px">
+      <el-empty v-if="tmpFileList.length === 0" description="暂无文件" />
+      <div v-else class="box">
+        <div
+          v-for="item in tmpFileList"
+          :key="item.name"
+          class="flex flex-col full-width border-bottom padding-bottom"
+        >
+          <div class="full-width flex flex-justify-between">
+            <span class="margin text-left font-12" style="flex: 3">{{
+              item.name
+            }}</span>
+            <span class="margin font-12 text-right" style="flex: 1"
+              >文件大小:{{ bytesToSize(item.size) }}</span
+            >
           </div>
-          <el-progress :format='format' :percentage="item.percentage" :show-text='true' :stroke-width='20'
-                       class='margin-left margin-right' text-inside></el-progress>
+          <el-progress
+            :format="format"
+            :percentage="item.percentage"
+            :show-text="true"
+            :stroke-width="20"
+            class="margin-left margin-right"
+            text-inside
+          ></el-progress>
         </div>
       </div>
     </div>
-    <el-divider/>
-    <div class='full-width flex flex-justify-end'>
-      <el-button plain size="small" @click='close'>取消上传</el-button>
-      <el-button size="small" type="primary" @click='submint'>开始上传</el-button>
+    <el-divider />
+    <div class="full-width flex flex-justify-end">
+      <el-button plain size="small" @click="close">取消上传</el-button>
+      <el-button size="small" type="primary" @click="submint"
+        >开始上传</el-button
+      >
     </div>
   </div>
 </template>
@@ -91,7 +112,7 @@ export default {
       default: api.uploadPath
     }
   },
-  data () {
+  data() {
     return {
       fileList: [],
       tmpFileList: [],
@@ -99,16 +120,18 @@ export default {
       oldLoadsize: 0,
       speed: '',
       headers: {
-        Authorization: `Basic ${Base64.encode(`${website.clientId}:${website.clientSecret}`)}`,
+        Authorization: `Basic ${Base64.encode(
+          `${website.clientId}:${website.clientSecret}`
+        )}`,
         'Blade-Auth': 'bearer ' + getToken()
       }
     }
   },
   methods: {
-    format (percentage) {
+    format(percentage) {
       return percentage.toFixed(2) + '%'
     },
-    progress (event, file, fileList) {
+    progress(event, file, fileList) {
       this.speed = this.uploadSpeed(event)
       this.tmpFileList.map(item => {
         if (item.uid === file.uid) {
@@ -117,7 +140,7 @@ export default {
         return item
       })
     },
-    uploadSpeed (evt) {
+    uploadSpeed(evt) {
       const timestamp = new Date().valueOf()
       const duration = timestamp - this.oldTimestamp // 间隔时间(毫秒)
       if (duration > 0) {
@@ -133,21 +156,23 @@ export default {
         return bitrate
       }
     },
-    bytesToSize (bytes) {
+    bytesToSize(bytes) {
       const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB']
       if (bytes === 0) return 'n/a'
       const i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)))
       if (i === 0) return bytes + ' ' + sizes[i]
       return (bytes / Math.pow(1024, i)).toFixed(1) + ' ' + sizes[i]
     },
-    handleChange (file, fileList) {
+    handleChange(file, fileList) {
       this.tmpFileList = fileList
     },
-    maxChange () {
+    maxChange() {
       this.$message.warning(`最多只能上传${this.max}个文件`)
     },
-    success () {
-      const finishList = this.tmpFileList.filter(sub => sub.status === 'success')
+    success() {
+      const finishList = this.tmpFileList.filter(
+        sub => sub.status === 'success'
+      )
       if (finishList.length === this.tmpFileList.length) {
         this.$emit('success', {
           fileList: this.tmpFileList
@@ -159,20 +184,20 @@ export default {
         }, 2000)
       }
     },
-    close () {
+    close() {
       this.$refs.upload.abort()
       this.$refs.upload.clearFiles()
       this.tmpFileList = []
       this.$emit('close')
     },
-    submint () {
+    submint() {
       if (this.tmpFileList && this.tmpFileList.length === 0) {
         this.$message.error('请先选择要上传的文件')
         return
       }
       this.$refs.upload.submit()
     },
-    remove (file, fileList) {
+    remove(file, fileList) {
       this.$emit('remove', {
         file,
         fileList
@@ -181,12 +206,12 @@ export default {
   }
 }
 </script>
-<style lang='scss' scoped>
+<style lang="scss" scoped>
 .custom {
   :deep(.el-upload) {
     width: 100%;
   }
-  .box{
+  .box {
     height: 300px;
     overflow-x: scroll;
   }

+ 56 - 40
src/components/uploads.vue

@@ -1,32 +1,42 @@
 <template>
   <div>
-    <el-upload ref='upload'
-               :accept="accept"
-               :action="action"
-               :data='data'
-               :auto-upload='auto'
-               :drag="drag"
-               :file-list="tmpFileList"
-               :headers="headers"
-               :limit="max"
-               :list-type="listType"
-               :multiple="max > 1"
-               :on-change="handleChange"
-               :on-exceed="maxChange"
-               :on-progress="progress"
-               :on-remove="remove"
-               :on-error='onError'
-               :on-success="success"
-               :before-upload="beforeUp"
-               :show-file-list="showList"
-               style='width: 100%;'>
+    <el-upload
+      ref="upload"
+      :accept="accept"
+      :action="action"
+      :data="data"
+      :auto-upload="auto"
+      :drag="drag"
+      :file-list="tmpFileList"
+      :headers="headers"
+      :limit="max"
+      :list-type="listType"
+      :multiple="max > 1"
+      :on-change="handleChange"
+      :on-exceed="maxChange"
+      :on-progress="progress"
+      :on-remove="remove"
+      :on-error="onError"
+      :on-success="success"
+      :before-upload="beforeUp"
+      :show-file-list="showList"
+      style="width: 100%"
+    >
       <div v-if="drag">
         <i class="el-icon-upload"></i>
-        <div class="el-upload__text">将文件/图片拖到此处,或<em>点击上传</em></div>
+        <div class="el-upload__text">
+          将文件/图片拖到此处,或<em>点击上传</em>
+        </div>
       </div>
-      <div v-else class='flex flex-justify-start'>
-        <el-button v-if="showBtn" :loading="loading" icon="el-icon-upload" plain size="mini"
-                   type="primary">{{ btnText }}
+      <div v-else class="flex flex-justify-start">
+        <el-button
+          v-if="showBtn"
+          :loading="loading"
+          icon="el-icon-upload"
+          plain
+          size="mini"
+          type="primary"
+          >{{ btnText }}
         </el-button>
       </div>
       <slot></slot>
@@ -86,26 +96,29 @@ export default {
     },
     files: {
       type: Array,
-      default () {
+      default() {
         return null
       }
     }
   },
-  data () {
+  data() {
     return {
       tmpFileList: [],
       fileList: [],
       headers: {
-        Authorization: `Basic ${Base64.encode(`${website.clientId}:${website.clientSecret}`)}`,
+        Authorization: `Basic ${Base64.encode(
+          `${website.clientId}:${website.clientSecret}`
+        )}`,
         'Blade-Auth': 'bearer ' + getToken()
       }
     }
   },
-  mounted () {
+  mounted() {
     this.setFiles(this.files, 'originalFileName')
   },
   methods: {
-    setFiles (fileList, name) { // 文件回填 (参数:文件列表,文件名的字段name)
+    setFiles(fileList, name) {
+      // 文件回填 (参数:文件列表,文件名的字段name)
       if (!fileList || fileList.length === 0) return
       const files = []
       fileList.forEach((item, index) => {
@@ -121,7 +134,7 @@ export default {
       })
       this.fileList = files
     },
-    progress (event, file, fileList) {
+    progress(event, file, fileList) {
       // this.$message.info('上传中')
       console.log(file.percentage)
       if (file.percentage === 100) {
@@ -135,24 +148,27 @@ export default {
 
       this.$emit('progress')
     },
-    handleChange (file, fileList) {
+    handleChange(file, fileList) {
       this.tmpFileList = fileList
       this.$emit('before', this.tmpFileList)
     },
-    maxChange () {
-      if (this.max === 1) { // 只有一张图的时候超出进行覆盖
+    maxChange() {
+      if (this.max === 1) {
+        // 只有一张图的时候超出进行覆盖
         this.fileList = []
       } else {
         this.$message.warning(`最多只能上传${this.max}个文件`)
       }
     },
-    beforeUpload (file) {
+    beforeUpload(file) {
       this.loading = true
       console.log(file)
       this.$emit('before', file)
     },
-    success () {
-      const finishList = this.tmpFileList.filter(sub => sub.status === 'success')
+    success() {
+      const finishList = this.tmpFileList.filter(
+        sub => sub.status === 'success'
+      )
       if (finishList.length === this.tmpFileList.length) {
         this.$emit('success', {
           fileList: this.tmpFileList
@@ -164,7 +180,7 @@ export default {
         }, 2000)
       }
     },
-    remove (file, fileList) {
+    remove(file, fileList) {
       const ids = fileList.map(e => e.response.data[0].id)
       this.$emit('remove', {
         file,
@@ -172,10 +188,10 @@ export default {
         ids
       })
     },
-    submit () {
+    submit() {
       this.$refs.upload.submit()
     },
-    onError (res, file, fileList) {
+    onError(res, file, fileList) {
       const error = JSON.parse(res.message)
       this.$confirm(error.msg, {
         confirmButtonText: '确定',
@@ -187,7 +203,7 @@ export default {
   }
 }
 </script>
-<style lang='scss' scoped>
+<style lang="scss" scoped>
 .custom-upload {
   :deep(.el-upload-list__item-name) {
     white-space: pre-wrap;

+ 95 - 51
src/views/home/component/current.vue

@@ -1,69 +1,112 @@
 <template>
   <div class="flex flex-col padding">
     <div class="flex flex-center mt-20">
-      <div class="bold font-16 grey flex-child-average text-left" style="margin-left: 50px">
+      <div
+        class="bold font-16 grey flex-child-average text-left"
+        style="margin-left: 50px"
+      >
         <div>
-          <el-button type='primary' class='mr-20' icon='el-icon-back' @click='this.$router.go(-1) '>返回上一层
+          <el-button
+            type="primary"
+            class="mr-20"
+            icon="el-icon-back"
+            @click="this.$router.go(-1)"
+            >返回上一层
           </el-button>
           <span>{{ folderName }}({{ folderNumber }})</span>
         </div>
       </div>
-      <div class="flex flex-center flex-child-average flex-justify-end" style="margin-right: 50px">
-        <base-button v-if='permissions && permissions.permissions.home_folder_authorize' class="mr-5" icon="User"
-                     title="批量授权"
-                     type="0" @click='showClick'/>
-        <base-button v-if="permissions && permissions.permissions.floder_detail_add && isAccess === '2'" icon="Plus"
-                     title="添加文件夹"
-                     class="mr-5"
-                     type="0" @click="addShow = true"/>
-        <base-button v-if="isAccess === '2'" icon="Upload" title="上传文件" @click="show = true"/>
+      <div
+        class="flex flex-center flex-child-average flex-justify-end"
+        style="margin-right: 50px"
+      >
+        <base-button
+          v-if="permissions && permissions.permissions.home_folder_authorize"
+          class="mr-5"
+          icon="User"
+          title="批量授权"
+          type="0"
+          @click="showClick"
+        />
+        <base-button
+          v-if="
+            permissions &&
+            permissions.permissions.floder_detail_add &&
+            isAccess === '2'
+          "
+          icon="Plus"
+          title="添加文件夹"
+          class="mr-5"
+          type="0"
+          @click="addShow = true"
+        />
+        <base-button
+          v-if="isAccess === '2'"
+          icon="Upload"
+          title="上传文件"
+          @click="show = true"
+        />
       </div>
     </div>
-    <files-list :data="data" class="mt-20" @change='changePage'/>
-    <el-dialog v-model="show"
-               append-to-body
-               center
-               title="附件上传(可批量)">
+    <files-list :data="data" class="mt-20" @change="changePage" />
+    <el-dialog v-model="show" append-to-body center title="附件上传(可批量)">
       <div class="flex flex-col" style="margin-top: -20px">
         <span class="font-16 main-color bold mb-10">{{ folderName }}</span>
-        <uploadFile :data='{type:1,toStatus:0}' :max='20'
-                    @close='show = false'
-                    accept='.doc,.docx,.pdf,.xls,.xlsx,.png,.jpg,.jpeg,.ppt,pptx'
-                    @success='success'/>
+        <uploadFile
+          :data="{ type: 1, toStatus: 0 }"
+          :max="20"
+          @close="show = false"
+          accept=".doc,.docx,.pdf,.xls,.xlsx,.png,.jpg,.jpeg,.ppt,pptx"
+          @success="success"
+        />
       </div>
-
     </el-dialog>
 
-    <el-dialog v-model='authorizeShow' :show-close='false' append-to-body center>
+    <el-dialog
+      v-model="authorizeShow"
+      :show-close="false"
+      append-to-body
+      center
+    >
       <template #header="{ close, titleId, titleClass }">
         <div class="flex flex-justify-between">
           <h4 :id="titleId" :class="titleClass">{{ data.folderName }}</h4>
           <el-button text type="danger" @click="close">
             <el-icon class="el-icon--left">
-              <CircleCloseFilled/>
+              <CircleCloseFilled />
             </el-icon>
           </el-button>
         </div>
       </template>
-      <authorize :list='data.records' :folder-id='id' :extra='{type:1}' :project-id='projectId' :folder-name='folderName' :author-type='false' @close='authorizeShow = false'/>
+      <authorize
+        :list="data.records"
+        :folder-id="id"
+        :extra="{ type: 1 }"
+        :project-id="projectId"
+        :folder-name="folderName"
+        :author-type="false"
+        @close="authorizeShow = false"
+      />
     </el-dialog>
-    <el-dialog v-model='addShow' append-to-body width='40%'>
+    <el-dialog v-model="addShow" append-to-body width="40%">
       <div class="flex flex-col">
-        <el-form ref="ruleFormRef"
-                 :model="folderInfo"
-                 class="demo-ruleForm"
-                 label-width="120px"
-                 status-icon>
+        <el-form
+          ref="ruleFormRef"
+          :model="folderInfo"
+          class="demo-ruleForm"
+          label-width="120px"
+          status-icon
+        >
           <el-form-item label="文件夹名称">
             <el-input
-                v-model="folderInfo.title"
-                placeholder="填写文件夹名称"
-                style="width: 100%"
+              v-model="folderInfo.title"
+              placeholder="填写文件夹名称"
+              style="width: 100%"
             />
           </el-form-item>
         </el-form>
         <div class="full-width flex flex-center mt-10">
-          <base-button icon="Lock" title="保存" type="1" @click="folderAdd"/>
+          <base-button icon="Lock" title="保存" type="1" @click="folderAdd" />
         </div>
       </div>
     </el-dialog>
@@ -85,7 +128,7 @@ export default {
     id: String,
     data: Object
   },
-  data () {
+  data() {
     return {
       authorizeShow: false,
       addShow: false,
@@ -113,12 +156,12 @@ export default {
       folderNumber: 0
     }
   },
-  setup () {
+  setup() {
     const permissions = permissionStore()
     const user = useStore()
     return { permissions, user }
   },
-  created () {
+  created() {
     this.folderName = this.$route.query.folderName
     this.folderNumber = this.$route.query.folderNumber
     this.isAccess = this.$route.query.isAccess
@@ -127,10 +170,10 @@ export default {
     this.folderInfo.stageId = this.$route.query.projectStageId
   },
   methods: {
-    showClick () {
+    showClick() {
       this.authorizeShow = true
     },
-    success (res) {
+    success(res) {
       this.fileList = res.fileList.map(res => {
         const item = {}
         item.title = res.response.data.originalFileName
@@ -147,7 +190,11 @@ export default {
       })
       this.fileList.forEach(sub => {
         this.saveCount++
-        if (['pdf', 'doc', 'docx', 'ppt', 'pptx', 'xls', 'xlsx'].includes(sub.suffix)) {
+        if (
+          ['pdf', 'doc', 'docx', 'ppt', 'pptx', 'xls', 'xlsx'].includes(
+            sub.suffix
+          )
+        ) {
           this.saveLibrary(sub)
         }
         if (this.saveCount === this.fileList.length) {
@@ -156,7 +203,7 @@ export default {
         }
       })
     },
-    saveLibrary (sub) {
+    saveLibrary(sub) {
       const data = { category: 4, content: '' }
       this.$api.common.submit(Object.assign(sub, data)).then(res => {
         if (res.code === 200) {
@@ -167,7 +214,7 @@ export default {
         }
       })
     },
-    addFile () {
+    addFile() {
       this.$api.project.fileAdd(this.fileList).then(res => {
         if (res.code === 200) {
           this.show = false
@@ -178,10 +225,9 @@ export default {
               confirmButtonText: '确定',
               cancelButtonText: '取消',
               type: 'warning'
+            }).then(() => {
+              this.SendMsg()
             })
-              .then(() => {
-                this.SendMsg()
-              })
           }
         } else {
           this.show = false
@@ -189,7 +235,7 @@ export default {
         }
       })
     },
-    SendMsg () {
+    SendMsg() {
       this.sendParams.ids = this.fileList.map(e => e.fileId).join(',')
       this.sendParams.projectId = this.$route.query.projectId
       this.sendParams.ownerId = this.$route.query.ownerId
@@ -204,7 +250,7 @@ export default {
         }
       })
     },
-    folderAdd () {
+    folderAdd() {
       this.folderInfo.projectId = this.projectId
       this.folderInfo.parentId = this.id
       this.$api.project.folderAdd(this.folderInfo).then(res => {
@@ -217,13 +263,11 @@ export default {
         }
       })
     },
-    changePage (page) {
+    changePage(page) {
       this.$emit('change', page)
     }
   }
 }
 </script>
 
-<style scoped>
-
-</style>
+<style scoped></style>

+ 197 - 143
src/views/home/component/params/params1.vue

@@ -1,207 +1,256 @@
 <template>
-  <div class='flex flex-justify-start flex-align-center flex-col'>
-    <div class='flex flex-center full-width flex-justify-between mt-10 mb-10'>
-      <span class='full-width text-left bold'>{{ info.dictValue }}</span>
-      <el-button v-if='detail.can_update' type='primary' @click='disabled = !disabled'>{{
-          disabled ? '编 辑' : '保 存'
-        }}
+  <div class="flex flex-justify-start flex-align-center flex-col">
+    <div class="flex flex-center full-width flex-justify-between mt-10 mb-10">
+      <span class="full-width text-left bold">{{ info.dictValue }}</span>
+      <el-button
+        v-if="detail.can_update"
+        type="primary"
+        @click="disabled = !disabled"
+        >{{ disabled ? '编 辑' : '保 存' }}
       </el-button>
     </div>
-    <div class='mt-10' style='width: 90%;'>
+    <div class="mt-10" style="width: 90%">
       <el-form
-          v-if='form'
-          :model="form"
-          label-width='240px'
-          :disabled='disabled'
-          label-position="left"
-          class='form-content flex flex-col'
+        v-if="form"
+        :model="form"
+        label-width="240px"
+        :disabled="disabled"
+        label-position="left"
+        class="form-content flex flex-col"
       >
-        <div class='flex flex-justify-start '>
-          <el-form-item label="项目名称" style='flex:1'>
-            <el-input v-model="form.name" placeholder='项目名称'/>
+        <div class="flex flex-justify-start">
+          <el-form-item label="项目名称" style="flex: 1">
+            <el-input v-model="form.name" placeholder="项目名称" />
           </el-form-item>
-          <el-form-item label="总投资金额(万元)" style='flex:1' class='ml-20 full-width'>
-            <div class='full-width'>
-              <el-input v-model="form.total_amount" placeholder='总投资金额(万元)' class='full-width'/>
+          <el-form-item
+            label="总投资金额(万元)"
+            style="flex: 1"
+            class="ml-20 full-width"
+          >
+            <div class="full-width">
+              <el-input
+                v-model="form.total_amount"
+                placeholder="总投资金额(万元)"
+                class="full-width"
+              />
             </div>
           </el-form-item>
         </div>
-        <div class='full-width  flex'>
-          <el-form-item label="县(区)" style='flex:1'>
-            <div class='full-width'>
-              <avue-input-tree v-model="form.county"
-                               class='full-width'
-                               placeholder="请选择县(区)"
-                               :dic="areaDic"></avue-input-tree>
+        <div class="full-width flex">
+          <el-form-item label="县(区)" style="flex: 1">
+            <div class="full-width">
+              <avue-input-tree
+                v-model="form.county"
+                class="full-width"
+                placeholder="请选择县(区)"
+                :dic="areaDic"
+              ></avue-input-tree>
             </div>
           </el-form-item>
-          <el-form-item label="责任单位" style='flex:1' class='ml-20'>
-            <el-input v-model="form.responsible_unit" placeholder='责任单位'/>
+          <el-form-item label="责任单位" style="flex: 1" class="ml-20">
+            <el-input v-model="form.responsible_unit" placeholder="责任单位" />
           </el-form-item>
         </div>
 
-        <div class='full-width  flex'>
-          <el-form-item label="主管单位" style='flex:1'>
-            <el-input v-model="form.competent_unit" placeholder='主管单位'/>
+        <div class="full-width flex">
+          <el-form-item label="主管单位" style="flex: 1">
+            <el-input v-model="form.competent_unit" placeholder="主管单位" />
           </el-form-item>
-          <el-form-item label="责任领导" style='flex:1' class='ml-20'>
-            <el-input v-model="form.responsible_leader" placeholder='责任领导'/>
+          <el-form-item label="责任领导" style="flex: 1" class="ml-20">
+            <el-input
+              v-model="form.responsible_leader"
+              placeholder="责任领导"
+            />
           </el-form-item>
         </div>
-        <div class='full-width  flex'>
-          <el-form-item label="项目负责人及联系电话" style='flex:1'>
-            <el-input v-model="form.construction_unit" placeholder='项目负责人及联系电话'/>
+        <div class="full-width flex">
+          <el-form-item label="项目负责人及联系电话" style="flex: 1">
+            <el-input
+              v-model="form.construction_unit"
+              placeholder="项目负责人及联系电话"
+            />
           </el-form-item>
         </div>
 
-        <div class='full-width  flex'>
-          <el-form-item label="行业分类" class='flex-child-average' style='flex:1'>
-            <el-input v-model="form.industry"/>
+        <div class="full-width flex">
+          <el-form-item
+            label="行业分类"
+            class="flex-child-average"
+            style="flex: 1"
+          >
+            <el-input v-model="form.industry" />
           </el-form-item>
-          <el-form-item label="建设起止时间" class='flex-child-average ml-20'>
-            <el-input v-if='disabled' v-model="form.construction_start_and_end"/>
+          <el-form-item label="建设起止时间" class="flex-child-average ml-20">
+            <el-input
+              v-if="disabled"
+              v-model="form.construction_start_and_end"
+            />
             <el-date-picker
-                v-else
-                v-model="form.construction_start_and_end_new"
-                @change='changeDate'
-                type="daterange"
-                range-separator="至"
-                start-placeholder="开始日期"
-                end-placeholder="截止日期"
-                style='width: 100%;'
-                format='YYYY-MM-DD'
-                value-format='YYYY-MM-DD'
+              v-else
+              v-model="form.construction_start_and_end_new"
+              @change="changeDate"
+              type="daterange"
+              range-separator="至"
+              start-placeholder="开始日期"
+              end-placeholder="截止日期"
+              style="width: 100%"
+              format="YYYY-MM-DD"
+              value-format="YYYY-MM-DD"
             />
           </el-form-item>
         </div>
 
-        <div class='full-width  flex'>
-          <el-form-item label="计划开工时间" style='flex:1' class='full-width'>
+        <div class="full-width flex">
+          <el-form-item label="计划开工时间" style="flex: 1" class="full-width">
             <el-date-picker
-                v-model="form.plan_commencement_time"
-                type="date"
-                style="width:100%;"
-                placeholder="计划开工时间"
-                format='YYYY-MM-DD'
-                value-format='YYYY-MM-DD'
+              v-model="form.plan_commencement_time"
+              type="date"
+              style="width: 100%"
+              placeholder="计划开工时间"
+              format="YYYY-MM-DD"
+              value-format="YYYY-MM-DD"
             />
           </el-form-item>
-          <el-form-item label="实际开工时间" style='flex:1' class='ml-20'>
+          <el-form-item label="实际开工时间" style="flex: 1" class="ml-20">
             <el-date-picker
-                v-model="form.start_time"
-                type="date"
-                style="width:100%;"
-                placeholder="实际开工时间"
-                format='YYYY-MM-DD'
-                value-format='YYYY-MM-DD'
+              v-model="form.start_time"
+              type="date"
+              style="width: 100%"
+              placeholder="实际开工时间"
+              format="YYYY-MM-DD"
+              value-format="YYYY-MM-DD"
             />
           </el-form-item>
         </div>
-        <div class='full-width  flex'>
-          <el-form-item label="计划入库时间" style='flex:1'>
+        <div class="full-width flex">
+          <el-form-item label="计划入库时间" style="flex: 1">
             <el-date-picker
-                v-model="form.plan_storage_time"
-                type="date"
-                style="width:100%;"
-                placeholder="计划入库时间"
-                format='YYYY-MM-DD'
-                value-format='YYYY-MM-DD'
+              v-model="form.plan_storage_time"
+              type="date"
+              style="width: 100%"
+              placeholder="计划入库时间"
+              format="YYYY-MM-DD"
+              value-format="YYYY-MM-DD"
             />
           </el-form-item>
-          <el-form-item label="实际入库时间" style='flex:1' class='ml-20'>
+          <el-form-item label="实际入库时间" style="flex: 1" class="ml-20">
             <el-date-picker
-                v-model="form.storage_time"
-                type="date"
-                style="width:100%;"
-                placeholder="实际入库时间"
-                format='YYYY-MM-DD'
-                value-format='YYYY-MM-DD'
+              v-model="form.storage_time"
+              type="date"
+              style="width: 100%"
+              placeholder="实际入库时间"
+              format="YYYY-MM-DD"
+              value-format="YYYY-MM-DD"
             />
           </el-form-item>
         </div>
-        <div class='full-width  flex'>
-          <el-form-item label="计划竣工时间" style='flex:1'>
+        <div class="full-width flex">
+          <el-form-item label="计划竣工时间" style="flex: 1">
             <el-date-picker
-                v-model="form.plan_completion_time"
-                type="date"
-                style="width:100%;"
-                placeholder="计划竣工时间"
-                format='YYYY-MM-DD'
-                value-format='YYYY-MM-DD'
+              v-model="form.plan_completion_time"
+              type="date"
+              style="width: 100%"
+              placeholder="计划竣工时间"
+              format="YYYY-MM-DD"
+              value-format="YYYY-MM-DD"
             />
           </el-form-item>
-          <el-form-item label="实际竣工时间" style='flex:1' class='ml-20'>
+          <el-form-item label="实际竣工时间" style="flex: 1" class="ml-20">
             <el-date-picker
-                v-model="form.completion_time"
-                type="date"
-                style="width:100%;"
-                placeholder="实际竣工时间"
-                format='YYYY-MM-DD'
-                value-format='YYYY-MM-DD'
+              v-model="form.completion_time"
+              type="date"
+              style="width: 100%"
+              placeholder="实际竣工时间"
+              format="YYYY-MM-DD"
+              value-format="YYYY-MM-DD"
             />
           </el-form-item>
         </div>
-        <div class='full-width  flex'>
-          <el-form-item label="是否入库" style='flex:1'>
-            <div class='full-width '>
-              <el-select v-model='form.is_storage' placeholder='是否入库' class='full-width'>
+        <div class="full-width flex">
+          <el-form-item label="是否入库" style="flex: 1">
+            <div class="full-width">
+              <el-select
+                v-model="form.is_storage"
+                placeholder="是否入库"
+                class="full-width"
+              >
                 <el-option
-                    v-for="item in yesOrNo"
-                    :key='item.label'
-                    :label="item.label"
-                    :value="item.value"
+                  v-for="item in yesOrNo"
+                  :key="item.label"
+                  :label="item.label"
+                  :value="item.value"
                 />
               </el-select>
             </div>
           </el-form-item>
-          <el-form-item label="是否开工" style='flex:1' class='ml-20'>
-            <div class='full-width'>
-              <el-select v-model='form.is_start' placeholder='是否开工' class='full-width'>
+          <el-form-item label="是否开工" style="flex: 1" class="ml-20">
+            <div class="full-width">
+              <el-select
+                v-model="form.is_start"
+                placeholder="是否开工"
+                class="full-width"
+              >
                 <el-option
-                    v-for="item in yesOrNo"
-                    :key='item.label'
-                    :label="item.label"
-                    :value="item.value"
+                  v-for="item in yesOrNo"
+                  :key="item.label"
+                  :label="item.label"
+                  :value="item.value"
                 />
               </el-select>
             </div>
           </el-form-item>
         </div>
-        <div class='full-width  flex'>
-          <el-form-item label="是否纳入省重点项目" style='flex:1'>
-            <div class='full-width'>
-              <el-select v-model='form.is_provincial_key' placeholder='是否纳入省重点项目' class='full-width'>
+        <div class="full-width flex">
+          <el-form-item label="是否纳入省重点项目" style="flex: 1">
+            <div class="full-width">
+              <el-select
+                v-model="form.is_provincial_key"
+                placeholder="是否纳入省重点项目"
+                class="full-width"
+              >
                 <el-option
-                    v-for="item in yesOrNo"
-                    :key='item.label'
-                    :label="item.label"
-                    :value="item.value"
+                  v-for="item in yesOrNo"
+                  :key="item.label"
+                  :label="item.label"
+                  :value="item.value"
                 />
               </el-select>
             </div>
           </el-form-item>
-          <el-form-item label="是否纳入省集中开工项目" style='flex:1' class='ml-20'>
-            <div class='full-width'>
-              <el-select v-model='form.is_provincial_level_construction' placeholder='是否纳入省集中开工项目'
-                         class='full-width'>
+          <el-form-item
+            label="是否纳入省集中开工项目"
+            style="flex: 1"
+            class="ml-20"
+          >
+            <div class="full-width">
+              <el-select
+                v-model="form.is_provincial_level_construction"
+                placeholder="是否纳入省集中开工项目"
+                class="full-width"
+              >
                 <el-option
-                    v-for="item in yesOrNo"
-                    :key='item.label'
-                    :label="item.label"
-                    :value="item.value"
+                  v-for="item in yesOrNo"
+                  :key="item.label"
+                  :label="item.label"
+                  :value="item.value"
                 />
               </el-select>
             </div>
           </el-form-item>
         </div>
-        <div class='full-width  '>
+        <div class="full-width">
           <el-form-item label="项目建设详细地址">
-            <el-input v-model="form.address" placeholder='项目建设详细地址'/>
+            <el-input v-model="form.address" placeholder="项目建设详细地址" />
           </el-form-item>
         </div>
-        <div class='full-width '>
+        <div class="full-width">
           <el-form-item label="主要建设内容及规模">
-            <el-input v-model="form.construction_content" type='textarea' placeholder='主要建设内容及规模' :rows='4'/>
+            <el-input
+              v-model="form.construction_content"
+              type="textarea"
+              placeholder="主要建设内容及规模"
+              :rows="4"
+            />
           </el-form-item>
         </div>
       </el-form>
@@ -224,14 +273,20 @@ export default {
   },
   watch: {
     detail: {
-      handler (val) {
+      handler(val) {
         this.form = val
         this.form.construction_start_and_end_new = ''
+        if (this.form.name) {
+          const xian = this.form.name.indexOf('县')
+          this.form.name = this.dev
+            ? this.form.name.substring(xian + 1)
+            : this.form.name
+        }
       },
       immediate: true
     },
     disabled: {
-      handler (val) {
+      handler(val) {
         if (val) {
           this.updata()
         }
@@ -239,7 +294,7 @@ export default {
       immediate: false
     }
   },
-  data () {
+  data() {
     return {
       disabled: true,
       form: {},
@@ -251,22 +306,21 @@ export default {
       dev: false
     }
   },
-  created () {
+  mounted() {
     this.dev = sessionStorage.getItem('dev') === 'true'
-    const xian = this.form.name.indexOf('县')
-    this.form.name = this.dev ? this.form.name.substring(xian + 1) : this.form.name
     this.areaList()
   },
   methods: {
-    areaList () {
+    areaList() {
       this.$api.common.region({ code: '' }).then(res => {
         if (res.code === 200) {
           this.areaDic = res.data.map(item => this.mapTree(item))
         }
       })
     },
-    mapTree (item) {
-      const haveChildren = Array.isArray(item.children) && item.children.length > 0
+    mapTree(item) {
+      const haveChildren =
+        Array.isArray(item.children) && item.children.length > 0
       return {
         key: item.id,
         value: item.id,
@@ -274,7 +328,7 @@ export default {
         children: haveChildren ? item.children.map(i => this.mapTree(i)) : []
       }
     },
-    updata () {
+    updata() {
       this.form.projectId = this.detail.id
       this.form.total_amount = Number.parseFloat(this.detail.total_amount)
       delete this.detail._id
@@ -286,14 +340,14 @@ export default {
         }
       })
     },
-    changeDate (res) {
+    changeDate(res) {
       this.form.construction_start_and_end = res.join(',')
     }
   }
 }
 </script>
 
-<style lang='scss' scoped>
+<style lang="scss" scoped>
 .form-content {
   border: 1px solid #eeeeee;
   padding: 20px;

+ 337 - 143
src/views/home/component/params/params3.vue

@@ -1,42 +1,77 @@
 <template>
-  <div class='flex flex-justify-start flex-align-center flex-col'>
-    <div class='flex flex-center full-width flex-justify-between mt-10 mb-10'>
-      <span class='full-width text-left bold'>{{ info.dictValue }}</span>
-      <el-button v-if='detail.can_update' type='primary' @click='disabled = !disabled'>
+  <div class="flex flex-justify-start flex-align-center flex-col">
+    <div class="flex flex-center full-width flex-justify-between mt-10 mb-10">
+      <span class="full-width text-left bold">{{ info.dictValue }}</span>
+      <el-button
+        v-if="detail.can_update"
+        type="primary"
+        @click="disabled = !disabled"
+      >
         {{ disabled ? '编 辑' : '保 存' }}
       </el-button>
     </div>
-    <div class="mt-10 mb-10 full-width" style="width: 93%;">
-      <base-button v-if='detail.can_update' title="新增年度" icon="Plus" @click='addYear(1)'/>
+    <div class="mt-10 mb-10 full-width" style="width: 93%">
+      <base-button
+        v-if="detail.can_update"
+        title="新增年度"
+        icon="Plus"
+        @click="addYear(1)"
+      />
     </div>
-    <div class='mt-10' style='width: 90%;'>
+    <div class="mt-10" style="width: 90%">
       <el-form
-          :model="form"
-          label-width='180px'
-          :disabled='disabled'
-          label-position="left"
-          class='form-content flex flex-col'
+        :model="form"
+        label-width="180px"
+        :disabled="disabled"
+        label-position="left"
+        class="form-content flex flex-col"
       >
-        <el-form-item v-for='(item,index) in completeCount' :key='item' label-width='0'>
-          <div class='flex flex-col flex-center full-width'>
-            <div class='flex flex-center  flex-justify-between  full-width'>
-              <div class='flex-child-average full-width  flex flex-center'>
-                <span style='width: 320px'>{{
-                    form.month_plan_complete_amount[index] ? form.month_plan_complete_amount[index].year : ''
-                  }}年度计划投资(万元)</span>
-                <div class='disable-input' @change='change(item)'>
-                  {{ form.month_plan_complete_amount[index] ? form.month_plan_complete_amount[index].sum : '' }}
+        <el-form-item
+          v-for="(item, index) in completeCount"
+          :key="item"
+          label-width="0"
+        >
+          <div class="flex flex-col flex-center full-width">
+            <div class="flex flex-center flex-justify-between full-width">
+              <div class="flex-child-average full-width flex flex-center">
+                <span style="width: 320px"
+                  >{{
+                    form.month_plan_complete_amount[index]
+                      ? form.month_plan_complete_amount[index].year
+                      : ''
+                  }}年度计划投资(万元)</span
+                >
+                <div class="disable-input" @change="change(item)">
+                  {{
+                    form.month_plan_complete_amount[index]
+                      ? form.month_plan_complete_amount[index].sum
+                      : ''
+                  }}
                 </div>
               </div>
-              <div style='width: 20px'></div>
-              <div class='flex-child-average full-width  flex flex-center'>
-                <span style='width: 380px'>{{
-                    form.month_plan_complete_amount[index] ? form.month_plan_complete_amount[index].year : ''
-                  }}年度累计投资(万元)</span>
-                <div class='disable-input' @change='change(item)'>
-                  {{ form.month_complete_amount[index] ? form.month_complete_amount[index].sum : '' }}
+              <div style="width: 20px"></div>
+              <div class="flex-child-average full-width flex flex-center">
+                <span style="width: 380px"
+                  >{{
+                    form.month_plan_complete_amount[index]
+                      ? form.month_plan_complete_amount[index].year
+                      : ''
+                  }}年度累计投资(万元)</span
+                >
+                <div class="disable-input" @change="change(item)">
+                  {{
+                    form.month_complete_amount[index]
+                      ? form.month_complete_amount[index].sum
+                      : ''
+                  }}
                 </div>
-                <div class='btnSub pointer' @click='showMonth(form.month_complete_amount[index].year ,1,index)'>月填报
+                <div
+                  class="btnSub pointer"
+                  @click="
+                    showMonth(form.month_complete_amount[index].year, 1, index)
+                  "
+                >
+                  月填报
                 </div>
               </div>
             </div>
@@ -44,31 +79,60 @@
         </el-form-item>
       </el-form>
     </div>
-    <div class="mt-20 mb-10 full-width" style="width: 93%;">
-      <base-button v-if='detail.can_update' title="新增年度" icon="Plus" @click='addYear(2)'/>
+    <div class="mt-20 mb-10 full-width" style="width: 93%">
+      <base-button
+        v-if="detail.can_update"
+        title="新增年度"
+        icon="Plus"
+        @click="addYear(2)"
+      />
     </div>
-    <div class='mt-10' style='width: 90%;'>
+    <div class="mt-10" style="width: 90%">
       <el-form
-          :model="form"
-          label-width='180px'
-          :disabled='disabled'
-          label-position="left"
-          class='form-content flex flex-col'
+        :model="form"
+        label-width="180px"
+        :disabled="disabled"
+        label-position="left"
+        class="form-content flex flex-col"
       >
-        <el-form-item v-for='(item,index) in investmentCount' :key='item' label-width='0'>
-          <div class='flex flex-col flex-center full-width'>
-            <div class='flex flex-center  flex-justify-between  full-width'>
-              <div class='flex-child-average full-width  flex flex-center'>
-                <span style='width: 400px'>{{ form.month_plan_investment[index].year }}年度计划纳统投资(万元)</span>
-                <div class='disable-input' @change='change(item)'>
-                  {{ form.month_plan_investment[index] ? form.month_plan_investment[index].sum : '' }}
+        <el-form-item
+          v-for="(item, index) in investmentCount"
+          :key="item"
+          label-width="0"
+        >
+          <div class="flex flex-col flex-center full-width">
+            <div class="flex flex-center flex-justify-between full-width">
+              <div class="flex-child-average full-width flex flex-center">
+                <span style="width: 400px"
+                  >{{
+                    form.month_plan_investment[index].year
+                  }}年度计划纳统投资(万元)</span
+                >
+                <div class="disable-input" @change="change(item)">
+                  {{
+                    form.month_plan_investment[index]
+                      ? form.month_plan_investment[index].sum
+                      : ''
+                  }}
                 </div>
               </div>
-              <div style='width: 20px'></div>
-              <div class='flex-child-average full-width  flex flex-center'>
-                <span style='width: 440px'>{{ form.month_plan_investment[index].year }}年度累计纳统投资(万元)</span>
-                <div class='disable-input' @change='change(item)'>{{ form.month_investment_amount[index].sum }}</div>
-                <div class='btnSub pointer' @click='showMonth(form.month_plan_investment[index].year,2,index)'>月填报
+              <div style="width: 20px"></div>
+              <div class="flex-child-average full-width flex flex-center">
+                <span style="width: 440px"
+                  >{{
+                    form.month_plan_investment[index].year
+                  }}年度累计纳统投资(万元)</span
+                >
+                <div class="disable-input" @change="change(item)">
+                  {{ form.month_investment_amount[index].sum }}
+                </div>
+                <div
+                  class="btnSub pointer"
+                  @click="
+                    showMonth(form.month_plan_investment[index].year, 2, index)
+                  "
+                >
+                  月填报
                 </div>
               </div>
             </div>
@@ -77,44 +141,62 @@
       </el-form>
     </div>
 
-    <el-dialog v-if='current' v-model='show'
-               :title='  current.editType === 1 ?  current.year + "年度投资情况" : current.year + "年度纳统情况"'
-               width='1260px'>
-      <div class='flex flex-center flex-align-start'>
+    <el-dialog
+      v-if="current"
+      v-model="show"
+      :title="
+        current.editType === 1
+          ? current.year + '年度投资情况'
+          : current.year + '年度纳统情况'
+      "
+      width="1260px"
+    >
+      <div class="flex flex-center flex-align-start">
         <div>
-          <div class='padding-top'></div>
-          <div class='padding-top mt-20 mr-10 bold'>{{ current.editType === 1 ? '月计划投资:' : '月计划纳统投资:' }}
+          <div class="padding-top"></div>
+          <div class="padding-top mt-20 mr-10 bold">
+            {{ current.editType === 1 ? '月计划投资:' : '月计划纳统投资:' }}
           </div>
-          <div class='padding-top mt-10 mr-10 bold'>{{ current.editType === 1 ? '月完成投资:' : '月完成纳统投资:' }}
+          <div class="padding-top mt-10 mr-10 bold">
+            {{ current.editType === 1 ? '月完成投资:' : '月完成纳统投资:' }}
           </div>
         </div>
         <div>
-          <div class='mr-5  flex flex-center '>
-            <div v-for='(item,index) in 11' :key='item' class='title'>
-              <div v-if='index === 0'>
-                1-2月
-              </div>
-              <div v-else>
-                {{ item + 1 }}月
-              </div>
+          <div class="mr-5 flex flex-center">
+            <div v-for="(item, index) in 11" :key="item" class="title">
+              <div v-if="index === 0">1-2月</div>
+              <div v-else>{{ item + 1 }}月</div>
             </div>
           </div>
-          <div class='mr-5  flex flex-center'>
-            <div v-for='(item,index) in current.planMonths' :key='item.name'>
-              <input class='input' v-model="item.data" @change='changeMonth(item,1,index)'/>
+          <div class="mr-5 flex flex-center">
+            <div v-for="(item, index) in current.planMonths" :key="item.name">
+              <input
+                class="input"
+                v-model="item.data"
+                @change="changeMonth(item, 1, index)"
+              />
             </div>
           </div>
 
-          <div class='mr-5  flex flex-center'>
-            <div v-for='(item,index) in current.months' :key='item.name'>
-              <input class='input' v-model="item.data" @change='changeMonth(item,2,index)'>
+          <div class="mr-5 flex flex-center">
+            <div v-for="(item, index) in current.months" :key="item.name">
+              <input
+                class="input"
+                v-model="item.data"
+                @change="changeMonth(item, 2, index)"
+              />
             </div>
           </div>
         </div>
       </div>
-      <div class='mt-20 full-width flex flex-justify-between'>
+      <div class="mt-20 full-width flex flex-justify-between">
         <span class="red">* 请按月份进行填报,单位:万元</span>
-        <base-button class="mr-20" title="保存" icon='el-icon-check' @click="update"/>
+        <base-button
+          class="mr-20"
+          title="保存"
+          icon="el-icon-check"
+          @click="update"
+        />
       </div>
     </el-dialog>
   </div>
@@ -139,7 +221,7 @@ export default {
   },
   watch: {
     detail: {
-      handler (val) {
+      handler(val) {
         if (Object.keys(val).length > 1) {
           this.init(val)
         }
@@ -147,7 +229,7 @@ export default {
       immediate: true
     },
     disabled: {
-      handler (val) {
+      handler(val) {
         if (val) {
           this.update(val !== true)
         }
@@ -155,7 +237,7 @@ export default {
       immediate: false
     }
   },
-  data () {
+  data() {
     return {
       show: false,
       disabled: true,
@@ -172,7 +254,7 @@ export default {
      *
      * @param type 1计划投资  2 纳统投资
      */
-    addYear (type) {
+    addYear(type) {
       this.disabled = false
       if (type === 1) {
         if (this.form.month_complete_amount.length === 0) {
@@ -180,8 +262,20 @@ export default {
           this.form.month_complete_amount.push(this.nextYear(nowYear))
           this.form.month_plan_complete_amount.push(this.nextYear(nowYear))
         } else {
-          this.form.month_complete_amount.splice(0, 0, this.nextYear(Number.parseInt(this.form.month_complete_amount[0].year)))
-          this.form.month_plan_complete_amount.splice(0, 0, this.nextYear(Number.parseInt(this.form.month_plan_complete_amount[0].year)))
+          this.form.month_complete_amount.splice(
+            0,
+            0,
+            this.nextYear(
+              Number.parseInt(this.form.month_complete_amount[0].year)
+            )
+          )
+          this.form.month_plan_complete_amount.splice(
+            0,
+            0,
+            this.nextYear(
+              Number.parseInt(this.form.month_plan_complete_amount[0].year)
+            )
+          )
         }
         this.completeCount = this.completeCount + 1
       } else if (type === 2) {
@@ -190,14 +284,26 @@ export default {
           this.form.month_investment_amount.push(this.nextYear(nowYear))
           this.form.month_plan_investment.push(this.nextYear(nowYear))
         } else {
-          this.form.month_investment_amount.splice(0, 0, this.nextYear(Number.parseInt(this.form.month_investment_amount[0].year)))
-          this.form.month_plan_investment.splice(0, 0, this.nextYear(Number.parseInt(this.form.month_plan_investment[0].year)))
+          this.form.month_investment_amount.splice(
+            0,
+            0,
+            this.nextYear(
+              Number.parseInt(this.form.month_investment_amount[0].year)
+            )
+          )
+          this.form.month_plan_investment.splice(
+            0,
+            0,
+            this.nextYear(
+              Number.parseInt(this.form.month_plan_investment[0].year)
+            )
+          )
         }
         this.investmentCount = this.investmentCount + 1
       }
       console.log(this.form)
     },
-    nextYear (year) {
+    nextYear(year) {
       const tmp2 = {}
       tmp2.year = (year + 1).toString()
       tmp2.sum = ''
@@ -208,7 +314,7 @@ export default {
       }
       return tmp2
     },
-    init (res) {
+    init(res) {
       if (!Object.keys(res).includes('month_plan_investment')) {
         res.month_plan_investment = []
       }
@@ -221,17 +327,27 @@ export default {
       if (!Object.keys(res).includes('month_plan_complete_amount')) {
         res.month_plan_complete_amount = []
       }
-      this.investmentCount = Math.max(res.month_plan_investment.length, res.month_investment_amount.length)
+      this.investmentCount = Math.max(
+        res.month_plan_investment.length,
+        res.month_investment_amount.length
+      )
       // 求出差集
-      const dd = res.month_plan_investment.filter((sub) => {
-        return res.month_investment_amount.findIndex(ele => sub.year !== ele.year) !== -1
-      }).map(sub => { // data -》 ''
-        sub.monthlyData.map(ele => {
-          ele.data = ele.data ? ele.data : ''
-          return ele
+      const dd = res.month_plan_investment
+        .filter(sub => {
+          return (
+            res.month_investment_amount.findIndex(
+              ele => sub.year !== ele.year
+            ) !== -1
+          )
+        })
+        .map(sub => {
+          // data -》 ''
+          sub.monthlyData.map(ele => {
+            ele.data = ele.data ? ele.data : ''
+            return ele
+          })
+          return sub
         })
-        return sub
-      })
       // 复制差集
       if (res.month_plan_investment.length === this.completeCount) {
         dd.forEach(sub => {
@@ -243,58 +359,116 @@ export default {
         })
       }
 
-      this.completeCount = Math.max(res.month_complete_amount.length, res.month_plan_complete_amount.length)
+      this.completeCount = Math.max(
+        res.month_complete_amount.length,
+        res.month_plan_complete_amount.length
+      )
       // 求出差集
-      const d = res.month_complete_amount.filter((sub) => {
-        return res.month_plan_complete_amount.findIndex(ele => sub.year !== ele.year) !== -1
-      }).map(sub => { // data -》 ''
-        sub.monthlyData.map(ele => {
-          ele.data = ele.data ? ele.data : ''
-          return ele
+      const d = res.month_complete_amount
+        .filter(sub => {
+          return (
+            res.month_plan_complete_amount.findIndex(
+              ele => sub.year !== ele.year
+            ) !== -1
+          )
+        })
+        .map(sub => {
+          // data -》 ''
+          sub.monthlyData.map(ele => {
+            ele.data = ele.data ? ele.data : ''
+            return ele
+          })
+          return sub
         })
-        return sub
-      })
       // 复制差集
       console.log(d)
       if (res.month_complete_amount.length === this.completeCount) {
         d.forEach(sub => {
-          if (res.month_plan_complete_amount.findIndex(ele => ele.year === sub.year) === -1) {
+          if (
+            res.month_plan_complete_amount.findIndex(
+              ele => ele.year === sub.year
+            ) === -1
+          ) {
             res.month_plan_complete_amount.push(sub)
           }
         })
       } else {
         d.forEach(sub => {
-          if (res.month_complete_amount.findIndex(ele => ele.year === sub.year) === -1) {
+          if (
+            res.month_complete_amount.findIndex(
+              ele => ele.year === sub.year
+            ) === -1
+          ) {
             res.month_complete_amount.push(sub)
           }
         })
       }
       this.form = res
     },
-    change (item) {
+    change(item) {
       this.form[item.code] = item.value
       this.form[item.code2] = item.value2
     },
-    update (show = Boolean) {
+    update(show = Boolean) {
       this.$nextTick(() => {
         this.form.projectId = this.form.id
-        if (this.form.month_plan_complete_amount[this.current.index] !== undefined && this.form.month_plan_complete_amount.length > 0) {
-          this.form.month_plan_complete_amount[this.current.index].sum = this.getSum(this.form.month_plan_complete_amount[this.current.index].monthlyData)
+        if (
+          this.form.month_plan_complete_amount[this.current.index] !==
+            undefined &&
+          this.form.month_plan_complete_amount.length > 0
+        ) {
+          this.form.month_plan_complete_amount[this.current.index].sum =
+            this.getSum(
+              this.form.month_plan_complete_amount[this.current.index]
+                .monthlyData
+            )
         }
-        if (this.form.month_complete_amount[this.current.index] !== undefined && this.form.month_complete_amount.length > 0) {
-          this.form.month_complete_amount[this.current.index].sum = this.getSum(this.form.month_complete_amount[this.current.index].monthlyData)
+        if (
+          this.form.month_complete_amount[this.current.index] !== undefined &&
+          this.form.month_complete_amount.length > 0
+        ) {
+          this.form.month_complete_amount[this.current.index].sum = this.getSum(
+            this.form.month_complete_amount[this.current.index].monthlyData
+          )
         }
-        if (this.form.month_plan_investment[this.current.index] !== undefined && this.form.month_plan_investment.length > 0) {
-          this.form.month_plan_investment[this.current.index].sum = this.getSum(this.form.month_plan_investment[this.current.index].monthlyData)
+        if (
+          this.form.month_plan_investment[this.current.index] !== undefined &&
+          this.form.month_plan_investment.length > 0
+        ) {
+          this.form.month_plan_investment[this.current.index].sum = this.getSum(
+            this.form.month_plan_investment[this.current.index].monthlyData
+          )
         }
-        if (this.form.month_investment_amount[this.current.index] !== undefined && this.form.month_investment_amount.length > 0) {
-          this.form.month_investment_amount[this.current.index].sum = this.getSum(this.form.month_investment_amount[this.current.index].monthlyData)
+        if (
+          this.form.month_investment_amount[this.current.index] !== undefined &&
+          this.form.month_investment_amount.length > 0
+        ) {
+          this.form.month_investment_amount[this.current.index].sum =
+            this.getSum(
+              this.form.month_investment_amount[this.current.index].monthlyData
+            )
         }
         // 生成年月字段
-        this.initYearMonth(this.form.month_plan_complete_amount, '_month_plan_complete_amount', '_yearly_plan_complete_amount')
-        this.initYearMonth(this.form.month_complete_amount, '_month_complete_amount', '_yearly_complete_amount')
-        this.initYearMonth(this.form.month_plan_investment, '_month_plan_investment', '_yearly_plan_investment')
-        this.initYearMonth(this.form.month_investment_amount, '_month_investment_amount', '_yearly_complete_investment')
+        this.initYearMonth(
+          this.form.month_plan_complete_amount,
+          '_month_plan_complete_amount',
+          '_yearly_plan_complete_amount'
+        )
+        this.initYearMonth(
+          this.form.month_complete_amount,
+          '_month_complete_amount',
+          '_yearly_complete_amount'
+        )
+        this.initYearMonth(
+          this.form.month_plan_investment,
+          '_month_plan_investment',
+          '_yearly_plan_investment'
+        )
+        this.initYearMonth(
+          this.form.month_investment_amount,
+          '_month_investment_amount',
+          '_yearly_complete_investment'
+        )
         delete this.form._id
         this.$api.project.proUpdate(this.detail).then(res => {
           if (res.code === 200) {
@@ -315,7 +489,7 @@ export default {
      * @param key 月度关键词
      * @param key1 年度关键词
      */
-    initYearMonth (list, key, key1) {
+    initYearMonth(list, key, key1) {
       if (list.length > 0) {
         list.forEach(sub => {
           let tmp = this.kv(sub.year + key1, sub.sum)
@@ -327,7 +501,7 @@ export default {
         })
       }
     },
-    kv (key, value) {
+    kv(key, value) {
       const keyValue = {}
       keyValue[key] = value
       return keyValue
@@ -339,32 +513,44 @@ export default {
      * @param type 1 年度投资  2 纳统投资
      * @param index 索引
      */
-    showMonth (year, type, index) {
+    showMonth(year, type, index) {
       this.$nextTick(() => {
         const item = { editType: type, year, index, planMonths: [], months: [] }
         if (type === 1) {
-          this.form.month_plan_complete_amount.find(sub => sub.year === year).monthlyData.forEach(sub => {
-            item.planMonths.push(deepClone(sub))
-          })
-          this.form.month_complete_amount.find(sub => sub.year === year).monthlyData.forEach(sub => {
-            item.months.push(deepClone(sub))
-          })
+          this.form.month_plan_complete_amount
+            .find(sub => sub.year === year)
+            .monthlyData.forEach(sub => {
+              item.planMonths.push(deepClone(sub))
+            })
+          this.form.month_complete_amount
+            .find(sub => sub.year === year)
+            .monthlyData.forEach(sub => {
+              item.months.push(deepClone(sub))
+            })
         } else if (type === 2) {
-          this.form.month_plan_investment.find(sub => sub.year === year).monthlyData.forEach(sub => {
-            item.planMonths.push(deepClone(sub))
-          })
-          this.form.month_investment_amount.find(sub => sub.year === year).monthlyData.forEach(sub => {
-            item.months.push(deepClone(sub))
-          })
+          this.form.month_plan_investment
+            .find(sub => sub.year === year)
+            .monthlyData.forEach(sub => {
+              item.planMonths.push(deepClone(sub))
+            })
+          this.form.month_investment_amount
+            .find(sub => sub.year === year)
+            .monthlyData.forEach(sub => {
+              item.months.push(deepClone(sub))
+            })
         }
         this.current = Object.assign({}, item)
         for (let i = 1; i <= 11; i++) {
-          const index = this.current.months.findIndex(sub => sub.month === i.toString())
+          const index = this.current.months.findIndex(
+            sub => sub.month === i.toString()
+          )
           if (index === -1 && this.current.months.length < 11) {
             const ele = { month: i.toString(), data: '', year: '' }
             this.current.months.push(ele)
           }
-          const planIndex = this.current.planMonths.findIndex(sub => sub.month === i.toString())
+          const planIndex = this.current.planMonths.findIndex(
+            sub => sub.month === i.toString()
+          )
           if (planIndex === -1 && this.current.planMonths.length < 11) {
             const sub = { month: i.toString(), data: '', year: '' }
             this.current.planMonths.push(sub)
@@ -379,24 +565,32 @@ export default {
      * @param type 1 计划 2 累计
      * current 1 年度投资 2 纳统投资
      */
-    changeMonth (res, type, index) {
+    changeMonth(res, type, index) {
       setTimeout(() => {
         if (this.current.editType === 1) {
           if (type === 1) {
-            this.form.month_plan_complete_amount[this.current.index].monthlyData[index] = res
+            this.form.month_plan_complete_amount[
+              this.current.index
+            ].monthlyData[index] = res
           } else {
-            this.form.month_complete_amount[this.current.index].monthlyData[index] = res
+            this.form.month_complete_amount[this.current.index].monthlyData[
+              index
+            ] = res
           }
         } else if (this.current.editType === 2) {
           if (type === 1) {
-            this.form.month_plan_investment[this.current.index].monthlyData[index] = res
+            this.form.month_plan_investment[this.current.index].monthlyData[
+              index
+            ] = res
           } else {
-            this.form.month_investment_amount[this.current.index].monthlyData[index] = res
+            this.form.month_investment_amount[this.current.index].monthlyData[
+              index
+            ] = res
           }
         }
       }, 1000)
     },
-    getSum (list) {
+    getSum(list) {
       let sum = 0
       list.forEach(sub => {
         if (sub.data.length > 0) {
@@ -409,7 +603,7 @@ export default {
 }
 </script>
 
-<style lang='scss' scoped>
+<style lang="scss" scoped>
 .form-content {
   border: 1px solid #eeeeee;
   padding: 20px;
@@ -455,8 +649,8 @@ export default {
   height: 30px;
   width: 100%;
   border-radius: 4px;
-  background-color: #F5F7FA;
-  border: #E6E8ED solid 1px;
+  background-color: #f5f7fa;
+  border: #e6e8ed solid 1px;
   text-align: left;
   padding: 0 10px;
   color: #343434;
@@ -467,7 +661,7 @@ export default {
   width: 120px;
   margin-left: 10px;
   height: 30px;
-  background-color: #EDAC56;
+  background-color: #edac56;
   border-radius: 30px;
   padding: 0 10px;
 }

+ 323 - 0
src/views/home/component/params/params7.vue

@@ -0,0 +1,323 @@
+<template>
+  <div class="flex flex-center flex-col">
+    <!-- title and btn -->
+    <div class="flex flex-center full-width flex-justify-between mt-10 mb-10">
+      <span class="full-width text-left bold">{{ info.dictValue }}</span>
+    </div>
+    <!-- content list -->
+    <div style="width: 93%" class="mt-20">
+      <div class="flex flex-justify-start">
+        <el-button type="primary" icon="el-icon-plus" @click="addYear(1)"
+          >新增年度</el-button
+        >
+      </div>
+    </div>
+
+    <div style="width: 90%" class="mt-20">
+      <div class="flex flex-justify-start flex-col border padding">
+        <div
+          v-for="(item, index) in amount"
+          :key="item"
+          class="flex flex-center full-width"
+        >
+          <div
+            class="flex flex-justify-start flex-align-center full-width flex-child-average mb-20"
+          >
+            <div class="value flex flex-justify-end">
+              {{ item.year }}年度计划投资(万元)
+            </div>
+            <div class="ml-20 value-box flex flex-justify-start">
+              {{ item.planSum }}
+            </div>
+          </div>
+
+          <div
+            class="flex flex-justify-start flex-align-center full-width flex-child-average"
+          >
+            <div class="value flex flex-justify-end">年度累计投资(万元)</div>
+            <div class="ml-20 value-box flex flex-justify-start">
+              {{ item.actualSum }}
+            </div>
+          </div>
+          <div>
+            <el-button
+              type="primary"
+              size="mini"
+              icon="el-icon-edit"
+              round
+              class="ml-10"
+              @click="updateMonth(item, 1, index)"
+              >月填报</el-button
+            >
+          </div>
+        </div>
+      </div>
+    </div>
+
+    <!-- 纳统投资 -->
+    <div style="width: 93%" class="mt-20">
+      <div class="flex flex-justify-start">
+        <el-button type="primary" icon="el-icon-plus" @click="addYear(2)"
+          >新增年度</el-button
+        >
+      </div>
+    </div>
+
+    <div style="width: 90%" class="mt-20">
+      <div class="flex flex-justify-start border padding flex-col mb-10">
+        <div
+          v-for="(item, index) in investment"
+          :key="item"
+          class="flex flex-center full-width mb-20"
+        >
+          <div
+            class="flex flex-justify-start flex-align-center full-width flex-child-average"
+          >
+            <div class="value flex flex-justify-end">
+              {{ item.year }}年度计划纳统投资(万元)
+            </div>
+            <div class="ml-20 value-box flex flex-justify-start">
+              {{ item.planSum }}
+            </div>
+          </div>
+
+          <div
+            class="flex flex-justify-start flex-align-center full-width flex-child-average"
+          >
+            <div class="value flex flex-justify-end">
+              年度累计纳统投资(万元)
+            </div>
+            <div class="ml-20 value-box flex flex-justify-start">
+              {{ item.actualSum }}
+            </div>
+          </div>
+          <div>
+            <el-button
+              type="primary"
+              size="mini"
+              icon="el-icon-edit"
+              round
+              class="ml-10"
+              @click="updateMonth(item, 2, index)"
+              >月填报</el-button
+            >
+          </div>
+        </div>
+      </div>
+    </div>
+    <!-- dialog -->
+    <el-dialog v-model="show" title="投资情况" v-if="currentMonth">
+      <div>
+        <div>
+          <div class="flex flex-center">
+            <div>
+              <div class="title-box bold" style="background-color: white"></div>
+              <div class="title-box bold flex flex-center">计划投资:</div>
+              <div class="title-box bold mt-10 flex flex-center">
+                实际投资:
+              </div>
+            </div>
+            <div>
+              <div class="flex flex-center">
+                <div
+                  v-for="i in currentMonth.monthData"
+                  :key="i"
+                  class="month-box bold flex flex-center"
+                  @focus="focusin"
+                >
+                  {{ i.month }}月
+                </div>
+              </div>
+
+              <div class="flex flex-center">
+                <div
+                  v-for="i in currentMonth.monthData"
+                  :key="i"
+                  class="month-box flex flex-center"
+                >
+                  <el-input type="number" v-model="i.planData"></el-input>
+                </div>
+              </div>
+
+              <div class="flex flex-center mt-5">
+                <div
+                  v-for="i in currentMonth.monthData"
+                  :key="i"
+                  class="month-box flex flex-center"
+                >
+                  <el-input type="number" v-model="i.actualData"></el-input>
+                </div>
+              </div>
+            </div>
+          </div>
+          <el-button type="primary" icon="el-icon-check" @click="save"
+            >保存</el-button
+          >
+        </div>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+export default {
+  props: {
+    info: {
+      type: Object,
+      default: null
+    },
+    detail: {
+      type: Object,
+      default: null
+    }
+  },
+  watch: {
+    detail: {
+      immediate: true,
+      deep: true,
+      handler(val) {
+        this.form = val
+        if (val.amount && val.amount.data) {
+          this.amount = val.amount.data
+        }
+        if (val.investment && val.investment.data) {
+          this.investment = val.investment.data
+        }
+      }
+    }
+  },
+  data() {
+    return {
+      form: null,
+      disabled: true,
+      amount: [],
+      investment: [],
+      currentMonth: null,
+      show: false
+    }
+  },
+  methods: {
+    /**
+     * 新增年度
+     * @param {*} type 1,新增年度投资 2 新增纳统投资
+     */
+    addYear(type) {
+      let newYear = new Date().getFullYear()
+      if (type === 1 && this.amount.length > 0) {
+        newYear = this.amount[0].year + 1
+      } else if (type === 2 && this.investment.length > 0) {
+        newYear = this.investment[0].year + 1
+      }
+      const newMonthData = []
+      for (let i = 1; i <= 12; i++) {
+        const sub = {
+          actualData: 0,
+          planData: 0,
+          month: i.toString(),
+          year: newYear
+        }
+        newMonthData.push(sub)
+      }
+      const newYearObj = {
+        year: newYear,
+        actualSum: 0,
+        planSum: 0,
+        monthData: newMonthData
+      }
+      if (type === 1) {
+        this.amount.splice(0, 0, newYearObj)
+      } else if (type === 2) {
+        this.investment.splice(0, 0, newYearObj)
+      }
+    },
+    /**
+     * 更新数据
+     * @param type 1 计划 2 纳统 index
+     */
+    updateMonth(item, type, index) {
+      this.currentMonth = item
+      this.currentMonth.updateIndex = index
+      this.currentMonth.updateType = type
+      this.show = !this.show
+    },
+    save() {
+      if (this.currentMonth.updateType === 1) {
+        this.form.amount.data[this.currentMonth.updateIndex].monthData =
+          this.currentMonth.monthData.map(sub => {
+            sub.planData = Number.parseInt(sub.planData)
+            sub.actualData = Number.parseInt(sub.actualData)
+            return sub
+          })
+        this.form.amount.data[this.currentMonth.updateIndex].planSum =
+          this.getSum(
+            this.form.amount.data[this.currentMonth.updateIndex].monthData.map(
+              sub => sub.planData
+            )
+          )
+        this.form.amount.data[this.currentMonth.updateIndex].actualSum =
+          this.getSum(
+            this.form.amount.data[this.currentMonth.updateIndex].monthData.map(
+              sub => sub.actualData
+            )
+          )
+      } else if (this.currentMonth.updateType === 2) {
+        this.form.investment.data[this.currentMonth.updateIndex].monthData =
+          this.currentMonth.monthData.map(sub => {
+            sub.planData = Number.parseInt(sub.planData)
+            sub.actualData = Number.parseInt(sub.actualData)
+            return sub
+          })
+        this.form.investment.data[this.currentMonth.updateIndex].planSum =
+          this.getSum(
+            this.form.investment.data[
+              this.currentMonth.updateIndex
+            ].monthData.map(sub => sub.planData)
+          )
+        this.form.investment.data[this.currentMonth.updateIndex].actualSum =
+          this.getSum(
+            this.form.investment.data[
+              this.currentMonth.updateIndex
+            ].monthData.map(sub => sub.actualData)
+          )
+      }
+      delete this.form._id
+      this.$api.project.proUpdate(this.detail).then(res => {
+        if (res.code === 200) {
+          this.$message.success(res.msg)
+        } else {
+          this.$message.error(res.msg)
+        }
+        this.show = false
+      })
+    },
+    getSum(list) {
+      let sum = 0
+      list.forEach(sub => {
+        sum = sum + Number.parseInt(sub)
+      })
+      return sum
+    }
+  }
+}
+</script>
+<style lang="scss" scoped>
+.value {
+  width: 300px;
+}
+.value-box {
+  width: 100%;
+  background-color: #f5f7fa;
+  border-radius: 4px;
+  padding: 10px 10px;
+}
+.month-box {
+  width: 90px;
+  background-color: #f5f7fa;
+  margin: 5px;
+  height: 35px;
+}
+.title-box {
+  width: 90px;
+  height: 42px;
+}
+</style>

+ 35 - 16
src/views/home/details.vue

@@ -1,13 +1,32 @@
 <template>
-  <div class='flex flex-justify-start full-height'>
+  <div class="flex flex-justify-start full-height">
     <div class="full-height">
-      <left-bar :active="type === '0' ? -1 : active " :data="data" :stage="stage" @typeChange="typeChange"
-                @typeChange1="typeChange1"/>
+      <left-bar
+        :active="type === '0' ? -1 : active"
+        :data="data"
+        :stage="stage"
+        @typeChange="typeChange"
+        @typeChange1="typeChange1"
+      />
     </div>
-    <div class="full-height full-width white-bg padding-left padding-top" style="margin-left: 300px">
-      <proinfo v-if="type === '0'" :data="data" :issue="list" @refInfo="proInfo" @refresh="issueList"/>
-      <folder-info v-else-if="type === '1'" :id="id" :data='data' :projectStageId="projectStageId"/>
-      <grant-record v-else/>
+    <div
+      class="full-height full-width white-bg padding-left padding-top"
+      style="margin-left: 300px"
+    >
+      <proinfo
+        v-if="type === '0'"
+        :data="data"
+        :issue="list"
+        @refInfo="proInfo"
+        @refresh="issueList"
+      />
+      <folder-info
+        v-else-if="type === '1'"
+        :id="id"
+        :data="data"
+        :projectStageId="projectStageId"
+      />
+      <grant-record v-else />
     </div>
   </div>
 </template>
@@ -27,7 +46,7 @@ import grantRecord from '@/views/home/component/grant_record.vue'
 
 export default {
   name: '项目详情',
-  components: {leftBar, proinfo, folderInfo, grantRecord},
+  components: { leftBar, proinfo, folderInfo, grantRecord },
   watch: {
     stage: {
       handler(newValue) {
@@ -55,10 +74,11 @@ export default {
     this.proInfo()
     this.issueList()
     this.getStage()
-    this.$bus.on('change', (index) => {
+    this.$bus.on('change', index => {
       this.type = '1'
       this.active = index
-      this.projectStageId = this.stage[index] === undefined ? '' : this.stage[index].id
+      this.projectStageId =
+        this.stage[index] === undefined ? '' : this.stage[index].id
     })
   },
   methods: {
@@ -82,7 +102,7 @@ export default {
      * 发行明细
      */
     issueList() {
-      this.$api.project.issuanceDetail({projectId: this.id}).then(res => {
+      this.$api.project.issuanceDetail({ projectId: this.id }).then(res => {
         if (res.code === 200) {
           this.list = res.data.records
         }
@@ -92,7 +112,7 @@ export default {
      * 获取项目阶段
      */
     getStage() {
-      this.$api.project.includeStage({projectId: this.id}).then(res => {
+      this.$api.project.includeStage({ projectId: this.id }).then(res => {
         if (res.code === 200) {
           this.stage = res.data.map(e => {
             const newItem = {}
@@ -113,12 +133,11 @@ export default {
       if (this.$route.query.type !== '0') {
         this.type = '1'
       }
-      this.projectStageId = this.stage[res] === undefined ? '' : this.stage[res].id
+      this.projectStageId =
+        this.stage[res] === undefined ? '' : this.stage[res].id
     }
   }
 }
 </script>
 
-<style scoped>
-
-</style>
+<style scoped></style>

+ 48 - 30
src/views/home/excel.vue

@@ -1,29 +1,47 @@
 <template>
   <el-container>
-    <basic-container class='mt-10 content'>
-       <div class='full-width white-bg' style='width: 100vw'>
-         <div class='flex flex-center flex-justify-start'>
-           <el-button type='primary' plain @click='back'>返回</el-button>
-           <el-button type='primary' @click='exportExcel'>导出表格</el-button>
-         </div>
-         <span class='red full-width text-left  flex flex-justify-start mt-10'>注:左右滑动,查看更多内容</span>
-       </div>
-      <div class='content mt-10'>
-        <div class='header  flex flex-center flex-justify-start full-width'>
-          <div class='flex flex-center' style='background-color: #5ACAFA' v-for='(item,index) in header' :key='item.id'>
-            <div class='item flex flex-center ' :class='index === 0 ? "item":"sub" '>
+    <basic-container class="mt-10 content">
+      <div class="full-width white-bg" style="width: 100vw">
+        <div class="flex flex-center flex-justify-start">
+          <el-button type="primary" plain @click="back">返回</el-button>
+          <el-button type="primary" @click="exportExcel">导出表格</el-button>
+        </div>
+        <span class="red full-width text-left flex flex-justify-start mt-10"
+          >注:左右滑动,查看更多内容</span
+        >
+      </div>
+      <div class="content mt-10">
+        <div class="header flex flex-center flex-justify-start full-width">
+          <div
+            class="flex flex-center"
+            style="background-color: #5acafa"
+            v-for="(item, index) in header"
+            :key="item.id"
+          >
+            <div
+              class="item flex flex-center"
+              :class="index === 0 ? 'item' : 'sub'"
+            >
               {{ item }}
             </div>
           </div>
         </div>
 
-        <div class='flex flex-center flex-justify-start flex-col' >
-          <div class='flex flex-center full-width ' v-for='item in list' :key='item.id'>
-            <div class='flex flex-center flex-justify-start full-width'>
-              <div class='flex flex-center'>
-                <div v-for='(sub,index) in item' :key='sub.id' class='item flex flex-center overflow-hide'
-                     :class='index === 0 ? "item":"sub" '>
-                  <el-tooltip :content='sub' placement="top">
+        <div class="flex flex-center flex-justify-start flex-col">
+          <div
+            class="flex flex-center full-width"
+            v-for="item in list"
+            :key="item.id"
+          >
+            <div class="flex flex-center flex-justify-start full-width">
+              <div class="flex flex-center">
+                <div
+                  v-for="(sub, index) in item"
+                  :key="sub.id"
+                  class="item flex flex-center overflow-hide"
+                  :class="index === 0 ? 'item' : 'sub'"
+                >
+                  <el-tooltip :content="sub" placement="top">
                     {{ sub }}
                   </el-tooltip>
                 </div>
@@ -48,23 +66,23 @@ import BasicContainer from '@/components/basic-container/main.vue'
 export default {
   name: 'excel',
   components: { BasicContainer },
-  data () {
+  data() {
     return {
       header: [],
       list: [],
       query: null
     }
   },
-  created () {
+  created() {
     this.query = this.$route.query
     console.log(this.query)
     this.getList()
   },
   methods: {
-    back () {
+    back() {
       this.$router.back()
     },
-    getList () {
+    getList() {
       this.$api.params.preview(this.query).then(res => {
         if (res.code === 200) {
           this.header = res.data.header
@@ -75,7 +93,7 @@ export default {
       })
     },
 
-    exportExcel () {
+    exportExcel() {
       if (this.query.previewType === '1') {
         this.$api.params.exportResult(this.query).then(res => {
           if (res.hasOwnProperty('code')) {
@@ -94,8 +112,10 @@ export default {
         })
       }
     },
-    download (res) {
-      const url = window.URL.createObjectURL(new Blob([res], { type: 'application/vnd.ms-excel' }))
+    download(res) {
+      const url = window.URL.createObjectURL(
+        new Blob([res], { type: 'application/vnd.ms-excel' })
+      )
       const link = document.createElement('a')
       link.style.display = 'none'
       link.href = url
@@ -111,14 +131,14 @@ export default {
 }
 </script>
 
-<style lang='scss' scoped>
+<style lang="scss" scoped>
 .content {
   white-space: nowrap;
   overflow-x: scroll;
 }
 
 .header {
-  background-color: #5ACAFA;
+  background-color: #5acafa;
   border-top: #1a1a1a solid 1px;
 }
 
@@ -132,7 +152,6 @@ export default {
   margin-top: -1px;
   padding: 5px;
   white-space: pre-wrap;
-
 }
 
 .top {
@@ -147,5 +166,4 @@ export default {
   height: 50px;
   text-wrap: normal;
 }
-
 </style>

+ 49 - 33
src/views/home/pro_detail.vue

@@ -1,41 +1,45 @@
 <template>
-  <div class='flex flex-justify-start'>
+  <div class="flex flex-justify-start">
     <div class="full-height">
-      <pro-left :data="data" :code='code' @success='listSucc' @change='changeIndex'/>
+      <pro-left
+        :data="data"
+        :code="code"
+        @success="listSucc"
+        @change="changeIndex"
+      />
     </div>
-    <div style='margin-left: 300px;' class='full-width' ref='content'>
+    <div style="margin-left: 300px" class="full-width" ref="content">
       <basic-container>
-        <basic-tab :tabs='tabs' @change='change'></basic-tab>
+        <basic-tab :tabs="tabs" @change="change"></basic-tab>
       </basic-container>
 
-      <div v-if='Object.keys(data).length === 0'>
+      <div v-if="Object.keys(data).length === 0">
         <basic-container>
-          <el-empty description='加载中...'></el-empty>
+          <el-empty description="加载中..."></el-empty>
         </basic-container>
       </div>
 
-      <div v-if='currentTab.value === 1'>
-        <basic-container v-for='(item,index) in resultList' :key='item.id'>
-          <div class='full-width padding-top' :id="`header`+(index+1)">
-            <params1 v-if='item.dictKey === "1" ' :info='item' :detail='data'/>
-            <params2 v-if='item.dictKey === "2" ' :info='item' :detail='data'/>
-            <params3 v-if='item.dictKey === "3" ' :info='item' :detail='data'/>
-            <params4 v-if='item.dictKey === "4" ' :info='item' :detail='data'/>
-            <params5 v-if='item.dictKey === "5" ' :info='item' :detail='data'/>
-            <params6 v-if='item.dictKey === "6" ' :info='item' :detail='data'/>
+      <div v-if="currentTab.value === 1">
+        <basic-container v-for="(item, index) in resultList" :key="item.id">
+          <div class="full-width padding-top" :id="`header` + (index + 1)">
+            <params1 v-if="item.dictKey === '1'" :info="item" :detail="data" />
+            <params2 v-if="item.dictKey === '2'" :info="item" :detail="data" />
+            <params3 v-if="item.dictKey === '3'" :info="item" :detail="data" />
+            <params7 v-if="item.dictKey === '3'" :info="item" :detail="data" />
+            <params4 v-if="item.dictKey === '4'" :info="item" :detail="data" />
+            <params5 v-if="item.dictKey === '5'" :info="item" :detail="data" />
+            <params6 v-if="item.dictKey === '6'" :info="item" :detail="data" />
           </div>
         </basic-container>
       </div>
-      <div v-else-if='currentTab.value === 2'>
-        <basic-container v-for='(item,index) in resultList' :key='item.id'>
-          <div class='full-width' :id="`header`+(index+1)">
-            <inspect1 :info='item'/>
+      <div v-else-if="currentTab.value === 2">
+        <basic-container v-for="(item, index) in resultList" :key="item.id">
+          <div class="full-width" :id="`header` + (index + 1)">
+            <inspect1 :info="item" />
           </div>
         </basic-container>
       </div>
-      <div v-else-if='currentTab.value === 3'>
-        tab3
-      </div>
+      <div v-else-if="currentTab.value === 3">tab3</div>
     </div>
   </div>
 </template>
@@ -56,12 +60,25 @@ import params3 from '@/views/home/component/params/params3.vue'
 import params4 from '@/views/home/component/params/params4.vue'
 import params5 from '@/views/home/component/params/params5.vue'
 import params6 from '@/views/home/component/params/params6.vue'
+import params7 from '@/views/home/component/params/params7.vue'
 import inspect1 from '@/views/home/component/inspect/Inspect1.vue'
 
 export default {
   name: 'pro_detail',
-  components: { BasicContainer, proLeft, BasicTab, params1, inspect1, params2, params3, params4, params5, params6 },
-  data () {
+  components: {
+    BasicContainer,
+    proLeft,
+    BasicTab,
+    params1,
+    inspect1,
+    params2,
+    params3,
+    params4,
+    params5,
+    params6,
+    params7
+  },
+  data() {
     return {
       id: '',
       data: {},
@@ -76,7 +93,7 @@ export default {
       url: ''
     }
   },
-  created () {
+  created() {
     this.id = this.$route.query.id
     const tmp = window.location.href
     if (tmp.indexOf('#header') > 0) {
@@ -94,23 +111,24 @@ export default {
     }, 1500)
   },
   methods: {
-    change (res, index) {
+    change(res, index) {
       this.currentTab = res
       this.code = this.currentTab.code
-    }, /**
+    },
+    /**
      * 项目信息
      */
-    proInfo () {
+    proInfo() {
       this.$api.project.projectMapInfo(this.id).then(res => {
         if (res.code === 200) {
           this.data = res.data
         }
       })
     },
-    listSucc (list) {
+    listSucc(list) {
       this.resultList = list
     },
-    changeIndex (index) {
+    changeIndex(index) {
       // window.location.hash = '#header' + (index + 1)
       document.getElementById('header' + (index + 1)).scrollIntoView()
       // this.$nextTick(() => {
@@ -120,6 +138,4 @@ export default {
 }
 </script>
 
-<style scoped>
-
-</style>
+<style scoped></style>

+ 38 - 31
src/views/invest/components/amount.vue

@@ -1,21 +1,26 @@
 <template>
-  <div class='flex flex-justify-start flex-col'>
-    <span class='font-16 bold full-width text-left'>各部门/乡镇投资完成情况总览</span>
-    <div class='full-width flex-justify-end  flex'>
-      <el-select v-model="month" class="m-2" placeholder="请选择" ref='month' clearable @change='changeMonth'>
+  <div class="flex flex-justify-start flex-col">
+    <span class="font-16 bold full-width text-left"
+      >各部门/乡镇投资完成情况总览</span
+    >
+    <div class="full-width flex-justify-end flex">
+      <el-select
+        v-model="month"
+        class="m-2"
+        placeholder="请选择"
+        ref="month"
+        clearable
+        @change="changeMonth"
+      >
         <el-option
-            v-for="item in selectOption"
-            :key="item.value"
-            :label="item.label"
-            :value="item.value"
+          v-for="item in selectOption"
+          :key="item.value"
+          :label="item.label"
+          :value="item.value"
         />
       </el-select>
     </div>
-    <avue-crud
-        :option="option"
-        :data="data"
-        ref="crud"
-        v-model="form">
+    <avue-crud :option="option" :data="data" ref="crud" v-model="form">
     </avue-crud>
   </div>
 </template>
@@ -39,25 +44,25 @@ export default {
   },
   watch: {
     type: {
-      handler (val) {
+      handler(val) {
         this.initOption(val)
       },
       immediate: true
     },
     deptId: {
-      handler (val) {
+      handler(val) {
         this.onLoad()
       },
       immediate: true
     },
     year: {
-      handler (val) {
+      handler(val) {
         this.onLoad()
       },
       immediate: true
     }
   },
-  data () {
+  data() {
     return {
       month: '',
       quarter: '',
@@ -111,19 +116,21 @@ export default {
     }
   },
   methods: {
-    onLoad () {
-      this.$api.invest.list({
-        deptId: this.deptId === null ? '' : this.deptId,
-        year: this.year === null ? '' : this.year,
-        month: this.month,
-        quarter: this.quarter
-      }).then(res => {
-        if (res.code === 200) {
-          this.data = res.data
-        }
-      })
+    onLoad() {
+      this.$api.invest
+        .list({
+          deptId: this.deptId === null ? '' : this.deptId,
+          year: this.year === null ? '' : this.year,
+          month: this.month,
+          quarter: this.quarter
+        })
+        .then(res => {
+          if (res.code === 200) {
+            this.data = res.data
+          }
+        })
     },
-    initOption (res) {
+    initOption(res) {
       this.month = ''
       this.selectOption.length = 0
       switch (res.value) {
@@ -166,7 +173,7 @@ export default {
       }
       this.onLoad()
     },
-    changeMonth (res) {
+    changeMonth(res) {
       this.month = res
       this.onLoad()
     }
@@ -174,7 +181,7 @@ export default {
 }
 </script>
 
-<style lang='scss' scoped>
+<style lang="scss" scoped>
 .m-2 {
 }
 </style>

+ 442 - 49
yarn.lock

@@ -27,21 +27,38 @@
   resolved "https://registry.yarnpkg.com/@element-plus/icons-vue/-/icons-vue-2.0.6.tgz#8490e7a3193c17515d10c3be0544d800afe6a228"
   integrity sha512-lPpG8hYkjL/Z97DH5Ei6w6o22Z4YdNglWCNYOPcB33JCF2A4wye6HFgSI7hEt9zdLyxlSpiqtgf9XcYU+m5mew==
 
-"@eslint/eslintrc@^1.3.0":
-  version "1.3.0"
-  resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.3.0.tgz#29f92c30bb3e771e4a2048c95fa6855392dfac4f"
-  integrity sha512-UWW0TMTmk2d7hLcWD1/e2g5HDM/HQ3csaLSqXCfqwh4uNDuNqlaKWXmEsL4Cs41Z0KnILNvwbHAah3C2yt06kw==
+"@eslint-community/eslint-utils@^4.2.0":
+  version "4.4.0"
+  resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59"
+  integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==
+  dependencies:
+    eslint-visitor-keys "^3.3.0"
+
+"@eslint-community/regexpp@^4.4.0":
+  version "4.5.0"
+  resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.5.0.tgz#f6f729b02feee2c749f57e334b7a1b5f40a81724"
+  integrity sha512-vITaYzIcNmjn5tF5uxcZ/ft7/RXGrMUIS9HalWckEOF6ESiwXKoMzAQf2UW0aVd6rnOeExTJVd5hmWXucBKGXQ==
+
+"@eslint/eslintrc@^2.0.2":
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.0.2.tgz#01575e38707add677cf73ca1589abba8da899a02"
+  integrity sha512-3W4f5tDUra+pA+FzgugqL2pRimUTDJWKr7BINqOpkZrC0uYI0NIc0/JFgBROCU07HR6GieA5m3/rsPIhDmCXTQ==
   dependencies:
     ajv "^6.12.4"
     debug "^4.3.2"
-    espree "^9.3.2"
-    globals "^13.15.0"
+    espree "^9.5.1"
+    globals "^13.19.0"
     ignore "^5.2.0"
     import-fresh "^3.2.1"
     js-yaml "^4.1.0"
     minimatch "^3.1.2"
     strip-json-comments "^3.1.1"
 
+"@eslint/js@8.37.0":
+  version "8.37.0"
+  resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.37.0.tgz#cf1b5fa24217fe007f6487a26d765274925efa7d"
+  integrity sha512-x5vzdtOOGgFVDCUs81QRB2+liax8rFg3+7hqM+QhBG0/G3F1ZsoYl97UrqgHgQ9KKT7G6c4V+aTUCgu/n22v1A==
+
 "@floating-ui/core@^0.7.3":
   version "0.7.3"
   resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-0.7.3.tgz#d274116678ffae87f6b60e90f88cc4083eefab86"
@@ -59,14 +76,19 @@
   resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.3.tgz#555193ab2e3bb3b6adc3d551c9c030d9e860daf6"
   integrity sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==
 
-"@humanwhocodes/config-array@^0.9.2":
-  version "0.9.5"
-  resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.9.5.tgz#2cbaf9a89460da24b5ca6531b8bbfc23e1df50c7"
-  integrity sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==
+"@humanwhocodes/config-array@^0.11.8":
+  version "0.11.8"
+  resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.8.tgz#03595ac2075a4dc0f191cc2131de14fbd7d410b9"
+  integrity sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==
   dependencies:
     "@humanwhocodes/object-schema" "^1.2.1"
     debug "^4.1.1"
-    minimatch "^3.0.4"
+    minimatch "^3.0.5"
+
+"@humanwhocodes/module-importer@^1.0.1":
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c"
+  integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==
 
 "@humanwhocodes/object-schema@^1.2.1":
   version "1.2.1"
@@ -91,7 +113,7 @@
   resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b"
   integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==
 
-"@nodelib/fs.walk@^1.2.3":
+"@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8":
   version "1.2.8"
   resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a"
   integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==
@@ -296,6 +318,24 @@
   dependencies:
     "@types/ms" "*"
 
+"@types/eslint@^8.4.2":
+  version "8.21.3"
+  resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.21.3.tgz#5794b3911f0f19e34e3a272c49cbdf48d6f543f2"
+  integrity sha512-fa7GkppZVEByMWGbTtE5MbmXWJTVbrjjaS8K6uQj+XtuuUv1fsuPAxhygfqLmsb/Ufb3CV8deFCpiMfAgi00Sw==
+  dependencies:
+    "@types/estree" "*"
+    "@types/json-schema" "*"
+
+"@types/estree@*":
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.0.tgz#5fb2e536c1ae9bf35366eed879e827fa59ca41c2"
+  integrity sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==
+
+"@types/json-schema@*":
+  version "7.0.11"
+  resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3"
+  integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==
+
 "@types/json5@^0.0.29":
   version "0.0.29"
   resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
@@ -318,11 +358,60 @@
   resolved "https://registry.yarnpkg.com/@types/ms/-/ms-0.7.31.tgz#31b7ca6407128a3d2bbc27fe2d21b345397f6197"
   integrity sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==
 
+"@types/prettier@^2.6.0":
+  version "2.7.2"
+  resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.7.2.tgz#6c2324641cc4ba050a8c710b2b251b377581fbf0"
+  integrity sha512-KufADq8uQqo1pYKVIYzfKbJfBAc0sOeXqGbFaSpv8MRmC/zXgowNZmFcbngndGk922QDmOASEXUZCaY48gs4cg==
+
 "@types/web-bluetooth@^0.0.14":
   version "0.0.14"
   resolved "https://registry.yarnpkg.com/@types/web-bluetooth/-/web-bluetooth-0.0.14.tgz#94e175b53623384bff1f354cdb3197a8d63cdbe5"
   integrity sha512-5d2RhCard1nQUC3aHcq/gHzWYO6K0WJmAbjO7mQJgCQKtZpgXxv1rOM6O/dBDhDYYVutk1sciOgNSe+5YyfM8A==
 
+"@typescript-eslint/parser@^5.10.0":
+  version "5.57.0"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.57.0.tgz#f675bf2cd1a838949fd0de5683834417b757e4fa"
+  integrity sha512-orrduvpWYkgLCyAdNtR1QIWovcNZlEm6yL8nwH/eTxWLd8gsP+25pdLHYzL2QdkqrieaDwLpytHqycncv0woUQ==
+  dependencies:
+    "@typescript-eslint/scope-manager" "5.57.0"
+    "@typescript-eslint/types" "5.57.0"
+    "@typescript-eslint/typescript-estree" "5.57.0"
+    debug "^4.3.4"
+
+"@typescript-eslint/scope-manager@5.57.0":
+  version "5.57.0"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.57.0.tgz#79ccd3fa7bde0758059172d44239e871e087ea36"
+  integrity sha512-NANBNOQvllPlizl9LatX8+MHi7bx7WGIWYjPHDmQe5Si/0YEYfxSljJpoTyTWFTgRy3X8gLYSE4xQ2U+aCozSw==
+  dependencies:
+    "@typescript-eslint/types" "5.57.0"
+    "@typescript-eslint/visitor-keys" "5.57.0"
+
+"@typescript-eslint/types@5.57.0":
+  version "5.57.0"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.57.0.tgz#727bfa2b64c73a4376264379cf1f447998eaa132"
+  integrity sha512-mxsod+aZRSyLT+jiqHw1KK6xrANm19/+VFALVFP5qa/aiJnlP38qpyaTd0fEKhWvQk6YeNZ5LGwI1pDpBRBhtQ==
+
+"@typescript-eslint/typescript-estree@5.57.0":
+  version "5.57.0"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.57.0.tgz#ebcd0ee3e1d6230e888d88cddf654252d41e2e40"
+  integrity sha512-LTzQ23TV82KpO8HPnWuxM2V7ieXW8O142I7hQTxWIHDcCEIjtkat6H96PFkYBQqGFLW/G/eVVOB9Z8rcvdY/Vw==
+  dependencies:
+    "@typescript-eslint/types" "5.57.0"
+    "@typescript-eslint/visitor-keys" "5.57.0"
+    debug "^4.3.4"
+    globby "^11.1.0"
+    is-glob "^4.0.3"
+    semver "^7.3.7"
+    tsutils "^3.21.0"
+
+"@typescript-eslint/visitor-keys@5.57.0":
+  version "5.57.0"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.57.0.tgz#e2b2f4174aff1d15eef887ce3d019ecc2d7a8ac1"
+  integrity sha512-ery2g3k0hv5BLiKpPuwYt9KBkAp2ugT6VvyShXdLOkax895EC55sP0Tx5L0fZaQueiK3fBLvHVvEl3jFS5ia+g==
+  dependencies:
+    "@typescript-eslint/types" "5.57.0"
+    eslint-visitor-keys "^3.3.0"
+
 "@vitejs/plugin-vue@^3.0.0":
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/@vitejs/plugin-vue/-/plugin-vue-3.0.0.tgz#7081e2b3fbe04e291bb85107b9fb57a1fa5e6aeb"
@@ -482,6 +571,11 @@ acorn@^8.7.1:
   resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.1.tgz#0197122c843d1bf6d0a5e83220a788f278f63c30"
   integrity sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==
 
+acorn@^8.8.0:
+  version "8.8.2"
+  resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a"
+  integrity sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==
+
 agent-base@6, agent-base@^6.0.2:
   version "6.0.2"
   resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77"
@@ -516,11 +610,33 @@ ajv@^6.10.0, ajv@^6.12.4:
     json-schema-traverse "^0.4.1"
     uri-js "^4.2.2"
 
+ansi-regex@^2.0.0:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
+  integrity sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==
+
+ansi-regex@^3.0.0:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.1.tgz#123d6479e92ad45ad897d4054e3c7ca7db4944e1"
+  integrity sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==
+
 ansi-regex@^5.0.1:
   version "5.0.1"
   resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304"
   integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==
 
+ansi-styles@^2.2.1:
+  version "2.2.1"
+  resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
+  integrity sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==
+
+ansi-styles@^3.2.0:
+  version "3.2.1"
+  resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
+  integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==
+  dependencies:
+    color-convert "^1.9.0"
+
 ansi-styles@^4.1.0, ansi-styles@^4.3.0:
   version "4.3.0"
   resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937"
@@ -570,6 +686,11 @@ array-includes@^3.1.4:
     get-intrinsic "^1.1.1"
     is-string "^1.0.7"
 
+array-union@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d"
+  integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==
+
 array.prototype.flat@^1.2.5:
   version "1.3.0"
   resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.0.tgz#0b0c1567bf57b38b56b4c97b8aa72ab45e4adc7b"
@@ -701,6 +822,17 @@ callsites@^3.0.0:
   resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73"
   integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==
 
+chalk@^1.1.3:
+  version "1.1.3"
+  resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
+  integrity sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==
+  dependencies:
+    ansi-styles "^2.2.1"
+    escape-string-regexp "^1.0.2"
+    has-ansi "^2.0.0"
+    strip-ansi "^3.0.0"
+    supports-color "^2.0.0"
+
 chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.2:
   version "4.1.2"
   resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
@@ -770,6 +902,13 @@ cmd-shim@^5.0.0:
   dependencies:
     mkdirp-infer-owner "^2.0.0"
 
+color-convert@^1.9.0:
+  version "1.9.3"
+  resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
+  integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==
+  dependencies:
+    color-name "1.1.3"
+
 color-convert@^2.0.1:
   version "2.0.1"
   resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3"
@@ -777,6 +916,11 @@ color-convert@^2.0.1:
   dependencies:
     color-name "~1.1.4"
 
+color-name@1.1.3:
+  version "1.1.3"
+  resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
+  integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==
+
 color-name@~1.1.4:
   version "1.1.4"
   resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
@@ -807,6 +951,11 @@ common-ancestor-path@^1.0.1:
   resolved "https://registry.yarnpkg.com/common-ancestor-path/-/common-ancestor-path-1.0.1.tgz#4f7d2d1394d91b7abdf51871c62f71eadb0182a7"
   integrity sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w==
 
+common-tags@^1.4.0:
+  version "1.8.2"
+  resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.8.2.tgz#94ebb3c076d26032745fd54face7f688ef5ac9c6"
+  integrity sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==
+
 concat-map@0.0.1:
   version "0.0.1"
   resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
@@ -958,6 +1107,18 @@ diff@^5.0.0:
   resolved "https://registry.yarnpkg.com/diff/-/diff-5.1.0.tgz#bc52d298c5ea8df9194800224445ed43ffc87e40"
   integrity sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==
 
+dir-glob@^3.0.1:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f"
+  integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==
+  dependencies:
+    path-type "^4.0.0"
+
+dlv@^1.1.0:
+  version "1.1.3"
+  resolved "https://registry.yarnpkg.com/dlv/-/dlv-1.1.3.tgz#5c198a8a11453596e751494d49874bc7732f2e79"
+  integrity sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==
+
 doctrine@^2.1.0:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d"
@@ -1213,11 +1374,21 @@ escape-html@^1.0.3:
   resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
   integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==
 
+escape-string-regexp@^1.0.2:
+  version "1.0.5"
+  resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
+  integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==
+
 escape-string-regexp@^4.0.0:
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34"
   integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==
 
+eslint-config-prettier@^8.8.0:
+  version "8.8.0"
+  resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.8.0.tgz#bfda738d412adc917fd7b038857110efe98c9348"
+  integrity sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA==
+
 eslint-config-standard@^17.0.0:
   version "17.0.0"
   resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-17.0.0.tgz#fd5b6cf1dcf6ba8d29f200c461de2e19069888cf"
@@ -1280,6 +1451,13 @@ eslint-plugin-n@^15.0.0:
     resolve "^1.10.1"
     semver "^7.3.7"
 
+eslint-plugin-prettier@^4.2.1:
+  version "4.2.1"
+  resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz#651cbb88b1dab98bfd42f017a12fa6b2d993f94b"
+  integrity sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==
+  dependencies:
+    prettier-linter-helpers "^1.0.0"
+
 eslint-plugin-promise@^6.0.0:
   version "6.0.0"
   resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-6.0.0.tgz#017652c07c9816413a41e11c30adc42c3d55ff18"
@@ -1298,7 +1476,7 @@ eslint-plugin-vue@^9.2.0:
     vue-eslint-parser "^9.0.1"
     xml-name-validator "^4.0.0"
 
-eslint-scope@^7.1.1:
+eslint-scope@^7.0.0, eslint-scope@^7.1.1:
   version "7.1.1"
   resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.1.1.tgz#fff34894c2f65e5226d3041ac480b4513a163642"
   integrity sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==
@@ -1330,18 +1508,28 @@ eslint-visitor-keys@^2.0.0:
   resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303"
   integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==
 
+eslint-visitor-keys@^3.1.0, eslint-visitor-keys@^3.4.0:
+  version "3.4.0"
+  resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.0.tgz#c7f0f956124ce677047ddbc192a68f999454dedc"
+  integrity sha512-HPpKPUBQcAsZOsHAFwTtIKcYlCje62XB7SEAcxjtmW6TD1WVpkS6i6/hOVtTZIl4zGj/mBqpFVGvaDneik+VoQ==
+
 eslint-visitor-keys@^3.3.0:
   version "3.3.0"
   resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826"
   integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==
 
-eslint@^8.0.1:
-  version "8.20.0"
-  resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.20.0.tgz#048ac56aa18529967da8354a478be4ec0a2bc81b"
-  integrity sha512-d4ixhz5SKCa1D6SCPrivP7yYVi7nyD6A4vs6HIAul9ujBzcEmZVM3/0NN/yu5nKhmO1wjp5xQ46iRfmDGlOviA==
-  dependencies:
-    "@eslint/eslintrc" "^1.3.0"
-    "@humanwhocodes/config-array" "^0.9.2"
+eslint@^8.37.0, eslint@^8.7.0:
+  version "8.37.0"
+  resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.37.0.tgz#1f660ef2ce49a0bfdec0b0d698e0b8b627287412"
+  integrity sha512-NU3Ps9nI05GUoVMxcZx1J8CNR6xOvUT4jAUMH5+z8lpp3aEdPVCImKw6PWG4PY+Vfkpr+jvMpxs/qoE7wq0sPw==
+  dependencies:
+    "@eslint-community/eslint-utils" "^4.2.0"
+    "@eslint-community/regexpp" "^4.4.0"
+    "@eslint/eslintrc" "^2.0.2"
+    "@eslint/js" "8.37.0"
+    "@humanwhocodes/config-array" "^0.11.8"
+    "@humanwhocodes/module-importer" "^1.0.1"
+    "@nodelib/fs.walk" "^1.2.8"
     ajv "^6.10.0"
     chalk "^4.0.0"
     cross-spawn "^7.0.2"
@@ -1349,20 +1537,22 @@ eslint@^8.0.1:
     doctrine "^3.0.0"
     escape-string-regexp "^4.0.0"
     eslint-scope "^7.1.1"
-    eslint-utils "^3.0.0"
-    eslint-visitor-keys "^3.3.0"
-    espree "^9.3.2"
-    esquery "^1.4.0"
+    eslint-visitor-keys "^3.4.0"
+    espree "^9.5.1"
+    esquery "^1.4.2"
     esutils "^2.0.2"
     fast-deep-equal "^3.1.3"
     file-entry-cache "^6.0.1"
-    functional-red-black-tree "^1.0.1"
-    glob-parent "^6.0.1"
-    globals "^13.15.0"
+    find-up "^5.0.0"
+    glob-parent "^6.0.2"
+    globals "^13.19.0"
+    grapheme-splitter "^1.0.4"
     ignore "^5.2.0"
     import-fresh "^3.0.0"
     imurmurhash "^0.1.4"
     is-glob "^4.0.0"
+    is-path-inside "^3.0.3"
+    js-sdsl "^4.1.4"
     js-yaml "^4.1.0"
     json-stable-stringify-without-jsonify "^1.0.1"
     levn "^0.4.1"
@@ -1370,13 +1560,20 @@ eslint@^8.0.1:
     minimatch "^3.1.2"
     natural-compare "^1.4.0"
     optionator "^0.9.1"
-    regexpp "^3.2.0"
     strip-ansi "^6.0.1"
     strip-json-comments "^3.1.0"
     text-table "^0.2.0"
-    v8-compile-cache "^2.0.3"
 
-espree@^9.3.1, espree@^9.3.2:
+espree@^9.0.0, espree@^9.5.1:
+  version "9.5.1"
+  resolved "https://registry.yarnpkg.com/espree/-/espree-9.5.1.tgz#4f26a4d5f18905bf4f2e0bd99002aab807e96dd4"
+  integrity sha512-5yxtHSZXRSW5pvv3hAlXM5+/Oswi1AUFqBmbibKb5s6bp3rGIDkyXU6xCoyuuLhijr4SFwPrXRoZjz0AZDN9tg==
+  dependencies:
+    acorn "^8.8.0"
+    acorn-jsx "^5.3.2"
+    eslint-visitor-keys "^3.4.0"
+
+espree@^9.3.1:
   version "9.3.2"
   resolved "https://registry.yarnpkg.com/espree/-/espree-9.3.2.tgz#f58f77bd334731182801ced3380a8cc859091596"
   integrity sha512-D211tC7ZwouTIuY5x9XnS0E9sWNChB7IYKX/Xp5eQj3nFXhqmiUDB9q27y76oFl8jTg3pXcQx/bpxMfs3CIZbA==
@@ -1404,6 +1601,13 @@ esquery@^1.4.0:
   dependencies:
     estraverse "^5.1.0"
 
+esquery@^1.4.2:
+  version "1.5.0"
+  resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b"
+  integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==
+  dependencies:
+    estraverse "^5.1.0"
+
 esrecurse@^4.3.0:
   version "4.3.0"
   resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921"
@@ -1439,6 +1643,11 @@ fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3:
   resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
   integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
 
+fast-diff@^1.1.2:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03"
+  integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==
+
 fast-glob@^3.2.11:
   version "3.2.11"
   resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.11.tgz#a1172ad95ceb8a16e20caa5c5e56480e5129c1d9"
@@ -1450,6 +1659,17 @@ fast-glob@^3.2.11:
     merge2 "^1.3.0"
     micromatch "^4.0.4"
 
+fast-glob@^3.2.9:
+  version "3.2.12"
+  resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80"
+  integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==
+  dependencies:
+    "@nodelib/fs.stat" "^2.0.2"
+    "@nodelib/fs.walk" "^1.2.3"
+    glob-parent "^5.1.2"
+    merge2 "^1.3.0"
+    micromatch "^4.0.4"
+
 fast-json-stable-stringify@^2.0.0:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633"
@@ -1493,6 +1713,14 @@ find-up@^2.1.0:
   dependencies:
     locate-path "^2.0.0"
 
+find-up@^5.0.0:
+  version "5.0.0"
+  resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc"
+  integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==
+  dependencies:
+    locate-path "^6.0.0"
+    path-exists "^4.0.0"
+
 flat-cache@^3.0.4:
   version "3.0.4"
   resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11"
@@ -1559,11 +1787,6 @@ function.prototype.name@^1.1.5:
     es-abstract "^1.19.0"
     functions-have-names "^1.2.2"
 
-functional-red-black-tree@^1.0.1:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327"
-  integrity sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==
-
 functions-have-names@^1.2.2:
   version "1.2.3"
   resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834"
@@ -1607,7 +1830,7 @@ glob-parent@^5.1.2, glob-parent@~5.1.2:
   dependencies:
     is-glob "^4.0.1"
 
-glob-parent@^6.0.1:
+glob-parent@^6.0.2:
   version "6.0.2"
   resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3"
   integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==
@@ -1637,18 +1860,42 @@ glob@^8.0.1:
     minimatch "^5.0.1"
     once "^1.3.0"
 
-globals@^13.15.0:
-  version "13.16.0"
-  resolved "https://registry.yarnpkg.com/globals/-/globals-13.16.0.tgz#9be4aca28f311aaeb974ea54978ebbb5e35ce46a"
-  integrity sha512-A1lrQfpNF+McdPOnnFqY3kSN0AFTy485bTi1bkLk4mVPODIUEcSfhHgRqA+QdXPksrSTTztYXx37NFV+GpGk3Q==
+globals@^13.19.0:
+  version "13.20.0"
+  resolved "https://registry.yarnpkg.com/globals/-/globals-13.20.0.tgz#ea276a1e508ffd4f1612888f9d1bad1e2717bf82"
+  integrity sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==
   dependencies:
     type-fest "^0.20.2"
 
+globby@^11.1.0:
+  version "11.1.0"
+  resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b"
+  integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==
+  dependencies:
+    array-union "^2.1.0"
+    dir-glob "^3.0.1"
+    fast-glob "^3.2.9"
+    ignore "^5.2.0"
+    merge2 "^1.4.1"
+    slash "^3.0.0"
+
 graceful-fs@^4.1.2, graceful-fs@^4.2.10, graceful-fs@^4.2.6:
   version "4.2.10"
   resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c"
   integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==
 
+grapheme-splitter@^1.0.4:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz#9cf3a665c6247479896834af35cf1dbb4400767e"
+  integrity sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==
+
+has-ansi@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91"
+  integrity sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==
+  dependencies:
+    ansi-regex "^2.0.0"
+
 has-bigints@^1.0.1, has-bigints@^1.0.2:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa"
@@ -1928,6 +2175,11 @@ is-number@^7.0.0:
   resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
   integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
 
+is-path-inside@^3.0.3:
+  version "3.0.3"
+  resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283"
+  integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==
+
 is-regex@^1.1.1, is-regex@^1.1.4:
   version "1.1.4"
   resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958"
@@ -2028,6 +2280,11 @@ js-md5@^0.7.3:
   resolved "https://registry.yarnpkg.com/js-md5/-/js-md5-0.7.3.tgz#b4f2fbb0b327455f598d6727e38ec272cd09c3f2"
   integrity sha512-ZC41vPSTLKGwIRjqDh8DfXoCrdQIyBgspJVPXHBGu4nZlAEvG3nf+jO9avM9RmLiGakg7vz974ms99nEV0tmTQ==
 
+js-sdsl@^4.1.4:
+  version "4.4.0"
+  resolved "https://registry.yarnpkg.com/js-sdsl/-/js-sdsl-4.4.0.tgz#8b437dbe642daa95760400b602378ed8ffea8430"
+  integrity sha512-FfVSdx6pJ41Oa+CF7RDaFmTnCaFhua+SNYQX74riGOpl96x+2jQCqEfQ2bnXu/5DPCqlRuiqyvTJM0Qjz26IVg==
+
 js-yaml@^4.1.0:
   version "4.1.0"
   resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602"
@@ -2226,6 +2483,13 @@ locate-path@^2.0.0:
     p-locate "^2.0.0"
     path-exists "^3.0.0"
 
+locate-path@^6.0.0:
+  version "6.0.0"
+  resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286"
+  integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==
+  dependencies:
+    p-locate "^5.0.0"
+
 lodash-es@^4.17.21:
   version "4.17.21"
   resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee"
@@ -2236,7 +2500,7 @@ lodash-unified@^1.0.2:
   resolved "https://registry.yarnpkg.com/lodash-unified/-/lodash-unified-1.0.2.tgz#bb2694db3533781e5cce984af60cfaea318b83c1"
   integrity sha512-OGbEy+1P+UT26CYi4opY4gebD8cWRDxAT6MAObIVQMiqYdxZr1g3QHWCToVsm31x2NkLS4K3+MC2qInaRMa39g==
 
-lodash.merge@^4.6.2:
+lodash.merge@^4.6.0, lodash.merge@^4.6.2:
   version "4.6.2"
   resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
   integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==
@@ -2246,6 +2510,19 @@ lodash@^4.17.21:
   resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
   integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
 
+loglevel-colored-level-prefix@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/loglevel-colored-level-prefix/-/loglevel-colored-level-prefix-1.0.0.tgz#6a40218fdc7ae15fc76c3d0f3e676c465388603e"
+  integrity sha512-u45Wcxxc+SdAlh4yeF/uKlC1SPUPCy0gullSNKXod5I4bmifzk+Q4lSLExNEVn19tGaJipbZ4V4jbFn79/6mVA==
+  dependencies:
+    chalk "^1.1.3"
+    loglevel "^1.4.1"
+
+loglevel@^1.4.1:
+  version "1.8.1"
+  resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.8.1.tgz#5c621f83d5b48c54ae93b6156353f555963377b4"
+  integrity sha512-tCRIJM51SHjAayKwC+QAg8hT8vg6z7GSgLJKGvzuPb1Wc+hLzqtuVLxp6/HzSPOozuK+8ErAhy7U/sVzw8Dgfg==
+
 lru-cache@^6.0.0:
   version "6.0.0"
   resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
@@ -2299,7 +2576,7 @@ memoize-one@^6.0.0:
   resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-6.0.0.tgz#b2591b871ed82948aee4727dc6abceeeac8c1045"
   integrity sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==
 
-merge2@^1.3.0:
+merge2@^1.3.0, merge2@^1.4.1:
   version "1.4.1"
   resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
   integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==
@@ -2329,7 +2606,7 @@ mimic-response@^3.1.0:
   resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9"
   integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==
 
-minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2:
+minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2:
   version "3.1.2"
   resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
   integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
@@ -2768,6 +3045,13 @@ p-limit@^1.1.0:
   dependencies:
     p-try "^1.0.0"
 
+p-limit@^3.0.2:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b"
+  integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==
+  dependencies:
+    yocto-queue "^0.1.0"
+
 p-locate@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43"
@@ -2775,6 +3059,13 @@ p-locate@^2.0.0:
   dependencies:
     p-limit "^1.1.0"
 
+p-locate@^5.0.0:
+  version "5.0.0"
+  resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834"
+  integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==
+  dependencies:
+    p-limit "^3.0.2"
+
 p-map@^4.0.0:
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b"
@@ -2845,6 +3136,11 @@ path-exists@^3.0.0:
   resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515"
   integrity sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==
 
+path-exists@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3"
+  integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==
+
 path-is-absolute@^1.0.0:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
@@ -2860,6 +3156,11 @@ path-parse@^1.0.7:
   resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
   integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
 
+path-type@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b"
+  integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==
+
 path@^0.12.7:
   version "0.12.7"
   resolved "https://registry.yarnpkg.com/path/-/path-0.12.7.tgz#d4dc2a506c4ce2197eb481ebfcd5b36c0140b10f"
@@ -2913,6 +3214,46 @@ prelude-ls@^1.2.1:
   resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"
   integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==
 
+prettier-eslint@^15.0.1:
+  version "15.0.1"
+  resolved "https://registry.yarnpkg.com/prettier-eslint/-/prettier-eslint-15.0.1.tgz#2543a43e9acec2a9767ad6458165ce81f353db9c"
+  integrity sha512-mGOWVHixSvpZWARqSDXbdtTL54mMBxc5oQYQ6RAqy8jecuNJBgN3t9E5a81G66F8x8fsKNiR1HWaBV66MJDOpg==
+  dependencies:
+    "@types/eslint" "^8.4.2"
+    "@types/prettier" "^2.6.0"
+    "@typescript-eslint/parser" "^5.10.0"
+    common-tags "^1.4.0"
+    dlv "^1.1.0"
+    eslint "^8.7.0"
+    indent-string "^4.0.0"
+    lodash.merge "^4.6.0"
+    loglevel-colored-level-prefix "^1.0.0"
+    prettier "^2.5.1"
+    pretty-format "^23.0.1"
+    require-relative "^0.8.7"
+    typescript "^4.5.4"
+    vue-eslint-parser "^8.0.1"
+
+prettier-linter-helpers@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b"
+  integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==
+  dependencies:
+    fast-diff "^1.1.2"
+
+prettier@^2.5.1, prettier@^2.8.7:
+  version "2.8.7"
+  resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.7.tgz#bb79fc8729308549d28fe3a98fce73d2c0656450"
+  integrity sha512-yPngTo3aXUUmyuTjeTUT75txrf+aMh9FiD7q9ZE/i6r0bPb22g4FsE6Y338PQX1bmfy08i9QQCB7/rcUAVntfw==
+
+pretty-format@^23.0.1:
+  version "23.6.0"
+  resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-23.6.0.tgz#5eaac8eeb6b33b987b7fe6097ea6a8a146ab5760"
+  integrity sha512-zf9NV1NSlDLDjycnwm6hpFATCGl/K1lt0R/GdkAK2O5LN/rwJoB+Mh93gGJjut4YbmecbfgLWVGSTCr0Ewvvbw==
+  dependencies:
+    ansi-regex "^3.0.0"
+    ansi-styles "^3.2.0"
+
 proc-log@^2.0.0, proc-log@^2.0.1:
   version "2.0.1"
   resolved "https://registry.yarnpkg.com/proc-log/-/proc-log-2.0.1.tgz#8f3f69a1f608de27878f91f5c688b225391cb685"
@@ -3033,11 +3374,16 @@ regexp.prototype.flags@^1.3.0, regexp.prototype.flags@^1.4.3:
     define-properties "^1.1.3"
     functions-have-names "^1.2.2"
 
-regexpp@^3.0.0, regexpp@^3.2.0:
+regexpp@^3.0.0:
   version "3.2.0"
   resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2"
   integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==
 
+require-relative@^0.8.7:
+  version "0.8.7"
+  resolved "https://registry.yarnpkg.com/require-relative/-/require-relative-0.8.7.tgz#7999539fc9e047a37928fa196f8e1563dabd36de"
+  integrity sha512-AKGr4qvHiryxRb19m3PsLRGuKVAbJLUD7E6eOaHkfKhwc+vSgVOCY5xNvm9EkolBKTOf0GrQAZKLimOCz81Khg==
+
 resolve-from@^4.0.0:
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6"
@@ -3162,6 +3508,11 @@ simple-get@^4.0.1:
     once "^1.3.1"
     simple-concat "^1.0.0"
 
+slash@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634"
+  integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==
+
 smart-buffer@^4.2.0:
   version "4.2.0"
   resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae"
@@ -3273,6 +3624,13 @@ string_decoder@^1.1.1:
   dependencies:
     safe-buffer "~5.2.0"
 
+strip-ansi@^3.0.0:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf"
+  integrity sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==
+  dependencies:
+    ansi-regex "^2.0.0"
+
 strip-ansi@^6.0.1:
   version "6.0.1"
   resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
@@ -3290,6 +3648,11 @@ strip-json-comments@^3.1.0, strip-json-comments@^3.1.1:
   resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"
   integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
 
+supports-color@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
+  integrity sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==
+
 supports-color@^7.1.0:
   version "7.2.0"
   resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da"
@@ -3351,6 +3714,18 @@ tslib@2.3.0:
   resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.0.tgz#803b8cdab3e12ba581a4ca41c8839bbb0dacb09e"
   integrity sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==
 
+tslib@^1.8.1:
+  version "1.14.1"
+  resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
+  integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
+
+tsutils@^3.21.0:
+  version "3.21.0"
+  resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623"
+  integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==
+  dependencies:
+    tslib "^1.8.1"
+
 type-check@^0.4.0, type-check@~0.4.0:
   version "0.4.0"
   resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1"
@@ -3363,6 +3738,11 @@ type-fest@^0.20.2:
   resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4"
   integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==
 
+typescript@^4.5.4:
+  version "4.9.5"
+  resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a"
+  integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==
+
 unbox-primitive@^1.0.2:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e"
@@ -3406,11 +3786,6 @@ util@^0.10.3:
   dependencies:
     inherits "2.0.3"
 
-v8-compile-cache@^2.0.3:
-  version "2.3.0"
-  resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee"
-  integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==
-
 validate-npm-package-license@^3.0.4:
   version "3.0.4"
   resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a"
@@ -3477,6 +3852,19 @@ vue-demi@*:
   resolved "https://registry.yarnpkg.com/vue-demi/-/vue-demi-0.13.4.tgz#fcb320892d78d3a7ec227024776f77d9a5c4831d"
   integrity sha512-KP4lq9uSz0KZbaqCllRhnxMV3mYRsRWJfdsAhZyt5bV5O1RTpoeDptBRV9NOa/JgOpfaA9ane88VF7OjWNK/DA==
 
+vue-eslint-parser@^8.0.1:
+  version "8.3.0"
+  resolved "https://registry.yarnpkg.com/vue-eslint-parser/-/vue-eslint-parser-8.3.0.tgz#5d31129a1b3dd89c0069ca0a1c88f970c360bd0d"
+  integrity sha512-dzHGG3+sYwSf6zFBa0Gi9ZDshD7+ad14DGOdTLjruRVgZXe2J+DcZ9iUhyR48z5g1PqRa20yt3Njna/veLJL/g==
+  dependencies:
+    debug "^4.3.2"
+    eslint-scope "^7.0.0"
+    eslint-visitor-keys "^3.1.0"
+    espree "^9.0.0"
+    esquery "^1.4.0"
+    lodash "^4.17.21"
+    semver "^7.3.5"
+
 vue-eslint-parser@^9.0.1:
   version "9.0.3"
   resolved "https://registry.yarnpkg.com/vue-eslint-parser/-/vue-eslint-parser-9.0.3.tgz#0c17a89e0932cc94fa6a79f0726697e13bfe3c96"
@@ -3622,6 +4010,11 @@ yaml@^2.1.1:
   resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.1.1.tgz#1e06fb4ca46e60d9da07e4f786ea370ed3c3cfec"
   integrity sha512-o96x3OPo8GjWeSLF+wOAbrPfhFOGY0W00GNaxCDv+9hkcDJEnev1yh8S7pgHF0ik6zc8sQLuL8hjHjJULZp8bw==
 
+yocto-queue@^0.1.0:
+  version "0.1.0"
+  resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
+  integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
+
 zrender@5.4.1:
   version "5.4.1"
   resolved "https://registry.yarnpkg.com/zrender/-/zrender-5.4.1.tgz#892f864b885c71e1dc25dcb3c7a4ba42678d3f11"