feat:增加项目实战模块
This commit is contained in:
202
docs/Web/Vue/ElTable.md
Normal file
202
docs/Web/Vue/ElTable.md
Normal file
@@ -0,0 +1,202 @@
|
||||
---
|
||||
title: Element Plus 表格组件
|
||||
date: 2026-05-27
|
||||
---
|
||||
|
||||
# 一、加载中
|
||||
```vue
|
||||
<el-table
|
||||
v-loading="dispatchStore.isLoading"
|
||||
element-loading-text="加载中..."
|
||||
:data="dispatchStore.contractList"
|
||||
border
|
||||
stripeempty-text="暂无记录"
|
||||
class="common-table">
|
||||
|
||||
</el-table>
|
||||
```
|
||||
|
||||
::: tip
|
||||
要配合pinia存储使用,获取数据前将loading置为true,完成后置为false。
|
||||
:::
|
||||
|
||||
# 二、展开行
|
||||
```vue
|
||||
<template>
|
||||
<el-table :data="dispatchStore.contractList"
|
||||
:row-key="getRowKey"
|
||||
:expand-row-keys="expandedRows"
|
||||
@expand-change="handleExpandChange">
|
||||
<el-table-column type="expand">
|
||||
<template #default="props">
|
||||
<el-table :data="props.row.dispatchList"
|
||||
border stripeempty-text="暂无记录"
|
||||
class="dispatch-content"
|
||||
style="width: 100%">
|
||||
<el-table-column fixed type="index" align="center" width="60" />
|
||||
<el-table-column prop="customer" label="终端客户" align="center" width="180"/>
|
||||
</el-table>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
const expandedRows = ref<number[]>([])
|
||||
|
||||
// 获取行的唯一标识
|
||||
const getRowKey = (row: IDispatch) => {
|
||||
return row.id
|
||||
}
|
||||
|
||||
// 处理展开行变化
|
||||
const handleExpandChange = (row: IDispatch, expandedRowsList: IDispatch[]) => {
|
||||
if (expandedRowsList.length > 0) {
|
||||
// 只保留最新展开的行
|
||||
expandedRows.value = [getRowKey(row)]
|
||||
} else {
|
||||
expandedRows.value = []
|
||||
}
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
||||
  通过类型expand和插槽props实现,可以展示任意格式数据。
|
||||
  增加表格的`row-key`、`expand-row-key`属性可以实现只展开某一行功能。
|
||||
|
||||
# 三、排序和筛选
|
||||
```vue
|
||||
<template>
|
||||
<el-table :data="dispatchStore.contractList">
|
||||
<el-table-column prop="contractNum" label="合同编号" align="center" min-width="10%"
|
||||
:filters=contractNumFilters :filter-method="filterColumnMethod" sortable>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useDispatchStore } from '@/stores/dispatch.ts'
|
||||
import { computed } from 'vue'
|
||||
import type { IContract } from '@/types/dispatch.ts'
|
||||
|
||||
const dispatchStore = useDispatchStore()
|
||||
|
||||
type ContractField = keyof IContract
|
||||
|
||||
const filterColumnMethod = (value, row, column) => {
|
||||
return row[column.property] === value
|
||||
}
|
||||
|
||||
const getFiltersByKey = (key: ContractField) => {
|
||||
const result = [...new Set(dispatchStore.contractList.map((item) => item[key]).filter((value) => value != null && value !==''))]
|
||||
|
||||
return result.map((item) => ({
|
||||
text: item,
|
||||
value: item
|
||||
}))
|
||||
}
|
||||
|
||||
const contractNumFilters = computed(() => getFiltersByKey('contractNum'))
|
||||
</script>
|
||||
```
|
||||
|
||||
  在`el-table-column`中添加`sortable`即可实现排序功能。
|
||||
  在`el-table-column`中添加`filters`和`filter-method`实现筛选功能。
|
||||
  `filters`为原始数据中该字段下的所有值,并转为指定格式,也可以自定义筛选字段。
|
||||
|
||||
# 四、表头搜索
|
||||
```vue
|
||||
<template>
|
||||
<el-table :data="dispatchStore.contractList" >
|
||||
<el-table-column prop="contractNum" label="合同编号" align="center" min-width="10%">
|
||||
<template #header>
|
||||
<div class="custom-header">
|
||||
<span :class="{ 'active': contractNumSearch }">合同编号</span>
|
||||
<el-popover ref="contractNumPopoverRef" placement="bottom" width="230" trigger="click">
|
||||
<template #default>
|
||||
<el-select v-model="contractNumSearch" filterable clearable
|
||||
placeholder="请选择或输入合同编号" @change="applySearch('contractNum')">
|
||||
<el-option v-for="(item, index) in contractNumValue"
|
||||
:key="index" :label="item" :value="item"/>
|
||||
</el-select>
|
||||
<div style="margin-top: 8px;display: flex;justify-content: flex-end;">
|
||||
<el-button type="primary" size="small" @click="applySearch('contractNum')">搜索</el-button>
|
||||
<el-button size="small" @click="resetSearch('contractNum')">重置</el-button>
|
||||
</div>
|
||||
</template>
|
||||
<template #reference>
|
||||
<el-icon class="search-icon"><Search/></el-icon>
|
||||
</template>
|
||||
</el-popover>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useDispatchStore } from '@/stores/dispatch.ts'
|
||||
import { computed, ref } from 'vue'
|
||||
import { Search } from '@element-plus/icons-vue'
|
||||
import type { IContract } from '@/types/dispatch.ts'
|
||||
import type { PopoverInstance } from 'element-plus'
|
||||
import type { Ref } from 'vue'
|
||||
|
||||
const dispatchStore = useDispatchStore()
|
||||
|
||||
type ContractField = keyof IContract
|
||||
|
||||
const getFiltersByKey = (key: ContractField) => {
|
||||
const result = [...new Set(dispatchStore.contractList.map((item) => item[key]).filter((value) => value != null && value !== ''))]
|
||||
|
||||
return result.map((item) => ({
|
||||
text: item,
|
||||
value: item
|
||||
}))
|
||||
}
|
||||
|
||||
const contractNumFilters = computed(() => getFiltersByKey('contractNum'))
|
||||
|
||||
const contractNumValue = computed(() => contractNumFilters.value.map((item) => item.value))
|
||||
|
||||
const contractNumPopoverRef = ref<PopoverInstance>()
|
||||
const contractNumSearch = ref('')
|
||||
|
||||
const popoverMap = new Map<string, Ref<PopoverInstance | undefined>>([
|
||||
['contractNum', contractNumPopoverRef]
|
||||
])
|
||||
const searchMap = new Map<string, Ref<string>>([
|
||||
['contractNum', contractNumSearch]
|
||||
])
|
||||
|
||||
const applySearch = async (field: ContractField) => {
|
||||
const searchRef = searchMap.get(field)
|
||||
|
||||
if (!searchRef) return
|
||||
|
||||
if (!searchRef.value) {
|
||||
await dispatchStore.queryContractList()
|
||||
return
|
||||
}
|
||||
if (!searchRef.value.trim()) return
|
||||
|
||||
dispatchStore.contractList = dispatchStore.contractList.filter((item) => {
|
||||
const value = item[field]
|
||||
return typeof value === 'string' && value.includes(searchRef.value)
|
||||
})
|
||||
popoverMap.get(field)?.value?.hide()
|
||||
}
|
||||
|
||||
const resetSearch = async (field: string) => {
|
||||
const searchRef = searchMap.get(field)
|
||||
|
||||
if (searchRef) {
|
||||
searchRef.value = ''
|
||||
}
|
||||
popoverMap.get(field)?.value?.hide()
|
||||
await dispatchStore.queryContractList()
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
||||
  表头搜索主要利用`header`插槽和`el-popover`组件实现。
|
||||
Reference in New Issue
Block a user