Эх сурвалжийг харах

feat: Detail组件重构完成

kailong321200875 3 жил өмнө
parent
commit
7f5ef99ccc

+ 20 - 11
components.d.ts

@@ -4,18 +4,25 @@
 
 declare module 'vue' {
   export interface GlobalComponents {
-    404: typeof import('E:/HBuilderProjects/element-plus-admin/src/components/Error/404.vue')['default']
+    404: typeof import('./src/components/Error/404.vue')['default']
     Aa: typeof import('E:/HBuilderProjects/element-plus-admin/src/components/aa.vue')['default']
-    CountTo: typeof import('E:/HBuilderProjects/element-plus-admin/src/components/CountTo/index.vue')['default']
-    Dialog: typeof import('E:/HBuilderProjects/element-plus-admin/src/components/Dialog/index.vue')['default']
-    Echart: typeof import('E:/HBuilderProjects/element-plus-admin/src/components/Echart/index.vue')['default']
-    Editor: typeof import('E:/HBuilderProjects/element-plus-admin/src/components/Editor/index.vue')['default']
+    Avatars: typeof import('./src/components/Avatars/index.vue')['default']
+    CountTo: typeof import('./src/components/CountTo/index.vue')['default']
+    Detail: typeof import('./src/components/Detail/index.vue')['default']
+    Dialog: typeof import('./src/components/Dialog/index.vue')['default']
+    Echart: typeof import('./src/components/Echart/index.vue')['default']
+    Editor: typeof import('./src/components/Editor/index.vue')['default']
     ElAlert: typeof import('element-plus/es')['ElAlert']
+    ElAvatar: typeof import('element-plus/es')['ElAvatar']
     ElBacktop: typeof import('element-plus/es')['ElBacktop']
     ElButton: typeof import('element-plus/es')['ElButton']
+    ElCard: typeof import('element-plus/es')['ElCard']
     ElCol: typeof import('element-plus/es')['ElCol']
+    ElCollapseTransition: typeof import('element-plus/es')['ElCollapseTransition']
     ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider']
     ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
+    ElDescriptions: typeof import('element-plus/es')['ElDescriptions']
+    ElDescriptionsItem: typeof import('element-plus/es')['ElDescriptionsItem']
     ElDialog: typeof import('element-plus/es')['ElDialog']
     ElDrawer: typeof import('element-plus/es')['ElDrawer']
     ElDropdown: typeof import('element-plus/es')['ElDropdown']
@@ -38,16 +45,18 @@ declare module 'vue' {
     ElSwitch: typeof import('element-plus/es')['ElSwitch']
     ElTabPane: typeof import('element-plus/es')['ElTabPane']
     ElTabs: typeof import('element-plus/es')['ElTabs']
+    ElTag: typeof import('element-plus/es')['ElTag']
     ElTimePicker: typeof import('element-plus/es')['ElTimePicker']
     ElTimeSelect: typeof import('element-plus/es')['ElTimeSelect']
     ElTooltip: typeof import('element-plus/es')['ElTooltip']
     Highlight: typeof import('E:/HBuilderProjects/element-plus-admin/src/components/Highlight/index.vue')['default']
-    ParentView: typeof import('E:/HBuilderProjects/element-plus-admin/src/components/ParentView/index.vue')['default']
-    Preview: typeof import('E:/HBuilderProjects/element-plus-admin/src/components/Preview/index.vue')['default']
-    Qrcode: typeof import('E:/HBuilderProjects/element-plus-admin/src/components/Qrcode/index.vue')['default']
-    Redirect: typeof import('E:/HBuilderProjects/element-plus-admin/src/components/Redirect/index.vue')['default']
-    Search: typeof import('E:/HBuilderProjects/element-plus-admin/src/components/Search/index.vue')['default']
-    SvgIcon: typeof import('E:/HBuilderProjects/element-plus-admin/src/components/SvgIcon/index.vue')['default']
+    Loading: typeof import('element-plus/es')['ElLoadingDirective']
+    ParentView: typeof import('./src/components/ParentView/index.vue')['default']
+    Preview: typeof import('./src/components/Preview/index.vue')['default']
+    Qrcode: typeof import('./src/components/Qrcode/index.vue')['default']
+    Redirect: typeof import('./src/components/Redirect/index.vue')['default']
+    Search: typeof import('./src/components/Search/index.vue')['default']
+    SvgIcon: typeof import('./src/components/SvgIcon/index.vue')['default']
   }
 }
 

+ 9 - 9
package.json

@@ -10,7 +10,7 @@
     "build:dev": "vue-tsc --noEmit && vite build --mode dev",
     "build:test": "vue-tsc --noEmit && vite build --mode test",
     "serve": "vite preview",
-    "check": "npm-check-updates",
+    "check": "npx npm-check-updates",
     "clean": "npx rimraf docs/node_modules && npx rimraf node_modules",
     "clean:docs": "npx rimraf docs/node_modules",
     "clean:main": "npx rimraf node_modules",
@@ -25,12 +25,12 @@
   "dependencies": {
     "@element-plus/icons": "^0.0.11",
     "@vueuse/core": "^6.5.3",
-    "axios": "^0.22.0",
+    "axios": "^0.23.0",
     "clipboard": "^2.0.8",
     "echarts": "^5.2.1",
     "echarts-wordcloud": "^2.0.0",
-    "element-plus": "1.1.0-beta.20",
-    "highlight.js": "^11.2.0",
+    "element-plus": "1.1.0-beta.21",
+    "highlight.js": "^11.3.1",
     "intro.js": "^4.2.2",
     "lodash-es": "^4.17.21",
     "mockjs": "^1.1.0",
@@ -76,17 +76,17 @@
     "stylelint-config-prettier": "^8.0.2",
     "stylelint-config-standard": "^22.0.0",
     "stylelint-order": "^4.1.0",
-    "typescript": "^4.4.3",
-    "unplugin-element-plus": "^0.1.0",
-    "unplugin-vue-components": "^0.15.6",
-    "vite": "^2.6.4",
+    "typescript": "^4.4.4",
+    "unplugin-element-plus": "^0.1.3",
+    "unplugin-vue-components": "^0.16.0",
+    "vite": "^2.6.10",
     "vite-plugin-commonjs-externals": "^0.1.1",
     "vite-plugin-eslint": "^1.3.0",
     "vite-plugin-style-import": "^1.2.1",
     "vite-plugin-svg-icons": "^1.0.5",
     "vite-plugin-vue-setup-extend": "^0.1.0",
     "vue-eslint-parser": "^7.11.0",
-    "vue-tsc": "^0.3.0"
+    "vue-tsc": "^0.28.7"
   },
   "engines": {
     "node": ">= 14.0.0",

+ 141 - 0
src/components/Avatars/index.vue

@@ -0,0 +1,141 @@
+<template>
+  <div class="avatars-wrap">
+    <template v-if="tooltip">
+      <el-tooltip
+        v-for="(item, $index) in avatarsData"
+        :key="$index"
+        :content="item.text"
+        placement="top"
+      >
+        <div
+          :class="
+            showAvatar ? 'avatars-item-img' : ['avatars-item', `avatars-${item.type || 'default'}`]
+          "
+        >
+          <el-avatar v-if="showAvatar" :size="40" :src="item.url">
+            <img :src="defaultImg" />
+          </el-avatar>
+          <span v-else>{{ item.text.substr(0, 1) }}</span>
+        </div>
+      </el-tooltip>
+      <div v-if="max && data.length - max > 0" :class="['avatars-item', 'avatars-item-img']">
+        <span>+{{ data.length - max }}</span>
+      </div>
+    </template>
+    <template v-else>
+      <div
+        v-for="(item, $index) in avatarsData"
+        :key="$index"
+        :class="
+          showAvatar ? 'avatars-item-img' : ['avatars-item', `avatars-${item.type || 'default'}`]
+        "
+      >
+        <el-avatar v-if="showAvatar" :size="40" :src="item.url">
+          <img :src="defaultImg" />
+        </el-avatar>
+        <span v-else>{{ item.text.substr(0, 1) }}</span>
+      </div>
+      <div v-if="max && data.length - max > 0" :class="['avatars-item', 'avatars-item-img']">
+        <span>+{{ data.length - max }}</span>
+      </div>
+    </template>
+  </div>
+</template>
+
+<script setup lang="ts" name="Avatars">
+import { PropType, computed } from 'vue'
+import { deepClone } from '@/utils'
+import { AvatarConfig } from './types'
+import defaultImg from '@/assets/img/default-avatar.png'
+
+const props = defineProps({
+  // 展示的数据
+  data: {
+    type: Array as PropType<AvatarConfig[]>,
+    default: () => []
+  },
+  // 最大展示数量
+  max: {
+    type: Number as PropType<number>,
+    default: 0
+  },
+  // 是否使用头像
+  showAvatar: {
+    type: Boolean as PropType<boolean>,
+    default: false
+  },
+  // 是否显示完整名称
+  tooltip: {
+    type: Boolean as PropType<boolean>,
+    default: true
+  }
+})
+
+const avatarsData = computed(() => {
+  if (props.max) {
+    if (props.data.length <= props.max) {
+      return props.data
+    } else {
+      const data = deepClone(props.data).splice(0, props.max)
+      return data
+    }
+  } else {
+    return props.data
+  }
+})
+</script>
+
+<style lang="less" scoped>
+.avatars-wrap {
+  display: flex;
+
+  .avatars-item {
+    display: inline-block;
+    width: 40px;
+    height: 40px;
+    line-height: 40px;
+    color: #fff;
+    text-align: center;
+    background: #2d8cf0;
+    border: 1px solid #fff;
+    border-radius: 50%;
+  }
+
+  .avatars-item-img {
+    display: inline-block;
+    border-radius: 50%;
+
+    .el-avatar--circle {
+      border: 1px solid #fff;
+    }
+  }
+
+  .avatars-item-img + .avatars-item-img {
+    margin-left: -12px;
+  }
+
+  .avatars-item + .avatars-item {
+    margin-left: -12px;
+  }
+
+  .avatars-default {
+    color: #bae7ff;
+    background: #096dd9;
+  }
+
+  .avatars-success {
+    color: #f6ffed;
+    background: #52c41a;
+  }
+
+  .avatars-danger {
+    color: #fff1f0;
+    background: #f5222d;
+  }
+
+  .avatars-warning {
+    color: #fffbe6;
+    background: #faad14;
+  }
+}
+</style>

+ 5 - 0
src/components/Avatars/types.ts

@@ -0,0 +1,5 @@
+export interface AvatarConfig {
+  text: string
+  type?: string
+  url?: string
+}

+ 206 - 0
src/components/Detail/index.vue

@@ -0,0 +1,206 @@
+<template>
+  <div class="detail__wrap">
+    <div v-if="title" class="detail__wrap--header" @click="toggleClick">
+      <div class="detail__wrap--title">
+        <div>
+          {{ title }}
+          <el-tooltip v-if="message" :content="message" placement="right">
+            <i class="el-icon-warning-outline"></i>
+          </el-tooltip>
+        </div>
+      </div>
+      <i
+        v-if="collapsed"
+        :class="['el-icon-arrow-down', { 'el-icon-arrow-down-transform': !show }]"
+      ></i>
+    </div>
+    <el-collapse-transition>
+      <div v-show="show" class="detail__content" :style="contentStyleObj">
+        <el-row>
+          <el-col v-for="(item, $index) in schema" :key="$index" :span="item.span || 12">
+            <div class="detail__content--item" :class="{ 'detail__content--flex': !vertical }">
+              <div class="content__item--label" :style="labelStyleObj">
+                <slot :name="item.field" :row="item">
+                  {{ item.label }}
+                </slot>
+              </div>
+              <div class="content__item--message" :style="messageStyleObj">
+                <slot :name="`${item.field}Content`" :row="data">
+                  {{ data[item.field] }}
+                </slot>
+              </div>
+            </div>
+          </el-col>
+        </el-row>
+      </div>
+    </el-collapse-transition>
+  </div>
+</template>
+
+<script setup lang="ts" name="Detail">
+import { PropType, ref, computed } from 'vue'
+import { SchemaConfig } from './types'
+
+const props = defineProps({
+  // 详情标题
+  title: {
+    type: String as PropType<string>,
+    default: ''
+  },
+  // 是否可折叠
+  collapsed: {
+    type: Boolean as PropType<boolean>,
+    default: true
+  },
+  // 辅助提示
+  message: {
+    type: String as PropType<string>,
+    default: ''
+  },
+  // 是否需要边框
+  border: {
+    type: Boolean as PropType<boolean>,
+    default: true
+  },
+  // 需要展示的数据
+  data: {
+    type: Object as PropType<IObj>,
+    required: true
+  },
+  // 布局展示的数据
+  schema: {
+    type: Array as PropType<SchemaConfig[]>,
+    required: true
+  },
+  // 是否标题和内容各占一行 垂直布局
+  vertical: {
+    type: Boolean as PropType<boolean>,
+    default: false
+  },
+  // 标题宽度
+  labelWidth: {
+    type: String as PropType<string>,
+    default: '150px'
+  },
+  // 标题位置
+  labelAlign: {
+    type: String as PropType<string>,
+    default: 'left'
+  },
+  // 边框颜色
+  borderColor: {
+    type: String as PropType<string>,
+    default: '#f0f0f0'
+  },
+  // 标题背景颜色
+  labelBg: {
+    type: String as PropType<string>,
+    default: '#fafafa'
+  },
+  classic: {
+    type: Boolean as PropType<boolean>,
+    default: false
+  }
+})
+
+const show = ref<boolean>(true)
+const contentStyleObj = computed(() => {
+  return {
+    borderTop: props.border ? `1px solid ${props.borderColor}` : '',
+    borderLeft: props.border ? `1px solid ${props.borderColor}` : ''
+  }
+})
+const labelStyleObj = computed((): any => {
+  return {
+    width: props.vertical ? `100%` : props.labelWidth,
+    textAlign: props.labelAlign,
+    backgroundColor: props.border && !props.classic ? props.labelBg : '',
+    borderRight: props.border && !props.classic ? `1px solid ${props.borderColor}` : '',
+    borderBottom: props.border && !props.classic ? `1px solid ${props.borderColor}` : ''
+  }
+})
+const messageStyleObj = computed(() => {
+  return {
+    width: props.vertical ? `100%` : `calc(100% - ${props.labelWidth})`,
+    borderRight: props.border && !props.classic ? `1px solid ${props.borderColor}` : '',
+    borderBottom: props.border && !props.classic ? `1px solid ${props.borderColor}` : ''
+  }
+})
+
+function toggleClick() {
+  if (props.collapsed) {
+    show.value = !show.value
+  }
+}
+</script>
+
+<style lang="less" scoped>
+.detail__wrap {
+  padding: 10px;
+  background: #fff;
+  border-radius: 2px;
+
+  .detail__wrap--header {
+    display: flex;
+    height: 32px;
+    margin-bottom: 10px;
+    justify-content: space-between;
+    align-items: center;
+    // cursor: pointer;
+    .detail__wrap--title {
+      position: relative;
+      display: inline-block;
+      margin-left: 10px;
+      font-family: MicrosoftYaHei-Bold;
+      font-size: 18px;
+      font-weight: 700;
+      color: rgba(0, 0, 0, 0.85);
+
+      &::after {
+        position: absolute;
+        top: 1px;
+        left: -10px;
+        width: 4px;
+        height: 90%;
+        background: var(--main-color);
+        content: '';
+      }
+    }
+
+    .el-icon-arrow-down {
+      transition: all 0.2s;
+    }
+
+    .el-icon-arrow-down-transform {
+      transform: rotate(-180deg);
+    }
+  }
+
+  .detail__content {
+    :deep(.el-row) {
+      flex-wrap: wrap;
+    }
+
+    .detail__content--flex {
+      display: flex;
+      height: 100%;
+    }
+
+    .content__item--label {
+      padding: 8px 16px;
+      font-size: 14px;
+      line-height: 20px;
+      color: #918e8d;
+    }
+
+    .content__item--message {
+      padding: 8px 16px;
+      flex: 1;
+      font-size: 14px;
+      line-height: 20px;
+      color: #606266;
+      overflow-wrap: break-word;
+    }
+  }
+}
+</style>

+ 5 - 0
src/components/Detail/types.ts

@@ -0,0 +1,5 @@
+export interface SchemaConfig {
+  field: string // 字段名
+  label?: string // label名
+  span?: number // 列的数量
+}

+ 2 - 0
src/components/index.ts

@@ -2,9 +2,11 @@ import type { App } from 'vue'
 import SvgIcon from './SvgIcon/index.vue' // svg组件
 import ComSearch from './Search/index.vue' // search组件
 import ComDialog from './Dialog/index.vue' // dialog组件
+import ComDetail from './Detail/index.vue' // detail组件
 
 export function setupGlobCom(app: App<Element>): void {
   app.component('SvgIcon', SvgIcon)
   app.component('ComSearch', ComSearch)
   app.component('ComDialog', ComDialog)
+  app.component('ComDetail', ComDetail)
 }

+ 2 - 2
src/main.ts

@@ -10,7 +10,7 @@ import { setupDirectives } from '@/directives' // 自定义指令
 
 import { setupGlobCom } from './components'
 
-import { setupElement } from '@/plugins/element-plus'
+// import { setupElement } from '@/plugins/element-plus'
 
 import '@/styles/index.less'
 
@@ -29,7 +29,7 @@ setupRouter(app) // 引入路由
 
 setupDirectives(app)
 
-setupElement(app)
+// setupElement(app)
 
 setupGlobCom(app) // 引入全局组件
 

+ 16 - 16
src/router/index.ts

@@ -185,14 +185,14 @@ export const asyncRouterMap: AppRouteRecordRaw[] = [
           title: '弹窗'
         }
       },
-      // {
-      //   path: 'detail',
-      //   component: () => import('_v/components-demo/detail/index.vue'),
-      //   name: 'DetailDemo',
-      //   meta: {
-      //     title: '详情组件'
-      //   }
-      // },
+      {
+        path: 'detail',
+        component: () => import('_v/components-demo/detail/index.vue'),
+        name: 'DetailDemo',
+        meta: {
+          title: '详情'
+        }
+      },
       {
         path: 'qrcode',
         component: () => import('_v/components-demo/qrcode/index.vue'),
@@ -201,14 +201,14 @@ export const asyncRouterMap: AppRouteRecordRaw[] = [
           title: '二维码'
         }
       },
-      // {
-      //   path: 'avatars',
-      //   component: () => import('_v/components-demo/avatars/index.vue'),
-      //   name: 'AvatarsDemo',
-      //   meta: {
-      //     title: '头像组'
-      //   }
-      // },
+      {
+        path: 'avatars',
+        component: () => import('_v/components-demo/avatars/index.vue'),
+        name: 'AvatarsDemo',
+        meta: {
+          title: '头像组'
+        }
+      },
       {
         path: 'highlight',
         component: () => import('_v/components-demo/highlight/index.vue'),

+ 84 - 0
src/views/components-demo/avatars/index.vue

@@ -0,0 +1,84 @@
+<template>
+  <div>
+    <el-alert
+      effect="dark"
+      :closable="false"
+      title="头像组组件 -- 基础用法"
+      type="info"
+      style="margin-bottom: 20px"
+    />
+    <avatars :data="data" />
+
+    <el-alert
+      effect="dark"
+      :closable="false"
+      title="头像组组件 -- 不显示tooltip"
+      type="info"
+      style="margin-top: 20px; margin-bottom: 20px"
+    />
+    <avatars :data="data" :tooltip="false" />
+
+    <el-alert
+      effect="dark"
+      :closable="false"
+      title="头像组组件 -- 最多展示5"
+      type="info"
+      style="margin-top: 20px; margin-bottom: 20px"
+    />
+    <avatars :data="data" :max="5" />
+
+    <el-alert
+      effect="dark"
+      :closable="false"
+      title="头像组组件 -- 展示头像"
+      type="info"
+      style="margin-top: 20px; margin-bottom: 20px"
+    />
+    <avatars show-avatar :data="data1" />
+  </div>
+</template>
+
+<script setup lang="ts" name="AvatarsDemo">
+import { ref } from 'vue'
+import { AvatarConfig } from '_c/Avatars/types'
+import Avatars from '_c/Avatars/index.vue'
+
+const data = ref<AvatarConfig[]>([
+  { text: '陈某某' },
+  { text: '李某某', type: 'success' },
+  { text: '张某某', type: 'danger' },
+  { text: '王某某', type: 'warning' },
+  { text: '龙某某' },
+  { text: '孙某某' },
+  { text: '刘某某' },
+  { text: '赵某某' }
+])
+const data1 = ref<AvatarConfig[]>([
+  {
+    text: '陈某某',
+    url: 'https://dss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=2863969516,2611770076&fm=26&gp=0.jpg'
+  },
+  {
+    text: '李某某',
+    url: 'https://dss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=465970198,3877503753&fm=26&gp=0.jpg'
+  },
+  {
+    text: '张某某',
+    url: 'https://dss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=1857202600,3614139084&fm=26&gp=0.jpg'
+  },
+  {
+    text: '王某某',
+    url: 'https://dss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=1444080181,4150129244&fm=26&gp=0.jpg'
+  },
+  {
+    text: '龙某某',
+    url: 'https://dss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=2469786567,2163872639&fm=26&gp=0.jpg'
+  },
+  {
+    text: '孙某某',
+    url: 'https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=4119236579,869456058&fm=26&gp=0.jpg'
+  },
+  { text: '刘某某', url: 'xxxxx' },
+  { text: '赵某某' }
+])
+</script>

+ 217 - 0
src/views/components-demo/detail/index.vue

@@ -0,0 +1,217 @@
+<template>
+  <div>
+    <el-alert
+      effect="dark"
+      :closable="false"
+      title="详情组件。"
+      type="info"
+      style="margin-bottom: 20px"
+    />
+
+    <com-detail :data="data" :schema="schema" title="基础示例" message="辅助文字" />
+
+    <com-detail
+      title="不可折叠"
+      :data="data"
+      :schema="schema"
+      :collapsed="false"
+      message="辅助文字"
+      style="margin-top: 20px"
+    />
+
+    <com-detail title="没有辅助文字" :data="data" :schema="schema" style="margin-top: 20px" />
+
+    <com-detail
+      title="没有边框"
+      :data="data"
+      :schema="schema"
+      :border="false"
+      style="margin-top: 20px"
+    />
+
+    <com-detail
+      title="垂直布局"
+      :data="data"
+      :vertical="true"
+      :schema="schema"
+      style="margin-top: 20px"
+    />
+
+    <el-form
+      ref="formRef"
+      :hide-required-asterisk="true"
+      :model="form"
+      :rules="rules"
+      style="margin-top: 20px"
+    >
+      <com-detail title="与表单结合并自定义插槽" :data="form" :schema="fromSchema">
+        <template #title="scope">
+          <span class="is-required-item">{{ scope.row.label }}</span>
+        </template>
+        <template #titleContent>
+          <el-form-item prop="title">
+            <el-input v-model="form.title" placeholder="请输入标题" />
+          </el-form-item>
+        </template>
+
+        <template #author="scope">
+          <span class="is-required-item">{{ scope.row.label }}</span>
+        </template>
+        <template #authorContent>
+          <el-form-item prop="author">
+            <el-input v-model="form.author" placeholder="请输入作者" />
+          </el-form-item>
+        </template>
+
+        <template #display_time="scope">
+          <span class="is-required-item">{{ scope.row.label }}</span>
+        </template>
+        <template #display_timeContent>
+          <el-form-item prop="display_time">
+            <el-date-picker
+              v-model="form.display_time"
+              type="datetime"
+              placeholder="请选择创建时间"
+              style="width: 100%"
+            />
+          </el-form-item>
+        </template>
+
+        <template #importance="scope">
+          <span class="is-required-item">{{ scope.row.label }}</span>
+        </template>
+        <template #importanceContent>
+          <el-form-item prop="importance">
+            <el-select v-model="form.importance" placeholder="请选择重要性" style="width: 100%">
+              <el-option label="重要" value="3" />
+              <el-option label="良好" value="2" />
+              <el-option label="一般" value="1" />
+            </el-select>
+          </el-form-item>
+        </template>
+
+        <template #pageviews="scope">
+          <span class="is-required-item">{{ scope.row.label }}</span>
+        </template>
+        <template #pageviewsContent>
+          <el-form-item prop="pageviews">
+            <el-input-number
+              v-model="form.pageviews"
+              :min="0"
+              :max="99999999"
+              style="width: 100%"
+            />
+          </el-form-item>
+        </template>
+      </com-detail>
+      <div style="margin-top: 15px; text-align: center">
+        <el-button type="primary" @click="saveData">保存(控制台查看数据)</el-button>
+      </div>
+    </el-form>
+  </div>
+</template>
+
+<script setup lang="ts" name="DetailDemo">
+import { reactive, ref, unref } from 'vue'
+
+const formRef = ref<Nullable<any>>(null)
+
+const requiredRule: {
+  required: boolean
+  message: string
+} = {
+  required: true,
+  message: '该项为必填项'
+}
+
+const data = reactive<IObj>({
+  username: 'chenkl',
+  nickName: '梦似花落。',
+  age: 26,
+  phone: '13655971xxxx',
+  email: '502431556@qq.com',
+  addr: '这是一个很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长很长的地址',
+  sex: '男',
+  certy: '35058319940712xxxx'
+})
+
+const schema = reactive<IObj[]>([
+  {
+    field: 'username',
+    label: '用户名'
+  },
+  {
+    field: 'nickName',
+    label: '昵称'
+  },
+  {
+    field: 'phone',
+    label: '联系电话'
+  },
+  {
+    field: 'email',
+    label: '邮箱'
+  },
+  {
+    field: 'addr',
+    label: '地址',
+    span: 24
+  }
+])
+
+const fromSchema = reactive<IObj[]>([
+  {
+    field: 'title',
+    label: '标题',
+    span: 24
+  },
+  {
+    field: 'author',
+    label: '作者'
+  },
+  {
+    field: 'display_time',
+    label: '创建时间'
+  },
+  {
+    field: 'importance',
+    label: '重要性'
+  },
+  {
+    field: 'pageviews',
+    label: '阅读数'
+  }
+])
+
+const form = reactive<IObj>({
+  id: '', // id
+  author: '', // 作者
+  title: '', // 标题
+  importance: '', // 重要性
+  display_time: '', // 创建时间
+  pageviews: 0 // 阅读数
+})
+
+const rules = reactive<IObj>({
+  title: [requiredRule],
+  author: [requiredRule],
+  importance: [requiredRule],
+  display_time: [requiredRule],
+  pageviews: [requiredRule]
+})
+
+function saveData() {
+  try {
+    ;(unref(formRef) as any).validate((valid) => {
+      if (valid) {
+        console.log(form)
+      } else {
+        console.log('error submit!!')
+        return false
+      }
+    })
+  } catch (err) {
+    console.log(err)
+  }
+}
+</script>

+ 126 - 110
yarn.lock

@@ -1075,52 +1075,52 @@
   resolved "https://registry.yarnpkg.com/@vitejs/plugin-vue/-/plugin-vue-1.9.3.tgz#93d61893ce6c723d0209af0483ec8b91a2cd811f"
   integrity sha512-yW6H/q+4Mc2PcVjSOelcsMrg/k15DnMUz8jyCFsI04emc3aLwo4AoofUfGnjHUkgirrDxSJLVqQVGhonQ3yykA==
 
-"@volar/code-gen@^0.27.24":
-  version "0.27.24"
-  resolved "https://registry.yarnpkg.com/@volar/code-gen/-/code-gen-0.27.24.tgz#ccdbe858951c1ee4e0c3979232d52412dc46756a"
-  integrity sha512-s4j/QqOZUW03PeD6LmVYI00Q1C3CfJEOePDOQwDvCTUov4lFk0iSBtFyYhjlLyQ1pdtV1+TDTErkj2aMQtc4PA==
+"@volar/code-gen@0.28.7":
+  version "0.28.7"
+  resolved "https://registry.yarnpkg.com/@volar/code-gen/-/code-gen-0.28.7.tgz#8b4108b59cdae987c71378a6f91dc35ac07b5dbe"
+  integrity sha512-cprWUzpGVCPsBpTKVUhfHEYpJBsjLYe/quvtU+PLAsXS7EcxSG+jMPNXWUyB6IhBcW5hrgMhIYfuWzhOvEESxQ==
   dependencies:
-    "@volar/shared" "^0.27.24"
-    "@volar/source-map" "^0.27.24"
+    "@volar/shared" "0.28.7"
+    "@volar/source-map" "0.28.7"
 
-"@volar/html2pug@^0.27.13":
-  version "0.27.13"
-  resolved "https://registry.yarnpkg.com/@volar/html2pug/-/html2pug-0.27.13.tgz#48dfa73ecf1ef1955a02a046d0c88845950fac85"
-  integrity sha512-3NYgNA5F3PDsKbbpOrVdGy2S7ZYmZIbFmbp1A/27DDzjj/uIC9Pj7HXVvbYOzi8HcOxUPt0BMrh4TVzBUaCFww==
+"@volar/html2pug@0.28.7":
+  version "0.28.7"
+  resolved "https://registry.yarnpkg.com/@volar/html2pug/-/html2pug-0.28.7.tgz#a8e359d6e6e574386ed6ac23b89c46658d91750b"
+  integrity sha512-HdxZYKVJJv3lRJfOB1sbyAdqyowVRMbvQtCejcvqEvAjaU7PYJLd974RMKf9eSpalFXtnRwXRZKKlNz18jicsQ==
   dependencies:
     domelementtype "^2.2.0"
-    domhandler "^4.2.0"
-    htmlparser2 "^6.1.0"
+    domhandler "^4.2.2"
+    htmlparser2 "^7.1.2"
     pug "^3.0.2"
 
-"@volar/shared@^0.27.24":
-  version "0.27.24"
-  resolved "https://registry.yarnpkg.com/@volar/shared/-/shared-0.27.24.tgz#a33457ec8ac0b0d367ed54c9e21913a5f8c2d6c2"
-  integrity sha512-Mi8a4GQaiorfb+o4EqOXDZm9E/uBJXgScFgF+NhtcMBOUKHNMKQyLI7YRGumtyJTTdaX7nSDJjGGTkv23tcOtQ==
+"@volar/shared@0.28.7":
+  version "0.28.7"
+  resolved "https://registry.yarnpkg.com/@volar/shared/-/shared-0.28.7.tgz#8b6804a6298f0ffca6fd311cfa4aa14cc1105874"
+  integrity sha512-binrWo2vjrQhUSBc7f/cn3Jq/qTLz+2kc13R+htWPxEBXPHcAqOspkOzLN9J3jQ4q4TA4kK1ZiSKGdIz4e41Tg==
   dependencies:
     upath "^2.0.1"
     vscode-jsonrpc "^8.0.0-next.2"
     vscode-uri "^3.0.2"
 
-"@volar/source-map@^0.27.24":
-  version "0.27.24"
-  resolved "https://registry.yarnpkg.com/@volar/source-map/-/source-map-0.27.24.tgz#60f2e070c169be82cbf7ffa296a30c2823c5205f"
-  integrity sha512-2I5a7cXqekZ66D6lHep7ttJgvVVtPEBUIe1hnpcGbnXWNA2ya6f6jKNNyTmrXQyfkh32IEuaUd4kocR+3AKMag==
+"@volar/source-map@0.28.7":
+  version "0.28.7"
+  resolved "https://registry.yarnpkg.com/@volar/source-map/-/source-map-0.28.7.tgz#73980c89aec2dd360b20d0e2fb46dfe1b2f76250"
+  integrity sha512-cjF0Em5MXtG687eenrURqJMNE6sN/MQzUtrrCsEp+bvP7Eaje0ugdhV9IZo0Q3aufbhtyUU7MOezptvhEiP+YA==
   dependencies:
-    "@volar/shared" "^0.27.24"
+    "@volar/shared" "0.28.7"
 
-"@volar/transforms@^0.27.24":
-  version "0.27.24"
-  resolved "https://registry.yarnpkg.com/@volar/transforms/-/transforms-0.27.24.tgz#68ebc53dca2e36884e247c0866ec3d24ed815784"
-  integrity sha512-sOHi1ZSapFlxn7yPl4MO5TXd9aWC0BVq2CgXAJ2EESb+ddh2uJbGQgLLNocX+MDh419cUuuFT2QAJpuWHhJcng==
+"@volar/transforms@0.28.7":
+  version "0.28.7"
+  resolved "https://registry.yarnpkg.com/@volar/transforms/-/transforms-0.28.7.tgz#a31464e8f53f365bb16fab34c2b629a26c6ea360"
+  integrity sha512-0quLXRC8rxHb/Ptmp8qr730cE8gCGZrJuoDEQ1+XE0IKGyF+jhvqJsdjh5JL8vdBQbkV5Vpo7pSo5mwUPAarSQ==
   dependencies:
-    "@volar/shared" "^0.27.24"
+    "@volar/shared" "0.28.7"
     vscode-languageserver "^8.0.0-next.2"
 
-"@vscode/emmet-helper@^2.7.0":
-  version "2.8.1"
-  resolved "https://registry.yarnpkg.com/@vscode/emmet-helper/-/emmet-helper-2.8.1.tgz#843c9a5704d72d6f3a30c76b22b518391029d508"
-  integrity sha512-4aVKk7sjtNPLKqVq5Td1EgtB+4kE/enExA4RUpYmVVKawqusRemZ+LzzzBxxnHRTOrIBermY8kXQsqjutDPyYQ==
+"@vscode/emmet-helper@^2.8.0":
+  version "2.8.2"
+  resolved "https://registry.yarnpkg.com/@vscode/emmet-helper/-/emmet-helper-2.8.2.tgz#9b2ce4fdd62cf3fda45cf8af67c012cfce55edc9"
+  integrity sha512-A/+pkBYQq2JTow1A2flfTmEOmiF780KpdkoX7VBjQ7wujeA+CFUPd17YdeIa9aim20+J5Jp7SFujPDwVFiQucQ==
   dependencies:
     emmet "^2.3.0"
     jsonc-parser "^2.3.0"
@@ -1159,7 +1159,7 @@
     estree-walker "^2.0.2"
     source-map "^0.6.1"
 
-"@vue/compiler-dom@3.2.20", "@vue/compiler-dom@^3.2.19":
+"@vue/compiler-dom@3.2.20", "@vue/compiler-dom@^3.2.20":
   version "3.2.20"
   resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.2.20.tgz#8e0ef354449c0faf41519b00bfc2045eae01dcb5"
   integrity sha512-QnI77ec/JtV7R0YBbcVayYTDCRcI9OCbxiUQK6izVyqQO0658n0zQuoNwe+bYgtqnvGAIqTR3FShTd5y4oOjdg==
@@ -1196,7 +1196,7 @@
   resolved "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.0.0-beta.19.tgz#f8e88059daa424515992426a0c7ea5cde07e99bf"
   integrity sha512-ObzQhgkoVeoyKv+e8+tB/jQBL2smtk/NmC9OmFK8UqdDpoOdv/Kf9pyDWL+IFyM7qLD2C75rszJujvGSPSpGlw==
 
-"@vue/reactivity@3.2.20", "@vue/reactivity@^3.2.19":
+"@vue/reactivity@3.2.20", "@vue/reactivity@^3.2.20":
   version "3.2.20"
   resolved "https://registry.yarnpkg.com/@vue/reactivity/-/reactivity-3.2.20.tgz#81fe1c368e7f20bc0ec1dec1045bbee253582de8"
   integrity sha512-nSmoLojUTk+H8HNTAkrUduB4+yIUBK2HPihJo2uXVSH4Spry6oqN6lFzE5zpLK+F27Sja+UqR9R1+/kIOsHV5w==
@@ -1239,7 +1239,7 @@
     "@vue/compiler-ssr" "3.2.20"
     "@vue/shared" "3.2.20"
 
-"@vue/shared@3.2.20", "@vue/shared@^3.2.19":
+"@vue/shared@3.2.20", "@vue/shared@^3.2.20":
   version "3.2.20"
   resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.2.20.tgz#53746961f731a8ea666e3316271e944238dc31db"
   integrity sha512-FbpX+hD5BvXCQerEYO7jtAGHlhAkhTQ4KIV73kmLWNlawWhTiVuQxizgVb0BOkX5oG9cIRZ42EG++d/k/Efp0w==
@@ -1536,10 +1536,10 @@ autoprefixer@^9.8.6:
     postcss "^7.0.32"
     postcss-value-parser "^4.1.0"
 
-axios@^0.22.0:
-  version "0.22.0"
-  resolved "https://registry.npmjs.org/axios/-/axios-0.22.0.tgz#bf702c41fb50fbca4539589d839a077117b79b25"
-  integrity sha512-Z0U3uhqQeg1oNcihswf4ZD57O3NrR1+ZXhxaROaWpDmsDTx7T2HNBV2ulBtie2hwJptu8UvgnJoK+BIqdzh/1w==
+axios@^0.23.0:
+  version "0.23.0"
+  resolved "https://registry.yarnpkg.com/axios/-/axios-0.23.0.tgz#b0fa5d0948a8d1d75e3d5635238b6c4625b05149"
+  integrity sha512-NmvAE4i0YAv5cKq8zlDoPd1VLKAqX5oLuZKs8xkJa4qi6RGn0uhCYFjWtHHC9EM/MwOwYWOs53W+V0aqEXq1sg==
   dependencies:
     follow-redirects "^1.14.4"
 
@@ -2504,7 +2504,7 @@ domhandler@^2.3.0:
   dependencies:
     domelementtype "1"
 
-domhandler@^4.0.0, domhandler@^4.2.0:
+domhandler@^4.2.0, domhandler@^4.2.2:
   version "4.2.2"
   resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.2.2.tgz#e825d721d19a86b8c201a35264e226c678ee755f"
   integrity sha512-PzE9aBMsdZO8TK4BnuJwH0QT41wgMbRzuZrHUcpYncEjmQazq8QEaBWgLG7ZyC/DAZKEgglpIA6j4Qn/HmxS3w==
@@ -2519,7 +2519,7 @@ domutils@^1.5.1:
     dom-serializer "0"
     domelementtype "1"
 
-domutils@^2.5.2, domutils@^2.6.0:
+domutils@^2.6.0, domutils@^2.8.0:
   version "2.8.0"
   resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135"
   integrity sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==
@@ -2561,11 +2561,12 @@ electron-to-chromium@^1.3.857:
   resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.864.tgz#6a993bcc196a2b8b3df84d28d5d4dd912393885f"
   integrity sha512-v4rbad8GO6/yVI92WOeU9Wgxc4NA0n4f6P1FvZTY+jyY7JHEhw3bduYu60v3Q1h81Cg6eo4ApZrFPuycwd5hGw==
 
-element-plus@1.1.0-beta.20:
-  version "1.1.0-beta.20"
-  resolved "https://registry.yarnpkg.com/element-plus/-/element-plus-1.1.0-beta.20.tgz#59523c99a88ca4881d899ba8bb81c4a9273ed822"
-  integrity sha512-5rBrLzfKGz4urSxqKi1tihylyotSswMCKdXpCAJAfRggMjtS1NfqVtrCYEPdjphmP2JHsj8TisDvbRTScRKF0Q==
+element-plus@1.1.0-beta.21:
+  version "1.1.0-beta.21"
+  resolved "https://registry.yarnpkg.com/element-plus/-/element-plus-1.1.0-beta.21.tgz#4b0232b908d1defee81ef94913c9479342d9d7e6"
+  integrity sha512-QaAX909KgFufXkIKAwXrdHRmv1e+jIyc1SlN90mg9HBE09MnInGUXy0qdYZhVoMgBFyStMkiSIz7XLG8m0ac8A==
   dependencies:
+    "@element-plus/icons" "^0.0.11"
     "@popperjs/core" "^2.10.1"
     "@vueuse/core" "~6.1.0"
     async-validator "^4.0.3"
@@ -2627,6 +2628,11 @@ entities@^2.0.0:
   resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55"
   integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==
 
+entities@^3.0.1:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/entities/-/entities-3.0.1.tgz#2b887ca62585e96db3903482d336c1006c3001d4"
+  integrity sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==
+
 errno@^0.1.1:
   version "0.1.8"
   resolved "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz#8bb3e9c7d463be4976ff888f76b4809ebc2e811f"
@@ -2651,6 +2657,11 @@ es-module-lexer@^0.7.1:
   resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.7.1.tgz#c2c8e0f46f2df06274cdaf0dd3f3b33e0a0b267d"
   integrity sha512-MgtWFl5No+4S3TmhDmCz2ObFGm6lEpTnzbQi+Dd+pw4mlTIZTmM2iAs5gRlmx5zS9luzobCSBSI90JM/1/JgOw==
 
+es-module-lexer@^0.9.3:
+  version "0.9.3"
+  resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.9.3.tgz#6f13db00cc38417137daf74366f535c8eb438f19"
+  integrity sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==
+
 esbuild-android-arm64@0.13.4:
   version "0.13.4"
   resolved "https://registry.yarnpkg.com/esbuild-android-arm64/-/esbuild-android-arm64-0.13.4.tgz#5178a20d2b7aba741a31c19609f9e67b346996b9"
@@ -3564,10 +3575,10 @@ header-case@^2.0.4:
     capital-case "^1.0.4"
     tslib "^2.0.3"
 
-highlight.js@^11.2.0:
-  version "11.2.0"
-  resolved "https://registry.nlark.com/highlight.js/download/highlight.js-11.2.0.tgz#a7e3b8c1fdc4f0538b93b2dc2ddd53a40c6ab0f0"
-  integrity sha1-p+O4wf3E8FOLk7LcLd1TpAxqsPA=
+highlight.js@^11.3.1:
+  version "11.3.1"
+  resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-11.3.1.tgz#813078ef3aa519c61700f84fe9047231c5dc3291"
+  integrity sha512-PUhCRnPjLtiLHZAQ5A/Dt5F8cWZeMyj9KRsACsWT+OD6OP0x6dp5OmT5jdx0JgEyPxPZZIPQpRN2TciUT7occw==
 
 homedir-polyfill@^1.0.1:
   version "1.0.3"
@@ -3617,15 +3628,15 @@ htmlparser2@^3.10.0, htmlparser2@^3.8.3:
     inherits "^2.0.1"
     readable-stream "^3.1.1"
 
-htmlparser2@^6.1.0:
-  version "6.1.0"
-  resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-6.1.0.tgz#c4d762b6c3371a05dbe65e94ae43a9f845fb8fb7"
-  integrity sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==
+htmlparser2@^7.1.2:
+  version "7.1.2"
+  resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-7.1.2.tgz#587923d38f03bc89e03076e00cba2c7473f37f7c"
+  integrity sha512-d6cqsbJba2nRdg8WW2okyD4ceonFHn9jLFxhwlNcLhQWcFPdxXeJulgOLjLKtAK9T6ahd+GQNZwG9fjmGW7lyg==
   dependencies:
     domelementtype "^2.0.1"
-    domhandler "^4.0.0"
-    domutils "^2.5.2"
-    entities "^2.0.0"
+    domhandler "^4.2.2"
+    domutils "^2.8.0"
+    entities "^3.0.1"
 
 http-proxy-agent@^4.0.1:
   version "4.0.1"
@@ -7024,6 +7035,11 @@ typescript@^4.4.3:
   resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.4.3.tgz#bdc5407caa2b109efd4f82fe130656f977a29324"
   integrity sha512-4xfscpisVgqqDfPaJo5vkd+Qd/ItkoagnHpufr+i2QCHBsNYp+G7UAoyFl8aPtx879u38wPV65rZ8qbGZijalA==
 
+typescript@^4.4.4:
+  version "4.4.4"
+  resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.4.4.tgz#2cd01a1a1f160704d3101fd5a58ff0f9fcb8030c"
+  integrity sha512-DqGhF5IKoBl8WNf8C1gu8q0xZSInh9j1kJJMqT3a94w1JzVaBU4EXOSMrz9yDqMT0xt3selp83fuFMQ0uzv6qA==
+
 unified@^9.1.0:
   version "9.2.2"
   resolved "https://registry.npmjs.org/unified/-/unified-9.2.2.tgz#67649a1abfc3ab85d2969502902775eb03146975"
@@ -7075,20 +7091,20 @@ universalify@^2.0.0:
   resolved "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717"
   integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==
 
-unplugin-element-plus@^0.1.0:
-  version "0.1.0"
-  resolved "https://registry.yarnpkg.com/unplugin-element-plus/-/unplugin-element-plus-0.1.0.tgz#eb68721f152a79ebe39a7404cc60cfcd6a8e587b"
-  integrity sha512-DdNgXlZtarpU6dGzh8WIP5bxLSIWg1qPKHnGvlqOY+RGlljyxe3yULPo6HMAzovdxy+ix4kAijncZSEud72khA==
+unplugin-element-plus@^0.1.3:
+  version "0.1.3"
+  resolved "https://registry.yarnpkg.com/unplugin-element-plus/-/unplugin-element-plus-0.1.3.tgz#3fefadef8a2a965ff3a2846beae6ae651f194fee"
+  integrity sha512-6GO1tuDIXcoYFkbL26Mrd84oUOgAHShcwn/xma5bwmBN2O0N0s13RbBDsK53vm4hxRKIVuFSSr659BkpmXWm2w==
   dependencies:
-    "@rollup/pluginutils" "^4.1.0"
-    es-module-lexer "^0.7.1"
+    "@rollup/pluginutils" "^4.1.1"
+    es-module-lexer "^0.9.3"
     magic-string "^0.25.7"
-    unplugin "^0.2.7"
+    unplugin "^0.2.16"
 
-unplugin-vue-components@^0.15.6:
-  version "0.15.6"
-  resolved "https://registry.yarnpkg.com/unplugin-vue-components/-/unplugin-vue-components-0.15.6.tgz#cd4e06e507c9dd7b6469e345b6812b3843e86d63"
-  integrity sha512-Prl+qtWtDwnxSYJckGn+WvrXElhEnjN9bJyi9D7d0mJcsspuFBlxRQEzAUnDvlr0CvuIkBZBVdXLu1oDTESjhg==
+unplugin-vue-components@^0.16.0:
+  version "0.16.0"
+  resolved "https://registry.yarnpkg.com/unplugin-vue-components/-/unplugin-vue-components-0.16.0.tgz#15a5d5d03ad658ae0202523811ec76150776569d"
+  integrity sha512-BM/5p6/btLgDjUxf290cKbzbaGow95NFibhp+TSQhL0wyb1Q6sP0nmlqOvGnpLANFq0+urXxXDloMLlTJH6Fww==
   dependencies:
     "@antfu/utils" "^0.3.0"
     "@rollup/pluginutils" "^4.1.1"
@@ -7101,7 +7117,7 @@ unplugin-vue-components@^0.15.6:
     resolve "^1.20.0"
     unplugin "^0.2.13"
 
-unplugin@^0.2.13, unplugin@^0.2.7:
+unplugin@^0.2.13, unplugin@^0.2.16:
   version "0.2.16"
   resolved "https://registry.yarnpkg.com/unplugin/-/unplugin-0.2.16.tgz#6f34e9f5068ca3ec92a36b016f47b5ad8bb875ca"
   integrity sha512-KkXatHba0baJszSHW+2e8EQU/5Bz7rYwzYXu8wUeq97tE6K3wvub+7OWSuRv04LttvzNLsJ2jXEyR35gofv74Q==
@@ -7252,10 +7268,10 @@ vite-plugin-vue-setup-extend@^0.1.0:
     "@vue/compiler-sfc" "^3.2.6"
     magic-string "^0.25.7"
 
-vite@^2.6.4:
-  version "2.6.5"
-  resolved "https://registry.yarnpkg.com/vite/-/vite-2.6.5.tgz#c4d25972e2f7371e682da86828722ddf5126f3d1"
-  integrity sha512-vavXMChDUb4Oh4YunrK9BrH5Ox74cu0eOp0VuyI/iqFz1FqbWD72So2c9I87lLL2n0+6tFPV5ijow60KrtxuZg==
+vite@^2.6.10:
+  version "2.6.10"
+  resolved "https://registry.yarnpkg.com/vite/-/vite-2.6.10.tgz#7a4f420c6e2c7d9062c7f9ce4578a817c72b3842"
+  integrity sha512-XbevwpDJMs3lKiGEj0UQScsOCpwHIjFgfzPnFVkPgnxsF9oPv1uGyckLg58XkXv6LnO46KN9yZqJzINFmAxtUg==
   dependencies:
     esbuild "^0.13.2"
     postcss "^8.3.8"
@@ -7269,7 +7285,7 @@ void-elements@^3.1.0:
   resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-3.1.0.tgz#614f7fbf8d801f0bb5f0661f5b2f5785750e4f09"
   integrity sha1-YU9/v42AHwu18GYfWy9XhXUOTwk=
 
-vscode-css-languageservice@^5.1.4:
+vscode-css-languageservice@^5.1.7:
   version "5.1.7"
   resolved "https://registry.yarnpkg.com/vscode-css-languageservice/-/vscode-css-languageservice-5.1.7.tgz#ebbf803b03fde539bd683588cd2da6c4a61b90e2"
   integrity sha512-h4oafcZaGFe2VtbNIlkZDmLEP0GQha3E5Ct2YMH4p/p9xYC8yWDNQ5CD+VF3UnSijKPSKmA+oc4cKjhJBowGKw==
@@ -7279,7 +7295,7 @@ vscode-css-languageservice@^5.1.4:
     vscode-nls "^5.0.0"
     vscode-uri "^3.0.2"
 
-vscode-html-languageservice@^4.0.7:
+vscode-html-languageservice@^4.1.0:
   version "4.1.0"
   resolved "https://registry.yarnpkg.com/vscode-html-languageservice/-/vscode-html-languageservice-4.1.0.tgz#e1662f1ff3b623b910c54d3f4a2aad8f397e53d7"
   integrity sha512-QQrEKfpfbeglD8Jcai4fQDQ7vOJrN6LyiOs47Y6qAxnhve+ervw1kP2UCt9ohHe/6teNWJDYTGxLDgs5iAvitw==
@@ -7289,7 +7305,7 @@ vscode-html-languageservice@^4.0.7:
     vscode-nls "^5.0.0"
     vscode-uri "^3.0.2"
 
-vscode-json-languageservice@^4.1.7:
+vscode-json-languageservice@^4.1.8:
   version "4.1.8"
   resolved "https://registry.yarnpkg.com/vscode-json-languageservice/-/vscode-json-languageservice-4.1.8.tgz#397a39238d496e3e08a544a8b93df2cd13347d0c"
   integrity sha512-0vSpg6Xd9hfV+eZAaYN63xVVMOTmJ4GgHxXnkLCh+9RsQBkWKIghzLhW2B9ebfG+LQQg8uLtsQ2aUKjTgE+QOg==
@@ -7340,25 +7356,25 @@ vscode-nls@^5.0.0:
   resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-5.0.0.tgz#99f0da0bd9ea7cda44e565a74c54b1f2bc257840"
   integrity sha512-u0Lw+IYlgbEJFF6/qAqG2d1jQmJl0eyAGJHoAJqr2HT4M2BNuQYSEiSE75f52pXHSJm8AlTjnLLbBFPrdz2hpA==
 
-vscode-pug-languageservice@^0.27.24:
-  version "0.27.24"
-  resolved "https://registry.yarnpkg.com/vscode-pug-languageservice/-/vscode-pug-languageservice-0.27.24.tgz#fa805c4d3e33dee3681e660a0767136738e68370"
-  integrity sha512-GSvsFB+rPhAD7cBlEKCVNNsFGIaOnp/0zyLw3WpYbXY24vJZafXu1kHvtYaaQXJRnIhqp5EI5p+EqpdI3hTBnw==
+vscode-pug-languageservice@0.28.7:
+  version "0.28.7"
+  resolved "https://registry.yarnpkg.com/vscode-pug-languageservice/-/vscode-pug-languageservice-0.28.7.tgz#096a36cc1db4244e41b5ce21ebc82dbaf708b1c4"
+  integrity sha512-LMeR/be3qm63xsamMFCn9/fcu0PKeIS1ci7ou9CcOwxIK7Zr/vGAmG2K0uNIKzm/w7I20F6855RVf9Ne2QHb4Q==
   dependencies:
-    "@volar/code-gen" "^0.27.24"
-    "@volar/shared" "^0.27.24"
-    "@volar/source-map" "^0.27.24"
-    "@volar/transforms" "^0.27.24"
+    "@volar/code-gen" "0.28.7"
+    "@volar/shared" "0.28.7"
+    "@volar/source-map" "0.28.7"
+    "@volar/transforms" "0.28.7"
     pug-lexer "^5.0.1"
     pug-parser "^6.0.0"
     vscode-languageserver "^8.0.0-next.2"
 
-vscode-typescript-languageservice@^0.27.25:
-  version "0.27.25"
-  resolved "https://registry.yarnpkg.com/vscode-typescript-languageservice/-/vscode-typescript-languageservice-0.27.25.tgz#acd211723b600108c25515388b75d55ce15bb056"
-  integrity sha512-nxpJI9MnF2rn5rKL/032Qrsq3T9DgM3slK5fwZp3suNdo90JG2zFTs3Ola8n62k7+KWu4A775obxyb4wLIW6Gw==
+vscode-typescript-languageservice@0.28.7:
+  version "0.28.7"
+  resolved "https://registry.yarnpkg.com/vscode-typescript-languageservice/-/vscode-typescript-languageservice-0.28.7.tgz#28a8f2a790c4bfcd4f4aa2d7ed79af85a6b1d402"
+  integrity sha512-CLrcnDlISMl9cKLFVubKfaa2fp0Y1sULeCoqUw0JsBRcz+2U67ETalUkolr8iw59oGwINybJ/VyfWnsNFLt9FA==
   dependencies:
-    "@volar/shared" "^0.27.24"
+    "@volar/shared" "0.28.7"
     semver "^7.3.5"
     upath "^2.0.1"
     vscode-languageserver "^8.0.0-next.2"
@@ -7374,29 +7390,29 @@ vscode-uri@^3.0.2:
   resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-3.0.2.tgz#ecfd1d066cb8ef4c3a208decdbab9a8c23d055d0"
   integrity sha512-jkjy6pjU1fxUvI51P+gCsxg1u2n8LSt0W6KrCNQceaziKzff74GoWmjVG46KieVzybO1sttPQmYfrwSHey7GUA==
 
-vscode-vue-languageservice@^0.27.0:
-  version "0.27.30"
-  resolved "https://registry.yarnpkg.com/vscode-vue-languageservice/-/vscode-vue-languageservice-0.27.30.tgz#1f32b0203dd233582f74a457428519a6318f039e"
-  integrity sha512-nPnUNCMqqHfxcCPLyLWvmgbNCgos3SwvPcl/CzAnMbqcjLtNZppsdI7bKX3EEj0Jbg6SGLQ9NanIvZaMI1bsUA==
-  dependencies:
-    "@volar/code-gen" "^0.27.24"
-    "@volar/html2pug" "^0.27.13"
-    "@volar/shared" "^0.27.24"
-    "@volar/source-map" "^0.27.24"
-    "@volar/transforms" "^0.27.24"
-    "@vscode/emmet-helper" "^2.7.0"
-    "@vue/compiler-dom" "^3.2.19"
-    "@vue/reactivity" "^3.2.19"
-    "@vue/shared" "^3.2.19"
+vscode-vue-languageservice@0.28.7:
+  version "0.28.7"
+  resolved "https://registry.yarnpkg.com/vscode-vue-languageservice/-/vscode-vue-languageservice-0.28.7.tgz#2aeae980da4afacde690323f04e6bd6dbc19192f"
+  integrity sha512-zguYZIDTqtTL4rPBZewqdTu2wpivlcw/dah6BcRKPSdJIXIncvCy/BoS0mKb+AvME6ltiQBTCAoF98d8XZRfxg==
+  dependencies:
+    "@volar/code-gen" "0.28.7"
+    "@volar/html2pug" "0.28.7"
+    "@volar/shared" "0.28.7"
+    "@volar/source-map" "0.28.7"
+    "@volar/transforms" "0.28.7"
+    "@vscode/emmet-helper" "^2.8.0"
+    "@vue/compiler-dom" "^3.2.20"
+    "@vue/reactivity" "^3.2.20"
+    "@vue/shared" "^3.2.20"
     request-light "^0.5.4"
     upath "^2.0.1"
-    vscode-css-languageservice "^5.1.4"
-    vscode-html-languageservice "^4.0.7"
-    vscode-json-languageservice "^4.1.7"
+    vscode-css-languageservice "^5.1.7"
+    vscode-html-languageservice "^4.1.0"
+    vscode-json-languageservice "^4.1.8"
     vscode-languageserver "^8.0.0-next.2"
     vscode-languageserver-textdocument "^1.0.1"
-    vscode-pug-languageservice "^0.27.24"
-    vscode-typescript-languageservice "^0.27.25"
+    vscode-pug-languageservice "0.28.7"
+    vscode-typescript-languageservice "0.28.7"
 
 vue-demi@*:
   version "0.11.4"
@@ -7423,12 +7439,12 @@ vue-router@^4.0.11:
   dependencies:
     "@vue/devtools-api" "^6.0.0-beta.14"
 
-vue-tsc@^0.3.0:
-  version "0.3.0"
-  resolved "https://registry.yarnpkg.com/vue-tsc/-/vue-tsc-0.3.0.tgz#3b3872bf4f1d2e4409b57adbd826032e253db406"
-  integrity sha512-zaDRZBxwRIz1XjhNP92FqugG71st6BUMnA2EwPeXrAyzbEYVRz6TezNFceYl3QYqqN8CtaxbqUhaQEDj/ntoCA==
+vue-tsc@^0.28.7:
+  version "0.28.7"
+  resolved "https://registry.yarnpkg.com/vue-tsc/-/vue-tsc-0.28.7.tgz#a6fa746dd0cafc1aea06cde74d22b3e71ed7266f"
+  integrity sha512-s3H29Aa2PVpJ0EKPGKllTIwgmcOTNe+Uo3jHkX+F+wSYBmVLt7ZHeYJD5K35PwM6QZ2ryKcaDn5cDIq683Gb1g==
   dependencies:
-    vscode-vue-languageservice "^0.27.0"
+    vscode-vue-languageservice "0.28.7"
 
 vue@^3.2.16:
   version "3.2.20"