<template>
<el-card shadow="never" class="vxe-table-demo">
<me-vxe-table
ref="meVxeTableRef"
v-model:quick-search="searchForm.search"
:loading="loading"
:data="data?.list"
:footer-method="footerMethod"
:edit-config="{ trigger: 'click', mode: 'row', showStatus: true }"
:print="print"
:pagination-options="paginationOptions"
stripe
height="600px"
me-class="table"
border
show-overflow
show-footer
keep-source
class="my-xtable-element"
@refresh="getData"
@quick-search="getData(1)"
>
<template #search>
<el-form ref="searchRef" :model="searchForm" inline label-width="100px" class="search">
<el-form-item label="名称" prop="name">
<el-input v-model="searchForm.name" />
</el-form-item>
<el-form-item label="类型" prop="type">
<el-select v-model="searchForm.type" clearable>
<el-option label="类型1" value="1" />
<el-option label="类型2" value="2" />
</el-select>
</el-form-item>
<el-form-item label="日期" prop="date">
<el-date-picker v-model="searchForm.date" type="date" />
</el-form-item>
<el-form-item label="地址" prop="address">
<el-input v-model="searchForm.address" />
</el-form-item>
<el-form-item label="邮政编码" prop="zip">
<el-input v-model="searchForm.zip" />
</el-form-item>
<el-form-item label=" ">
<el-button type="primary" @click="getData(1)">查询</el-button>
<el-button @click="()=>($refs.searchRef as FormInstance).resetFields()">重置</el-button>
</el-form-item>
</el-form>
</template>
<template #buttons>
<el-button @click="() => (print = print ? false : {})">打印显/隐</el-button>
<el-button @click="xTable!.clearCheckboxRow()">全选清空</el-button>
</template>
<vxe-column type="checkbox" width="60"></vxe-column>
<vxe-column type="seq" width="80">
<template #header>
<span>序号</span>
<i class="el-icon-question"></i>
</template>
</vxe-column>
<vxe-colgroup title="Group1">
<vxe-column field="name" title="ElInput" min-width="140" :edit-render="{}">
<template #edit="scope">
<el-input v-model="scope.row.name" @input="xTable!.updateStatus(scope)"></el-input>
</template>
</vxe-column>
<vxe-column field="role" title="ElAutocomplete" min-width="160" :edit-render="{}">
<template #edit="{ row }">
<el-autocomplete v-model="row.role" :fetch-suggestions="roleSearchEvent"></el-autocomplete>
</template>
</vxe-column>
<vxe-column field="age" title="ElInputNumber" width="160" :edit-render="{}">
<template #header="{ column }">
<span>{{ column.title }}</span>
<i class="el-icon-warning"></i>
</template>
<template #edit="{ row }">
<el-input-number v-model="row.age" :max="99" :min="18"></el-input-number>
</template>
</vxe-column>
<vxe-colgroup title="Group2">
<vxe-column field="sex" title="ElSelect" width="140" :edit-render="{}">
<template #edit="scope">
<el-select v-model="scope.row.sex" @change="xTable!.updateStatus(scope)">
<el-option
v-for="item in demo1.sexList"
:key="item.value"
:label="item.label"
:value="item.value"
></el-option>
</el-select>
</template>
<template #default="{ row }">{{ getSelectLabel(row.sex, demo1.sexList) }}</template>
</vxe-column>
<vxe-column field="sex1" title="ElSelect" width="180" :edit-render="{}">
<template #edit="scope">
<el-select v-model="scope.row.sex1" multiple>
<el-option
v-for="item in demo1.sexList"
:key="item.value"
:label="item.label"
:value="item.value"
></el-option>
</el-select>
</template>
<template #default="{ row }">{{ getSelectMultipleLabel(row.sex1, demo1.sexList) }}</template>
</vxe-column>
<vxe-column field="region" title="ElCascader" width="200" :edit-render="{}">
<template #edit="{ row }">
<el-cascader v-model="row.region" :options="demo1.regionList"></el-cascader>
</template>
<template #default="{ row }">{{ getCascaderLabel(row.region, demo1.regionList) }}</template>
</vxe-column>
</vxe-colgroup>
</vxe-colgroup>
<vxe-colgroup title="Group1">
<vxe-column field="date" title="ElDatePicker" width="200" :edit-render="{}">
<template #edit="{ row }">
<el-date-picker v-model="row.date" type="date" format="YYYY/MM/DD"></el-date-picker>
</template>
<template #default="{ row }">{{ formatDate(row.date, 'YYYY/MM/DD') }}</template>
</vxe-column>
<vxe-column field="date1" title="ElDatePicker" width="220" :edit-render="{}">
<template #edit="{ row }">
<el-date-picker v-model="row.date1" type="datetime" format="YYYY-MM-DD HH:mm:ss"></el-date-picker>
</template>
<template #default="{ row }">{{ formatDate(row.date1, 'YYYY-MM-DD HH:mm:ss') }}</template>
</vxe-column>
<vxe-column field="date2" title="ElTimePicker" width="200" :edit-render="{}">
<template #edit="{ row }">
<el-time-select
v-model="row.date2"
:picker-options="{ start: '08:30', step: '00:15', end: '18:30' }"
></el-time-select>
</template>
</vxe-column>
<vxe-column field="color1" title="ElColorPicker" width="140" :edit-render="{}">
<template #edit="{ row }">
<el-color-picker v-model="row.color1"></el-color-picker>
</template>
</vxe-column>
<vxe-column field="rate" title="ElRate" width="200">
<template #default="{ row }">
<el-rate v-model="row.rate"></el-rate>
</template>
</vxe-column>
<vxe-column field="flag" title="ElSwitch" width="100">
<template #default="{ row }">
<el-switch v-model="row.flag"></el-switch>
</template>
</vxe-column>
</vxe-colgroup>
</me-vxe-table>
</el-card>
</template>
<script setup lang="ts" name="VxeTableDemo">
import { VxeTablePropTypes } from 'vxe-table';
import XEUtils from 'xe-utils';
import { FormInstance } from 'element-plus';
import { listApi } from '@/api/vxeTable';
const meVxeTableRef = ref<MeVxeTableInstance>();
const xTable = computed(() => meVxeTableRef.value?.vxeTableRef);
const restaurants = [
{ value: 'Designer', name: 'Designer' },
{ value: 'Develop', name: 'Develop' },
{ value: 'Test', name: 'Test' },
{ value: 'PM', name: 'PM' },
];
const demo1 = {
sexList: [
{ value: '1', label: '男' },
{ value: '0', label: '女' },
],
regionList: [
{
label: '北京',
value: 1,
children: [
{ value: 3, label: '东城区' },
{ value: 4, label: '西城区' },
],
},
{
label: '上海',
value: 21,
children: [
{ value: 23, label: '黄浦区' },
{ value: 24, label: '卢湾区' },
],
},
{
label: '广东',
value: 42,
children: [
{ value: 43, label: '广州市' },
{ value: 67, label: '深圳市' },
],
},
],
};
const formatDate = (value: any, format: string) => {
return XEUtils.toDateString(value, format);
};
const getSelectLabel = (value: any, list: any[], valueProp = 'value', labelField = 'label') => {
const item = list.find((item) => item[valueProp] === value);
return item ? item[labelField] : null;
};
const getSelectMultipleLabel = (value: any[], list: any[], valueProp = 'value', labelField = 'label') => {
return value
.map((val) => {
const item = list.find((item) => item[valueProp] === val);
return item ? item[labelField] : null;
})
.join(', ');
};
const getCascaderLabel = (value: any, list: any[]) => {
const values: any[] = value || [];
const labels: any[] = [];
const matchCascaderData = function (index: any, list: any[]) {
const val = values[index];
if (list && values.length > index) {
list.forEach((item) => {
if (item.value === val) {
labels.push(item.label);
matchCascaderData(++index, item.children);
}
});
}
};
matchCascaderData(0, list);
return labels.join(' / ');
};
const roleSearchEvent = (queryString: string, cb: (params: any) => void) => {
const results = queryString
? restaurants.filter((item) => item.name.toLowerCase().indexOf(queryString.toLowerCase()) === 0)
: restaurants;
setTimeout(() => {
cb(results);
}, 500 * Math.random());
};
const meanNum = (list: any[], field: string) => {
let count = 0;
list.forEach((item) => {
count += Number(item[field]);
});
return count / list.length;
};
const sumNum = (list: any[], field: string) => {
let count = 0;
list.forEach((item) => {
count += Number(item[field]);
});
return count;
};
const footerMethod: VxeTablePropTypes.FooterMethod = ({ columns, data }) => {
return [
columns.map((column, columnIndex) => {
if (columnIndex === 0) {
return '平均';
}
if (['age', 'rate'].includes(column.property)) {
return meanNum(data, column.property);
}
return null;
}),
columns.map((column: any, columnIndex: number) => {
if (columnIndex === 0) {
return '和值';
}
if (['age', 'rate'].includes(column.property)) {
return sumNum(data, column.property);
}
return null;
}),
];
};
const searchForm = reactive({
name: '',
search: '',
type: undefined,
date: '',
address: '',
zip: '',
page: 1,
size: 10,
});
const { loading, run, data } = listApi({ defaultParams: [searchForm], manual: false });
const getData = (page = searchForm.page, size = searchForm.size) => {
run(Object.assign(searchForm, { page, size }));
};
const paginationOptions = reactive({
currentPage: computed(() => searchForm.page),
pageSize: computed(() => searchForm.size),
total: computed(() => data.value?.count ?? 0),
change: getData,
});
const print = ref({} as object | boolean);
</script>
<style lang="scss" scoped>
.vxe-table-demo {
.search {
:deep(.el-form-item) {
width: 319px;
}
}
}
</style>