Vuetify UI组件笔记

1. v-btn浮动按钮

v-btn浮动按钮
v-btn按钮和v-text-field文本
flat:移除按钮的背景色,布尔值类型,默认为false;
icon:将按钮指定为图标——原型和平面,布尔值类型,默认为false;
disabled: 移除组件的单击或 target(触发事件)功能;
depressed:移除按钮的阴影效果

2. v-text-field文本框

v-text-field官网
v-btn按钮和v-text-field文本
(1)append-icon:在文本框后面追加一个图标,默认为String类型;
(2)counter:为输入长度创建一个计数器,如果未指定数字,则默认为25,不会应用任何验证;类型为boolean|number|string;
(3)disabled:布尔类型boolean不可见;
(4)multi-line:是否转为文本域,默认是false。文本框和文本域可以自由切换;
(5)name:字段名,表单中会用到;
(6)label:提示文字,输入框的标签;
(7)value:值。可以用v-model代替,实现双向绑定。
(8)hide-details:表示隐藏文本框底部错误信息。
(9)required:是否为必填项,如果是,会在label后加*,不具备校验功能。默认是false;
(10)rows:文本域的行数,multi-line为true时才有效;
(11)single-line:是否单行文本显示,默认是false;
(12)hint:提示文本;
(13)persistent-hint:强制提示总是可见的

3. v-textarea多行文本框 v-textarea

(1)auto-grow:根据文本数量自动增长文本;
(2)rows:默认行数;
(3)hint:提示文本;
(4)persistent-hint:强制提示总是可见的;
(5)disabled:禁用输入;
(6)id:设置组件上的 DOM id;
(7)hide-details:表示隐藏文本框底部提示和验证错误信息;
(8)flat:当使用solo或者solo-inverted属性时,移除添加到元素的标高(阴影)

项目实例:

<v-col cols="12">
  <vee
    :rules="{required:true, max: 128}"
    v-slot="{ errors }"
  >
    <v-textarea
      :error-messages="errors"
      :label="$t('schema.license.customerUuid')"
      :rows="1"
      auto-grow
      v-model="currentModel.customerUuid"
    ></v-textarea>
  </vee>
</v-col>

4. v-toolbar工具栏组件

Vuetify官网链接:v-toolbar工具栏
v-toolbar 组件对于任何 gui 都是至关重要的,因为它通常是站点导航的主要来源。工具栏组件与 v-navigation-drawer 和 v-card 配合使用效果非常好。
dense: 将工具栏内容的高度降低到 48px(使用 prominent 属性时为 96px)。 --(type: boolean)
flat: 删除工具栏的框阴影。–(type: boolean)

5. v-dialog对话框

Vuetify官网链接:v-dialog对话框
v-dialog 组件常用属性:
(1)max-width:限制宽度;
(2)v-model:value值双向绑定到show变量,用来控制窗口显示;
(3)persistent: 在元素外部单击不会将其停用。----(type: boolean)-(delault: false);
(4)scrollable:当包含card, card-title, card-text 以及 card-actions这几个的对话框可滚动设为 true 的时候;card-text 应该指定高度并且设置 overflow-y;布尔类型,默认值为false.

6. v-card卡片

Vuetify官网链接:v-card卡片
v-card组件是一个多功能组件,可用于从面板到静态图像的任何事物。card组件有许多班助组件,使标记尽可能简单。没有列出选项的组件使用Vue的功能组件选项来加快渲染速度,并作为标记糖来使构建更容易。
(1)v-card-media:一般放图片或视频;
(2)v-card-title:卡片的标题,一般位于卡片顶部;
(3)v-card-text:卡片的文本(主体内容),一般位于卡片正中;
(4)v-card-action:卡片的按钮,一般位于卡片底部.

7.v-form表单

v-form的常用属性
(1)lazy-validation:如果启用,value将永远是 true ,除非有可见的验证错误。您仍然可以调用validate()来手动触发验证;布尔类型,默认值为false。
(2)value:true,代表表单验证通过;false,代表表单验证失败;布尔类型,默认值为false。

v-form的常用方法
(1)validate:校验整个表单数据,前提是你写好了校验规则。返回Boolean表示校验成功或失败。
(2)reset:重置表单数据。

8.v-menu下拉菜单

v-menu的常用属性
(1)left:将组件向左边对齐
(2)right:将组件向右边对齐
(3)bottom:将组件向底部对齐
(4)offset-x(y):在y轴上偏移菜单,与左/右(上/下)方向一起工作
(6)transition:设置组件转换方式

9.v-overlay遮罩层 v-overlay

v-overlay的常用属性
(1)absolute:给组件应用 position: absolute,绝对定位,并且包含在其父元素内
(2)color:将指定的颜色应用于控件;
(3)value:控制组件可见还是隐藏;
(4)opacity:设置遮罩层的透明度;
(6)z-index:用于组件的 z-index

项目实例:

<template>
  <div class="fill-height">
    <v-overlay
      :absolute="absolute"
      :opacity="opacity"
      :value="showing"
    >
      <v-progress-circular
        indeterminate
        size="64"
      ></v-progress-circular>
    </v-overlay>
    <inner-frame
      :src="baseUrl+'#/strategy/dpi?assetIp='+ip+'&'+param+'&token='+token"
      id="sasManageIframe"
      name="sasFrame"
      ref="frame"
      style="border: none;"
    ></inner-frame>
  </div>
</template>

<script>
import innerFrame from '@c/inner-frame.vue'
// import { services } from '@/settings'
import userMixins from '@/mixins/store/user'

export default {
  mixins: [userMixins],
  props: {
    show: {
      type: Boolean,
      default: false
    }
  },
  components: { innerFrame },
  data() {
    return {
      baseUrl: '',
      ip: '',
      param:
        'header=false&footer=false&toolbar=false&license=false&permanent=true&id=strategy&value=0',
      token: '',
      showing: false,
      absolute: true,
      opacity: 0.1
    }
  },
  watch: {
    show: {
      handler(val) {
        this.showing = val
      },
      immediate: true
    }
  },
  mounted() {
    //添加审计加载loading
    const iframe = document.querySelector('#sasManageIframe')
    if (iframe) {
      const ithis = this  // 将this赋给一个变量,在function(){}中使用
      iframe.addEventListener(
        'load',
        function () {
          ithis.showing = false
        },
        false
      )
    }
  },
  created() {
    this.ip = this.$attrs.ip
    // this.baseUrl = services.sas
    this.baseUrl = `https://${this.ip}/`
    this.token = this.$token
  }
}
</script>

<style>
</style>

10. v-file-input文件上传 v-file-input

v-file-input属性:
(1)truncate-length:在用省略号截断之前的文件名的长度
(2)prepend-icon:在组件前添加一个图标,使用与 v-icon 相同的语法
(3)show-size:设置所选文件的显示大小。当使用 true 默认值为 1000 显示(kB,MB,GB) 时,1024 将显示(KiB,MiB,GiB)。
(4)accept:接收格式(accept=".doc,.docx,.png,.txt")

参考:vuetify文件上传 file inputs

11. v-navigation-drawer v-navigation-drawer

v-navigation-drawer的常用属性

(1)permanent:不管屏幕尺寸如何,抽屉都可以看到
(2)value:控制组件可见还是隐藏
(3)fixed:给组件应用 position: fixed

12.v-data-table_表格组件 vuetify—v-data-table

v-data-table 用于显示表格数据,功能包括排序、搜索、分页、行内编辑、头部提示以及行选择。而我们在实际应用中使用最多的就是服务端分页和排序,如果你从后台加载数据,并希望显示结果之前进行分页和排序,你可以使用 total-items 属性。定义这个属性将会禁用内置的分页和排序,并且你需要使用 pagination 属性来监听变化。使用 loading 属性来显示获取数据时的进度条。

相关资料:
(1)data-tables组件
(2)v-data-table_表格组件
(3)data-table每页数目下拉框设置

项目实例:

(1) 安管(smp)操作日志&事件记录页面

<!--
  FilePath: \src\views\reports\analysis\analysis1.vue
  Project: xxx
  CreatedAt: 2020-10-28 10:02:47
  CreatedBy:666
  Copyright: (c) 2020
  Task: #1
  操作日志页面
-->

<template>
  <div class="d-flex flex-column fill-height">
    <v-toolbar
      class="mb-1"
      slot="header"
    >
      <v-toolbar-items class="d-flex align-center">
        <span class="pr-4">{{$t('schema.logs.time')}}</span>
        <v-select
          :items="items"
          class="pr-5 mt-6"
          dense
          solo
          style="flex: 1; width: 200px"
          v-model="time"
        ></v-select>
        <date-time-picker
          :enablings="enabling"
          v-model="date"
        ></date-time-picker>
        <div class="my-2 ml-5">
          <v-btn
            @click="search"
            color="primary"
          >{{$t('common.actions.searchBtn')}}</v-btn>
        </div>
      </v-toolbar-items>
    </v-toolbar>
    <div
      class="fill-height my-1 white"
      style="overflow: auto;"
    >
      <data-table
        :headers="headers"
        :list="list"
        :total="totalItems"
        @pagi="pagi"
      ></data-table>
    </div>
  </div>
</template>

<script>
// import dateTimePicker from '@c/data-time-picker'
import dataTable from './data-table'
import dateTimePicker from './date-time-picker'
import { format, subMinutes, subHours, subDays } from 'date-fns'

export default {
  components: {
    dateTimePicker,
    dataTable
  },
  // filters: {
  //   time(value) {
  //     return format(Date.parse(value), 'yyyy-MM-dd HH:mm:ss')
  //   }
  // },
  data() {
    return {
      date: {
        from: format(subMinutes(new Date(), 10), 'yyyy-MM-dd HH:mm'),
        to: format(new Date(), 'yyyy-MM-dd HH:mm')
      },
      items: [
        { text: this.$t('schema.dates.5-minutes'), value: 1 },
        { text: this.$t('schema.dates.1-hour'), value: 2 },
        { text: this.$t('schema.dates.1-day'), value: 3 },
        { text: this.$t('schema.dates.selfDefine'), value: 4 }
      ],
      enabling: true,
      time: '',
      totalItems: 0,
      model: {
        timerange: {
          type: 'absolute'
        },
        per_page: 15,
        page: 1, // 当前页
        // itemsPerPage: 10,
        filter: { alerts: 'exclude' }
      },
      headers: [
        // {
        //   type: 'index'
        // },
        // {
        //   text: '',
        //   value: 'data-table-expand',
        //   width: 20,
        //   align: 'right',
        //   sortable: false
        // },
        {
          text: this.$t('schema.logs.operator'),
          value: 'event.message',
          align: 'left',
          sortable: true
        },
        {
          text: this.$t('schema.logs.time'),
          value: 'event.priority',
          align: 'left',
          sortable: true
        },
        {
          text: this.$t('schema.logs.content'),
          value: 'event.description',
          align: 'left',
          sortable: true
        }
      ],
      list: []
    }
  },
  watch: {
    'model.page'() {
      this.getRecords()
    },
    time: {
      handler(val) {
        if (val === 1 || val === 2 || val === 3) {
          this.enabling = true
          this.date.from =
            val === 1
              ? format(subMinutes(new Date(), 5), 'yyyy-MM-dd HH:mm')
              : val === 2
              ? format(subHours(new Date(), 1), 'yyyy-MM-dd HH:mm')
              : format(subDays(new Date(), 1), 'yyyy-MM-dd HH:mm')
          this.date.to = format(new Date(), 'yyyy-MM-dd HH:mm')
        } else if (val === 4) {
          this.enabling = false
        }
      }
    }
  },
  methods: {
    search() {
      if (this.model.page === 1) {
        this.getRecords()
      } else {
        this.model.page = 1
      }
    },
    pagi(val) {
      this.model.per_page = val.itemsPerPage
      this.model.page = val.page
      this.getRecords()
    },
    async getRecords() {
      const date = JSON.parse(JSON.stringify(this.date))
      const { from, to } = date
      const data = JSON.parse(JSON.stringify(this.model))
      Object.assign(data.timerange, {
        from: new Date(from).toISOString(),
        to: new Date(to).toISOString()
      })
      // const res = await search(data)
      // if (res.status === 200) {
      //   this.list = res.data.events
      //   this.totalItems = res.data.total_events
      // }
    }
  },
  created() {
    this.time = this.items[0].value
  },
  async mounted() {
    this.getRecords()
  }
}
</script>

<style lang="scss" scoped>
</style>

<!--
  FilePath: \src\views\happening\record\data-table.vue
  Project: xxx
  CreatedAt: 2020-10-28 10:23:19
  CreatedBy: 666
  Copyright: (c) 2020
  Task: #1
  事件记录页面-data-table
-->

<template>
  <v-data-table
    :footer-props="perPageOptions"
    :headers="headers"
    :hide-default-footer="false"
    :items="list"
    :options.sync="options"
    :server-items-length="total"
    :single-expand="true"
    @update:options="optionsChanged"
    class="elevation-1 flex-table"
    item-key="event.id"
  >
    <template
      v-slot:item.event.timestamp="{ item }"
    >{{format(Date.parse(item.event.timestamp), 'yyyy-MM-dd HH:mm:ss.SSS')}}</template>
  </v-data-table>
</template>

<script>
import { format } from 'date-fns'
// import i18n from '@/i18n'
export default {
  props: {
    headers: {
      type: Array,
      default: () => {
        return []
      }
    },
    list: {
      type: Array,
      default: () => {
        return []
      }
    },
    total: {
      type: Number,
      default: 0
    }
  },
  data() {
    return {
      format,
      options: {
        page: 1,
        itemsPerPage: 15,
        pageStart: 1,
        pageStop: 1,
        sortDesc: [false, false]
      },
      perPageOptions: {
        'items-per-page-options': [5, 10, 15, 20, -1]
      }
    }
  },
  filters: {},
  methods: {
    optionsChanged() {
      this.$emit('pagi', this.options)
    }
  }
}
</script>

(2) 安全审计(sas)数据外发页面

<!--
  FilePath: \src\views\devices\outdata\outdata.vue
  Project: xxx
  CreatedAt: 2021-05-07 09:56:46
  CreatedBy: 666
  Copyright: (c) 2021
  Task: #1
  数据外发页面
-->

<template>
  <one-table>
    <div class="flex-grow-1">
      <v-row class="mt-n4 mb-n4">
        <v-col cols="6">
          <syslog-server></syslog-server>
        </v-col>
      </v-row>
      <v-row class="mt-n2">
        <v-col cols="6">
          <safe-platform></safe-platform>
        </v-col>
      </v-row>
    </div>
  </one-table>
</template>

<script>
import oneTable from '@c/layout/one-table'
import syslogServer from './syslog-server'
import safePlatform from './safe-platform'

export default {
  components: { oneTable, syslogServer, safePlatform },
  data() {
    return {}
  }
}
</script>

<style>
</style>

-------------------------------------------------------------------------------------

<!--
  FilePath: \src\views\devices\outdata\syslog-server.vue
  Project: xxx
  CreatedAt: 2021-05-07 11:16:51
  CreatedBy: 666
  Copyright: (c) 2021
  Task: #1
  数据外发--syslog服务器模块
-->

<template>
  <div class="d-flex flex-column white">
    <v-toolbar
      color="#e6f0fb"
      dense
      flat
    >
      <v-toolbar-title
        class="primary--text"
      >{{$t('schema.system.syslogServer')}}</v-toolbar-title>
    </v-toolbar>
    <div
      class="d-flex flex-column"
      style="height: 221px"
    >
      <div class="text-left pt-3 pl-3 mb-2">
        <v-btn
          :disabled="syslogServers.length >=2 ? true : false"
          @click="addSyslogServer"
          class="primary"
        >{{$t('schema.system.addSyslogServer')}}</v-btn>
      </div>
      <div
        class="mx-3"
        style="border:1px solid #e0e0e0"
      >
        <v-data-table
          :headers="headers"
          :items="syslogServers"
          :items-per-page="per_page"
          class="fill-height overflow-y-auto"
          hide-default-footer
        >
          <template v-slot:top>
            <syslogServer-dialog
              :icon="icon"
              :model="model"
              :title="title"
              :uploadDatas="uploadDatas"
              @changed="refresh"
              v-if="serverDialog"
              v-model="serverDialog"
            ></syslogServer-dialog>
          </template>
          <template v-slot:item.option="{ item }">
            <v-icon
              @click="editServer(item)"
              class="mr-2"
              color="primary"
              dense
            >edit</v-icon>
            <v-icon
              @click="deleteServer(item)"
              color="primary"
              dense
            >remove_circle</v-icon>
          </template>
        </v-data-table>
      </div>
    </div>
  </div>
</template>

<script>
import { enums } from '@utils'
import syslogServerDialog from './syslogServer-dialog'
import { findSyslogServer, remove } from '@api/system/outData'
import { success, error, confirm } from '@utils/message'

export default {
  components: { syslogServerDialog },
  data() {
    return {
      icon: '',
      uploadDatas: [],
      title: '',
      serverDialog: false,
      syslogServers: [],
      per_page: 10000,
      model: this.getDef(),
      headers: [
        {
          text: this.$t('schema.system.ip'),
          value: 'ip',
          sortable: false
        },
        {
          text: this.$t('schema.system.port'),
          value: 'port',
          sortable: false,
          width: 60
        },
        {
          text: this.$t('schema.system.uploadDatas'),
          value: 'items',
          sortable: false
        },
        {
          text: this.$t('schema.dpi.actions'),
          value: 'option',
          sortable: false,
          width: 80
        }
      ]
    }
  },
  methods: {
    addSyslogServer() {
      // if (this.syslogServers.length >= 2) {
      //   error(this.$t('schema.system.syslogServerlen'))
      //   return
      // }
      this.icon = 'add_circle'
      this.title = this.$t('schema.system.addSyslogServer')
      this.model = this.getDef()
      this.serverDialog = true
    },
    editServer(item) {
      this.icon = 'edit'
      this.title = this.$t('schema.system.editSyslogServer')
      let itemsys = JSON.parse(JSON.stringify(item))
      itemsys.items = itemsys.items.map(o => {
        for (let i = 0; i < this.uploadDatas.length; i++) {
          if (this.uploadDatas[i].text === o) {
            return this.uploadDatas[i].value
          }
        }
      })
      this.model = itemsys
      this.serverDialog = true
    },
    refresh() {
      this.findSyslogServer()
    },
    async deleteServer(item) {
      const yes = await confirm(this.$t('common.messages.deleteConfirm'))
      if (!yes) {
        return
      }
      try {
        await remove(item.id)
        this.refresh()
        success()
      } catch (err) {
        error()
        throw new Error(err)
      }
    },
    async findSyslogServer() {
      const res = await findSyslogServer()
      this.syslogServers = res.map(item => {
        item.items = item.items.map(o => {
          for (let i = 0; i < this.uploadDatas.length; i++) {
            if (this.uploadDatas[i].value === o) {
              return this.uploadDatas[i].text
            }
          }
        })
        return item
      })
    },
    getDef() {
      return {
        ip: '',
        port: '',
        items: []
      }
    }
  },
  created() {
    this.uploadDatas = enums.list('UploadDatas')
    this.findSyslogServer()
  }
}
</script>

-----------------------------------------------------------------------------------

<!--
  FilePath: \src\views\devices\outdata\syslogServer-dialog.vue
  Project: xxx
  CreatedAt: 2021-05-09 11:33:46
  CreatedBy: 666
  Copyright: (c) 2021
  Task: #1
  新增/修改syslog服务器弹框
-->

<template>
  <single-dialog
    :actions="actions"
    :icon="icon"
    :title="title"
    @cancel="cancel"
    @ok="ok"
    max-width="500"
    v-model="value"
  >
    <vee-ob ref="ob">
      <form-flex class="pb-0">
        <v-row class="mx-0">
          <v-col
            class="pb-0"
            cols="6"
          >
            <vee
              :customMessages="{remote:$t('common.messages.alreadyExist')}"
              :debounce="500"
              :rules="{required: true, ip: true, remote: { callback: uniqueValue, args:{id: currentModel.id }}}"
              v-slot="{ errors }"
            >
              <v-text-field
                :error-messages="errors"
                :label="$t('schema.system.ip')"
                placeholder="192.168.1.1"
                v-model="currentModel.ip"
              ></v-text-field>
            </vee>
          </v-col>
          <v-col
            class="pb-0"
            cols="2"
          >
            <vee
              rules="required|port"
              v-slot="{ errors }"
            >
              <v-text-field
                :error-messages="errors"
                :label="$t('schema.system.port')"
                placeholder="514"
                v-model="currentModel.port"
              ></v-text-field>
            </vee>
          </v-col>
          <v-col
            class="mt-n8"
            cols="12"
          >
            <div>
              <h4 class="pt-4 pb-1">{{$t('schema.system.uploadData')}}</h4>
              <v-row class="mb-n3">
                <v-col
                  :key="index"
                  class="mt-n6"
                  cols="4"
                  v-for="(item, index) in this.uploadDatas"
                >
                  <v-checkbox
                    :label="item.text"
                    :value="item.value"
                    class="pt-0"
                    dense
                    hide-details
                    v-model="currentModel.items"
                  ></v-checkbox>
                </v-col>
              </v-row>
            </div>
          </v-col>
        </v-row>
      </form-flex>
    </vee-ob>
  </single-dialog>
</template>

<script>
import { singleDialog } from '@c/dialogs'
import { formFlex } from '@c/forms'
import { update, create, validateSyslogServerIp } from '@api/system/outData'
import { success, error } from '@utils/message'

export default {
  components: { singleDialog, formFlex },
  props: {
    value: {
      type: Boolean,
      default: false
    },
    title: {
      type: String,
      default: ''
    },
    icon: {
      type: String,
      default: ''
    },
    uploadDatas: {
      type: Array,
      default: () => []
    },
    model: {
      type: Object,
      default: () => {}
    }
  },
  data() {
    return {
      actions: true,
      currentModel: {}
    }
  },
  watch: {
    model: {
      handler(val) {
        this.currentModel = JSON.parse(JSON.stringify(val))
      },
      immediate: true
    }
  },
  methods: {
    async uniqueValue(value, args) {
      const res = await validateSyslogServerIp(value, args.id)
      return res.length <= 0
    },
    cancel() {
      this.$emit('input', false)
    },
    async ok() {
      const valid = await this.$refs.ob.validate()
      if (!valid) {
        return
      }
      const { ip, port, items } = this.currentModel
      let data = {
        ip,
        port: Number(port),
        items
      }
      try {
        if (this.currentModel.id) {
          data = {
            ip: { set: ip },
            port: { set: Number(port) },
            items
          }
          await update(this.currentModel.id, data)
        } else {
          await create(data)
        }
        this.$emit('changed')
        this.$emit('input', false)
        success()
      } catch (err) {
        error()
        throw new Error(err)
      }
    }
  }
}
</script>

  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值