1.1.5 • Published 8 months ago

npm-vue3-element-table v1.1.5

Weekly downloads
-
License
MIT
Repository
-
Last release
8 months ago

注: 由于 sass 版本变更较大,如果遇到安装后报错的 可以查看本地之前安装的 sass 版本是否是 1.80.4 , sass-loader 是否是 16.0.2 如果不是这个版本,请升级一下 sass 版本,并且在 vite.config.ts 里面加上

css: {
    preprocessorOptions: {
        scss: {
            silenceDeprecations: ['legacy-js-api'], //去掉警告提示
        }
    }
}

如果引入 npm-vue3-element-table 报 ts 类型错误,在 src 文件夹下面创建 shims-vue.d.ts 文件,写入 declare module 'npm-vue3-element-table'

示例图片

Fileter_transaction Fileter_transaction

github 项目使用链接地址

封装表格使用说明

调用方法

1.在 main.ts 中全局引入 import { MyBasicTable } from 'npm-vue3-element-table'
app.use(MyBasicTable)
2.在页面中单独引入 import { MyBasicTable } from 'npm-vue3-element-table'

接收参数

1.表格:tableObj(在父组件 computed 计算方法里面声明)

const tableObj = computed(() => {
  let table = {
    data: tableData.value,
    option: tableOptions.value,
    config: {
      height:'300',//高度
      showHeader:true,//是否显示表头
      columnType:'selection', // selection(复选框) expand(展开) radio(单选框)
      hasRadio:true/false, //是否显示单选框
      hasSelection:true/false, //是否显示复选框
      defaultSort: { prop: 'startTime', order: 'descending' }.//默认排序
      rowKey:id, //为表格数据的唯一值,例如id、uuid
      defaultExpandAll: false ,//有展开列时,用该参数设置是否默认展开所有列
      reserveSelection:true// 仅对 type=selection 的列有效
    },
    operation: {
      label: '操作',//操作列
      width: operation.width || '120',
      fixed: operation.fixed || false,
      show: operation.show || false,
      minWidth: operation.minWidth || '',
      showIcon: operation.showIcon || false
    }
  }
  return table
})

2.tableOptions:

tableOptions 中的每一项的 width,min-width 都支持设置

const tableOptions = computed(() => {
  let tableOptions = [
    {
      prop: 'applyPersonName',
      label: '申请人',
      showOverflowToolTip: true,
      show:true/false   //当前列是否显示
    },
    {
      prop: 'name', //如果无需修改,可以直接写后端返回的对应的 key
      showOverflowToolTip: true, //展示超出时鼠标悬浮提示
      fun: (row: any) => {
        goDetail(row) //点击进入详情页
      },
      label: '申请名称' //列名
    },
    {
      prop: 'applyPersonName',
      label: '申请人',
      showOverflowToolTip: true,
      headerRender: (row: any) => {   //自定义表头
        return h(
          ElButton,
          {
            onClick: btnClick
          },
          ['row.action + row.target']
        )
      },
    },
    {
      prop: 'status',
      label: '状态',
      showOverflowToolTip: true,
      filter: true,
      filterKey: 'status',
      selectOptions: statusOptions.value,
      render: (row: any) => {
        return h(statusItem, {
          row: row
        })
      }
    },
    //平台管理-账单管理-消费概览
    {
      prop: 'nameTxt',
      label: '项目名称',
      multipleTip: true, //鼠标悬浮,tooltip 有多个提示的情况
      multipleTipContent: 'multipleTipContent' //tooltip 中展示的内容
    },
      // 表格展开示例
    {
      prop: 'expand',
      label: '',
      render: (row: any) => {
        return h(
          'span',
          row.action ? row.status + '(' + row.userAccount + ')' : '-'
        )
      }
    },
  ]
  return tableOptions
})

3.分页:Pagination(没有特殊需求,在 data 中声明即可)

const Pagination = reactive({
  pagingData: [10, 50, 100, 200],
  pageSize: 10,
  total: 0,
  currentPage: 1,
  show: true
})

4.方法

分页:@pagingEvent="pagingChange"
排序:@sortChange="sortChange"
列表中的筛选事件:@filterChange="filterChange"
当选择项发生变化时会触发该事件:@handleSelectionChange="handleSelectionChange"(handlerSelectAll,handlerSelect的触发 均会触发handleSelectionChange事件,一般情况下写这个事件就可以获取选中的行)
当用户手动勾选全选 Checkbox 时触发的事件:@handlerSelectAll="handlerSelectAll"
当用户手动勾选数据行的 Checkbox 时触发的事件:@handlerSelect="handlerSelect"

5.示例

父页面:
<template>
  <my-basic-table
    ref="logTable"
    :Pagination="Pagination"
    @pagingEvent="pagingChange"
    :tableObj
    @sortChange="sortChange"
    @filterChange="filterChange"
  ></my-basic-table>
</template>
<script lang="ts" setup>
import { ref, computed, reactive, h } from 'vue'
import { ElButton } from 'element-plus'
import statusItem from './status-item.vue'
import editName from './edit-name.vue'
const moduleOptions = ref([
  { value: 'module_login', text: '登录' },
  { value: 'module_job', text: '作业管理' },
])
const statusOptions = ref([
  { value: 'success', text: '成功' },
  { value: 'fail', text: '失败' },
])
const tableData = ref([
  {
    type: 'file',
    createtime: '2024-10-29 13:14:33',
    createpin: '',
    updatetime: null,
    updatepin: '',
    yn: 1,
    uuid: '6d995990-f629-4072-b237-93dc01115d97',
    userAccount: 'gjx',
    userName: 'gjx1',
    managerNum:3,
    multipleTipContent:['account1','account2','account3'],
    module: '登录',
    action: '登录',
    chinese: 2,
    else: 3,
    target: '',
    targetUuid: '6c219b34-db38-48d4-8dd0-a6e84454eacd',
    targetName: 'gjx',
    status: '成功',
    message: null,
    messageExtra: null,
    ip: '172.27.133.22',
    startTime: '2024-10-29 13:14:33',
    endTime: '2024-10-29 13:14:33',
  },
])

const addOperation = (server: any) => {
  const operation = []
  operation.push({
    value: '删除',
    className:'del',
    fun: (item, row) => {
      return openDrawer('删除', row)
    }
  })
  operation.push({
    value: '编辑',
    fun: (item, row) => {
      return openDrawer('编辑', row)
    }
  })
  return (server.operation = operation)
}
const openDrawer = (str: string, obj: object) => {}
tableData.value.map((item: any) => {
  // @ts-ignore
  item.operation = addOperation(item)
})

const Pagination = reactive({
  pagingData: [10, 50, 100, 200],
  pageSize: 10,
  total: 100,
  currentPage: 1,
  show: true,
})
const tableOptions = computed(() => {
  const tableOptions = [
    // 表格展开示例
    {
      prop: 'expand',
      label: '',
      render: (row: any) => {
        return h(
          'span',
          {
            class: 'mgl60',
          },
          row.action ? row.status + '(' + row.userAccount + ')' : '-',
        )
      },
    },
    {
      prop: 'name',
      label: '操作人',
      showOverflowToolTip: true,
      render: (row: any) => {
        return h(
          'span',
          row.userAccount ? row.userAccount + '(' + row.userName + ')' : '-',
        )
      },
    },
    {
      prop: 'managerNum',
      label: '管理员',
      multipleTip: true,
      multipleTipContent: 'multipleTipContent',
      showOverflowToolTip: true
    },
    {
      label: '作业量',
      align: 'center',
      showOverflowToolTip: true,
      children: [
        {
          prop: 'chinese',
          label: '语文',
          showOverflowToolTip: true,
          sortProp: 'chinese',
          minWidth: 120,
        },
        {
          prop: 'else',
          label: '其它',
          minWidth: 110,
          filter: true,
          filterKey: 'elseNum',
          selectOptions: [
            { value: 'math', text: '数学' },
            { value: 'english', text: '英语' },
          ],
          showOverflowToolTip: true,
        },
      ],
    },
    {
      prop: 'module',
      label: '操作模块',
      showOverflowToolTip: true,
      width: 140,
      filter: true,
      filterKey: 'module',
      selectOptions: moduleOptions.value,
    },
    {
      prop: 'actionTxt',
      showOverflowToolTip: true,
      width: 140,
      label: '执行动作', // 自定义渲染表头示例
      headerRender: (row: any) => {
        return h(
          ElButton,
          {
            onClick: btnClick,
          },
          ['自定义表头'],
        )
      },
      render: (row: any) => {
        return h('span', row.action + row.target)
      },
    },
    {
      prop: 'operationName',
      showOverflowToolTip: true,
      width: 200,
      label: '操作对象',
      render: (row: any) => {
        return h(editName)
      },
    },
    {
      prop: 'status',
      label: '状态',
      filter: true,
      filterKey: 'status',
      selectOptions: statusOptions.value,
      render: (row: any) => {
        return h(statusItem, {
          row: row,
        })
      },
    },
    {
      prop: 'startTime',
      label: '操作时间',
      width: 160,
      sortProp: 'startTime',
    },
  ]
  return tableOptions
})
const tableObj = computed(() => {
  const table = {
    data: tableData.value,
    option: tableOptions.value,
    operation:{show:true},
    config: {
      defaultSort: { prop: 'startTime', order: 'descending' },
    },
  }
  return table
})
const pagingChange = (type: string, val: number) => {
  console.log(type, val, '分页')
}
const filterChange = (obj: any) => {
  console.log(obj, '筛选条件')
}
const btnClick = () => {
  console.log('自定义表头按钮点击事件')
}
const sortChange = (obj: any) => {
  console.log(obj, '排序条件')
}
</script>
<style lang="scss">
#app {
  height: 100vh;
}
.mgl60 {
  margin-left: 60px;
}
</style>
status-item子页面
<template>
  <div class="">
    <span class="status">
      <span
        class="status-circle"
        :class="
          row.status == '成功'
            ? 'success'
            : row.status == '失败'
              ? 'fail'
              : 'color-create-update-delete'
        ">
        <!-- ● -->
      </span>
      <span
        class="fs14"
        :class="
          row.status == '成功'
            ? 'success'
            : row.status == '失败'
              ? 'fail'
              : 'color-create-update-delete'
        ">
        {{
          row.status == '成功'
            ? '成功'
            : row.status == '失败'
              ? '失败'
              : '操作中'
        }}
      </span>
      <el-popover
        v-if="row.status == '失败'"
        placement="top"
        popper-class="ope-status-pop"
        title="【失败原因】"
        width="200"
        trigger="hover">
        <template #reference>
          <img class="icon-img" src="../../assets/images/warning.png" alt="" />
        </template>
        <template #default>
          <div class="ope-status-pop-content">
            {{ row.message }}
          </div>
        </template>
      </el-popover>
    </span>
  </div>
</template>

<script lang="ts" setup>
defineProps({ row: Object as any })
</script>

<style lang="scss" scoped>
.status {
  // 成功
  .success {
    color: #333;
    font-size: 1rem;
    &::before {
      background: #50b89c;
    }
  }
  // 其他
  .color-create-update-delete {
    font-size: 1rem;
    color: #333;
    &::before {
      background: #206bfa;
    }
  }
  // 失败
  .fail {
    color: #333;
    font-size: 1rem;
    &::before {
      background: #ec7c7c;
    }
  }
  .status-circle {
    &::before {
      content: '';
      display: inline-block;
      width: 0.375rem;
      height: 0.375rem;
      border-radius: 50%;
      position: relative;
      top: -0.125rem;
      margin-right: 0.25rem;
      white-space: nowrap;
    }
  }
  .fs14 {
    font-size: 0.875rem !important;
  }
  .icon-img {
    width: 0.875rem;
    height: 0.875rem;
    position: relative;
    top: 0.125rem;
    margin-left: 0.125rem;
  }
}
</style>

<style lang="scss">
.ope-status-pop {
  font-weight: 400;
  font-size: 0.875rem;
  color: #333;
  letter-spacing: 0;
  text-align: justify;
  line-height: 1.375rem;
  .ope-status-pop-content {
    max-height: 300px;
    overflow-y: auto;
  }
  .el-popover__title {
    font-weight: 600;
    font-size: 1rem;
    color: #333;
  }
}
.ope-status-pop .el-popper__arrow {
}
</style>
edit-name子页面
<template>
  <div class="table-name-wrapper">
    <el-icon>
      <FolderOpened v-if="row.type == 'folder'" />
      <Shop v-else />
    </el-icon>
    <div class="edit-show-box">
      <template v-if="isEdit">
        <el-input
          v-model="inputShowName"
          placeholder="请输入"
          maxlength="255" />
        <!-- 扩展名 -->
        <span v-if="row.type == 'file'">{{ extendName }}</span>
        <!-- 按钮 -->
        <el-icon @click="confirm"><Check /></el-icon>
        <el-icon><Close @click="cancel" /></el-icon>
      </template>
      <span v-else class="show-name-box">
        <span :title="showName">{{ showName }}{{ extendName }}</span>
        <el-icon @click="edit"><EditPen /></el-icon>
      </span>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { ElMessage } from 'element-plus'

const props = defineProps<{
  row: {
    userName: string
    type: 'file' | 'folder'
  }
}>()
const $emit = defineEmits(['openDialog'])
const isEdit = ref(false)
const inputShowName = ref('') // input内绑定名称
const showName = ref('') // 表格内显示名称
const extendName = ref('') // 扩展名

function edit() {
  isEdit.value = true
  inputShowName.value = showName.value
}
function confirm() {
  isEdit.value = false
  showName.value = inputShowName.value
  ElMessage({
    message: '编辑成功',
    type: 'success'
  })
}
function cancel() {
  isEdit.value = false
}

function init() {
  console.log(props.row, 'row')
  showName.value = props.row.userName
}
init()
</script>

<style scoped lang="scss">
.table-name-wrapper {
  display: flex;
  align-items: center;
  .icon-wenjianjia1 {
    color: #ffca28;
  }
  .icon-yingyong {
    color: #1496db;
  }
  .edit-show-box {
    margin-left: 8px;
    display: flex;
    align-items: center;
    flex: 1;
    width: calc(100% - 8px - 1rem);
    .el-icon {
      font-size: 16px;
      cursor: pointer;
      margin-left: 8px;
    }
    .show-name-box {
      display: flex;
      align-items: center;
      width: 100%;
      > span {
        color: #206bfa;
        cursor: pointer;
        overflow: hidden;
        white-space: nowrap;
        text-overflow: ellipsis;
      }
      .el-icon {
        color: #206bfa;
      }
    }
  }
}
</style>
1.1.1

9 months ago

1.1.0

9 months ago

1.0.9

9 months ago

1.0.8

9 months ago

1.0.7

9 months ago

1.1.5

8 months ago

1.1.4

8 months ago

1.1.3

9 months ago

1.1.2

9 months ago

1.0.10

9 months ago

1.0.5

9 months ago

1.0.4

9 months ago

1.0.3

9 months ago