需求:el-tree目录实现搜索查询el-table表格项,双击表格项根据yiZhuMLID||muLuID定位el-tree目录,并且高亮展示在可视化区域内,再重新根据el-tree目录的yiZhuMLID搜索刷新el-table表格,定位且高亮展示相对应的yiZhuMLID的需求
1、先上DOM代码
<div class="main">
<div class="left">
<el-tree
ref="tree"
class="tree"
:data="labWorkOptions"
:props="defaultProps"
node-key="yiZhuMLID"
:default-expanded-keys="currentNodekey"
highlight-current
@node-click="handleNodeClick"
/>
</div>
<div class="center">
// 封装的el-table(后面加上)
<PublicTable
ref="multipleTable"
row-key="$multipleTable"
class="table"
:is-need-pagination="false"
:table-data="centerTableData"
:table-info="tableInfo"
:need-select="true"
:table-column="centerColumns"
:events="centerEvents"
:has-operation="false"
/>
<div class="centerSearch">
<el-input
v-model="queryString"
class=""
size="small"
clearable
placeholder="请输入格式拼音/五笔首码搜索"
@clear="onSearch"
@keyup.enter.native="onSearch"
/>
<el-button
size="small"
class="el-button-color"
style="margin-right: 10px"
icon="el-icon-search"
@click="onSearch"
>
查询
</el-button>
</div>
</div>
<div class="right">
<PublicTable
ref="publicTable"
class="table"
:is-need-pagination="false"
:table-data="rightData"
:table-info="tableInfo"
:table-column="rightColumns"
:has-operation="false"
/>
</div>
</div>
2、样式Style代码
<style lang="scss" scoped>
::v-deep .el-table__body-wrapper {
overflow: auto;
}
.title {
font-size: 15px;
font-weight: 600;
padding: 0 8px;
border-left: 3px solid #21c5c8;
}
.main {
display: flex;
width: 100%;
height: 100%;
.left {
flex: 1;
max-width: 25%;
overflow: auto;
::v-deep .tree {
height: 500px;
}
}
.center {
max-width: 29%;
height: 500px;
.centerSearch {
display: flex;
flex-direction: row;
}
.table {
height: calc(500px - 15px);
overflow: auto;
}
}
.right {
flex: 1;
max-width: 50%;
height: 500px;
}
}
::v-deep .handle-dialog {
height: 100%;
margin-top: 10px;
}
::v-deep .el-table__header-wrapper .el-checkbox {
display: none;
}
</style>
3、JS代码
<script>
import {
getHYXMMXWHByIdItem,
getItemByPinyinWubi
} from '@/api/menZhenAPI/huaYanjiChu/huaYanXMMLMXWH'
export default {
name: 'HuaYanMNKDDialog',
props: {
labWorkOptions: {
type: Array,
default: () => []
},
value: {
type: Boolean,
default: false
},
data: {
type: Object,
default: () => ({})
},
rightTableData: {
type: Array,
default: () => []
}
},
data() {
return {
currentNodekey: [],
formData: {},
yiZhuMLID: '',
queryString: '',
leftTableData: [],
centerTableData: [],
tableData: [],
defaultProps: {
children: 'children',
label: 'yiZhuMLMC'
},
addData: [],
tableInfo: {},
rightData: [],
leftEvents: {
'row-click': (row) => {
this.getHuaYanXMById(row)
}
},
centerEvents: {
select: (selection, row) => {
console.log('selection', selection)
console.log('row', row)
const flag = this.rightData.findIndex((item) => item.huaYanID === row.huaYanID)
if (flag === -1) {
if (row.lianDongHao !== null) {
this.centerTableData.forEach((item) => {
if (item.lianDongHao === row.lianDongHao) {
this.rightData.push({
muLuID: item.muLuId,
huaYanID: item.huaYanID,
huaYanXMMC: item.huaYanXMMC,
paiXu: item.paiXu,
lianDongHao: item.lianDongHao,
zhuCiXiang: null
})
console.log('item', item)
console.log('this.rightData', this.rightData)
}
})
} else {
this.rightData.push({
muLuID: row.muLuId,
huaYanID: row.huaYanID,
huaYanXMMC: row.huaYanXMMC,
paiXu: row.paiXu,
lianDongHao: row.lianDongHao,
zhuCiXiang: null
})
console.log(this.rightData)
}
} else {
if (row.lianDongHao === null) {
this.rightData.splice(flag, 1)
} else {
this.centerTableData.forEach((item) => {
if (item.lianDongHao === row.lianDongHao) {
const index = this.rightData.findIndex((item) => item.huaYanID === row.huaYanID)
this.rightData.splice(index, 1)
}
})
}
this.$refs.multipleTable.getTableRef().clearSelection()
}
this.chenckByHuaYanID()
},
// 这是主要方法其他地方的函数方法可以尽量不看
'row-dblclick': (row) => {
const currentKey = row.yiZhuMLID || row.muLuID
this.$nextTick(() => {
// tree节点的id
// this.currentNodekey = row.yiZhuMLID || row.muLuID
this.currentNodekey = []
for (let i = 0; i < this.$refs.tree.store._getAllNodes().length; i++) {
if (currentKey === this.$refs.tree.store._getAllNodes()[i].data.yiZhuMLID) {
this.$refs.tree.setCurrentKey(currentKey)
this.currentNodekey.push(currentKey)
}
}
getHYXMMXWHByIdItem(currentKey).then((res) => {
if (res.data) {
console.log(row)
this.centerTableData = res.data
this.chenckByHuaYanID()
// 获取数据后定位
setTimeout(() => {
this.$tools.tableLocateKey(
row.huaYanID,
'huaYanID',
this.centerTableData,
this.$refs['multipleTable'].$refs.tableData
)
}, 200)
// 让高亮元素出现在视图区域
document
.querySelector(
'.el-tree--highlight-current .el-tree-node.is-current>.el-tree-node__content'
)
.scrollIntoView()
}
})
})
}
},
leftColumns: [
{
label: '化验项目名称',
prop: 'mingCheng',
minWidth: '120px'
}
],
centerColumns: [
{
label: '请选择化验项目',
prop: 'huaYanXMMC',
minWidth: '120px'
}
],
rightColumns: [
{
prop: 'huaYanXMMC',
label: '化验项目名称',
minWidth: '150px'
},
{
prop: '',
label: '类别',
minWidth: '50px'
},
{
prop: '',
label: '医保类别',
minWidth: '80px'
},
{
prop: '',
label: '目录名称',
minWidth: '80px'
},
{
prop: '',
label: '状态标志',
minWidth: '80px'
},
{
prop: '',
label: '医嘱备注',
minWidth: '80px'
},
{
prop: '',
label: '首次录入时间',
minWidth: '120px'
},
{
prop: '',
label: '医嘱用户',
minWidth: '80px'
}
],
operations: [
{
text: '删除',
type: 'text',
class: 'el-text-color-del',
callback: (row) => {
this.delHandleCancelFormClick(row)
}
}
]
}
},
computed: {
visible: {
get() {
return this.value
},
set(value) {
this.$emit('update:value', false)
}
}
},
watch: {
visible(val) {
if (val) {
this.rightData = Object.assign([], this.rightTableData)
this.queryString = ''
} else {
this.centerTableData = []
}
}
},
created() {},
methods: {
onSearch() {
getItemByPinyinWubi({
key: this.queryString,
zhenLiaoLX: this.data.zhenLiaoLX
}).then((res) => {
if (res) {
this.centerTableData = res.data.map((item) => {
return {
huaYanID: item['huaYanID'],
huaYanXMMC: item['huaYanMC'],
yiZhuMLID: item['yiZhuMLID'],
yiZhuMLMC: item['yiZhuMLMC']
}
})
this.queryString = ''
}
})
},
}
}
</script>
4、el-table的封装
<template>
<div class="table-box">
<el-table
ref="tableData"
v-loading="loading"
style="width: 100%"
:row-key="rowKey"
:data="tableData"
:height="tableHeight"
highlight-current-row
v-bind="tableInfo"
:span-method="objectSpanMethod"
v-on="events"
@selection-change="handleSelectionChange"
>
<slot name="expand" />
<el-table-column v-if="selectAllTemplate" min-width="140" label="全选模板列表">
<template slot-scope="{ row }">
<div>
<el-checkbox
v-model="row.all"
@change="muBanAllToggleSelection($event, tableData, row)"
>
{{ row.muBanMC }}
</el-checkbox>
</div>
</template>
</el-table-column>
<!-- 多选 -->
<el-table-column
v-if="needSelect"
type="selection"
reserve-selection
width="55"
align="center"
/>
<el-table-column v-if="hasIndex" label="序号" width="50" type="index" />
<template v-for="(item, index) in tableColumn">
<!-- 此列需要自定义 -->
<el-table-column
v-if="item.isSlot"
:key="'%' + index"
:show-overflow-tooltip="showOverflowTooltip"
v-bind="item"
:render-header="item.renderHeader"
v-on="events"
>
<template slot-scope="{ row, $index }">
<ex-slot
v-if="item.render"
:render="item.render"
:row="row"
:index="$index"
:column="item"
:class="item.prop"
:default-value="item.defaultValue"
/>
<slot v-else :name="item.prop" :row="row" />
</template>
</el-table-column>
<!-- 正常列 -->
<el-table-column
v-else
:key="'%' + index"
:show-overflow-tooltip="showOverflowTooltip"
v-bind="item"
v-on="events"
/>
</template>
<el-table-column v-if="hasOperation" fixed="right" label="操作" :min-width="operationWidth">
<!-- <template v-if="!btnButton || btnButton.length === 0" slot-scope="scope">
<slot name="operation" :row="scope.row" :index="scope.$index" />
</template> -->
<template v-if="btnButton.length" slot-scope="{ row, column, $index }">
<el-button
v-for="(value, i) in btnButton"
:key="'$' + i"
size="small"
:type="value.type"
:icon="value.icon"
:class="value.class"
@click="value.callback(row, column, $index)"
>
{{ value.text }}
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<div
v-if="isNeedPagination"
style="display: flex; justify-content: flex-end; align-item: centerl; padding-top: 15px"
>
<el-pagination
ref="pagination"
:page-sizes="pageSizes"
:page-size.sync="computedPageSize"
:hide-on-single-page="isSinglePageHide"
layout="total, sizes, prev, pager, next, jumper"
:current-page.sync="computedCurrentPage"
:total="total"
:pager-count="pagerCount"
@current-change="currentChange"
@size-change="sizeChange"
/>
</div>
</div>
</template>
<script>
// 自定义组件的内容
const exSlot = {
functional: true,
props: {
row: Object,
render: Function,
index: Number,
column: {
type: Object,
default: null
},
defaultValue: [Number, String]
},
render: (h, ctx) => {
const params = {
row: ctx.props.row,
index: ctx.props.index
}
const defaultValue = ctx.props.defaultValue
params.column = ctx.props.column || {}
return h(
'div',
{
class: [
params.column.prop || '',
params.column.class || params.column.className || ''
].join('')
},
[ctx.props.render(h, params) || defaultValue]
)
}
}
export default {
name: 'PublicTable',
components: {
'ex-slot': exSlot
},
props: {
// key
rowKey: {
type: String,
default: ''
},
// 超出行是否隐藏不换行
showOverflowTooltip: {
type: Boolean,
default: true
},
// 是否需要多选
needSelect: {
type: Boolean,
default: false
},
// 是否需要序号
hasIndex: {
type: Boolean,
default: false
},
// 是否需要分页
isNeedPagination: {
type: Boolean,
default: true
},
// 是否单页隐藏,默认为true
isSinglePageHide: {
type: Boolean,
default: false
},
// 当前页页码,支持.sync修饰符
currentPage: {
type: Number,
default: 1
},
// 页码显示数据量
pagerCount: {
type: Number,
default: 7
},
// 每页数据条数, 支持.sync修饰符默认为每页10条
pageSize: {
type: Number,
default: 20
},
// 数据总条数
total: {
type: Number,
default: 0
},
// 每页多少数据
pageSizes: {
type: Array,
required: false,
default: () => [20, 40, 80, 100]
},
tableInfo: {
type: Object,
default: () => {}
},
// 获取数据时是否需要加载loading
loading: {
type: Boolean,
default: false
},
tableData: {
type: Array,
default: () => []
},
// 表格展示数据
tableColumn: {
type: Array,
default: () => []
},
// 是否需要操作列
hasOperation: {
type: Boolean,
default: true
},
// 操作列
btnButton: {
type: Array,
default: () => []
},
// 操作列宽度
operationWidth: {
type: String,
default: '120px'
},
// 表格方法
events: {
type: Object,
default: () => {}
},
templateSelectAll: {
type: Boolean,
default: false
},
// 合并单元格
objectSpanMethod: {
type: Function,
default: () => {}
},
muBanAllToggleSelection: {
type: Function,
default: () => {}
},
selectAllTemplate: {
type: Boolean,
default: false
}
},
data() {
return {}
},
computed: {
computedCurrentPage: {
get() {
return this.currentPage
},
set(val) {
this.$emit('update:currentPage', val)
}
},
computedPageSize: {
get() {
return this.pageSize
},
set(val) {
this.$emit('update:pageSize', val)
}
},
tableHeight() {
return !this.isNeedPagination ? '100%' : 'calc(100% - 47px)'
}
},
mounted() {},
methods: {
getTableRef() {
return this.$refs.tableData
},
getRefPagination() {
return this.$refs.pagination
},
// 页面切换事件 通过 @currentChange 绑定
currentChange(val) {
this.$emit('currentChange', val)
},
// 每页条数切换事件,通过@sizeChange 绑定
sizeChange(val) {
this.$emit('sizeChange', val)
},
handleSelectionChange(val) {
this.$emit('selectionChange', val)
}
}
}
</script>
<style lang="scss" scoped>
.table-box {
flex: 1;
overflow: hidden;
width: 100%;
height: 100%;
}
</style>
5、el-table定位数据高亮的方法
/**
* table表格数据定位
* @param {value} 查询的value唯一值
* @param {tabKey} tableData数据中的key属性
* @param {tableData} table表格数据源tableData
* @param {tableRefs} table表格标签tableRefs
* @returns
*/
function tableLocateKey(value, tabKey, tableData, tableRefs) {
let index = tableData.findIndex((i) => {
return value === i[tabKey]
})
let vm = tableRefs.$el
vm.querySelectorAll('.el-table__body tr')[index].scrollIntoView()
//让定位到的这条数据产生高亮效果
tableRefs.setCurrentRow(tableData[index])
}