123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384 |
- <template>
- <div id="data-table">
- <el-form :model="searchInfo" :inline="true" style="padding:8px 0" size="mini">
- <el-row type="flex" justify="end">
- <el-col :span="22" v-if="useFilter">
- <el-form-item v-for="(item, index) in filterList" :key="index">
- <template v-if="item.filter === 'select'">
- <el-select
- v-model="searchInfo[item.prop]"
- size="mini"
- clearable
- filterable
- :placeholder="`请选择${item.label}`"
- @clear="toClear(item.prop)"
- @change="data => filterReturn(data, item)"
- >
- <slot name="options" v-bind="{ item }"></slot>
- </el-select>
- </template>
- <template v-else-if="item.filter === 'date'">
- <el-date-picker
- v-model="searchInfo[item.prop]"
- value-format="yyyy-MM-dd"
- format="yyyy-MM-dd"
- type="daterange"
- range-separator="-"
- start-placeholder="开始日期"
- end-placeholder="结束日期"
- clearable
- >
- </el-date-picker>
- </template>
- <template v-else>
- <el-input v-model="searchInfo[item.prop]" clearable size="mini" :placeholder="`请输入${item.label}`" @clear="toClear(item.prop)"></el-input>
- </template>
- </el-form-item>
- <el-form-item>
- <el-button type="primary" size="mini" @click="filterSearch">查询</el-button>
- </el-form-item>
- </el-col>
- <el-col :span="2" style="text-align:right">
- <slot name="selfbtn"></slot>
- </el-col>
- </el-row>
- </el-form>
- <el-table
- ref="table"
- row-key="id"
- :data="data"
- border
- stripe
- size="mini"
- :max-height="height !== null ? height : ''"
- @select="handleSelectionChange"
- @select-all="handleSelectAll"
- v-bind="options"
- :show-summary="useSum"
- @row-click="rowClick"
- :summary-method="computedSum"
- >
- <el-table-column type="selection" width="55" v-if="select" prop="id" :reserve-selection="true"> </el-table-column>
- <template v-for="(item, index) in fields">
- <template v-if="!item.notable">
- <template v-if="item.custom">
- <el-table-column :key="index" align="center" :label="item.label" v-bind="item.options" :show-overflow-tooltip="item.showTip || true">
- <template v-slot="{ row }">
- <slot name="custom" v-bind="{ item, row }"></slot>
- </template>
- </el-table-column>
- </template>
- <template v-else>
- <el-table-column
- :key="index"
- align="center"
- :label="item.label"
- :prop="item.prop"
- :formatter="toFormatter"
- :sortable="sortable"
- v-bind="item.options"
- :show-overflow-tooltip="item.showTip || true"
- >
- </el-table-column>
- </template>
- </template>
- </template>
- <template v-if="opera.length > 0">
- <el-table-column label="操作" align="center" :width="operaWidth">
- <template v-slot="{ row, $index }">
- <template v-for="(item, index) in opera">
- <template v-if="display(item, row)">
- <el-tooltip v-if="item.icon" :key="index" effect="dark" :content="item.label" placement="bottom">
- <el-button
- :key="index"
- type="text"
- :icon="item.icon || ''"
- size="mini"
- @click="handleOpera(row, item.method, item.confirm, item.methodZh, item.label, $index)"
- ></el-button>
- </el-tooltip>
- <!-- <el-button v-else :key="index" type="text" size="mini" @click="handleOpera(row, item.method, item.confirm, item.methodZh, item.label, $index)">
- {{ item.label }}
- </el-button> -->
- <el-link
- v-else
- :key="`${item.model}-column-${index}`"
- :type="item.type || 'primary'"
- :icon="item.icon || ''"
- size="mini"
- style="padding-right:10px"
- :underline="false"
- @click="handleOpera(row, item.method, item.confirm, item.methodZh, item.label, $index, item.confirmWord)"
- >
- {{ item.label }}
- </el-link>
- </template>
- </template>
- </template>
- </el-table-column>
- </template>
- </el-table>
- <el-row type="flex" align="middle" justify="end" style="padding-top:1rem" v-if="usePage">
- <el-col :span="24" style="text-align:right;">
- <el-pagination
- background
- layout="total, prev, pager, next"
- :page-sizes="[10, 15, 20, 50, 100]"
- :total="total"
- :page-size="limit"
- :current-page.sync="currentPage"
- @current-change="changePage"
- @size-change="sizeChange"
- >
- </el-pagination>
- <!-- sizes -->
- </el-col>
- </el-row>
- </div>
- </template>
- <script>
- import _ from 'lodash';
- export default {
- name: 'data-table',
- props: {
- fields: { type: Array, required: true },
- data: { type: Array, required: true },
- opera: { type: Array, default: () => [] },
- toFormat: null,
- height: null,
- select: { type: Boolean, default: false },
- selected: { type: Array, default: () => [] },
- usePage: { type: Boolean, default: true },
- total: { type: Number, default: 0 },
- options: null,
- useSum: { type: Boolean, default: false },
- sumcol: { type: Array, default: () => [] },
- sumres: { type: String, default: 'total' },
- filter: { type: Array, default: () => [] },
- operaWidth: { type: Number, default: 200 },
- sortable: { type: Boolean, default: true },
- limit: { type: Number, default: _.get(this, `$limit`, undefined) !== undefined ? this.$limit : process.env.VUE_APP_LIMIT * 1 || 10 },
- },
- components: {},
- data: () => ({
- pageSelected: [],
- currentPage: 1,
- // limit: _.get(this, `$limit`, undefined) !== undefined ? this.$limit : process.env.VUE_APP_LIMIT * 1 || 10,
- searchInfo: {},
- useFilter: true,
- filterList: [],
- }),
- created() {},
- computed: {},
- methods: {
- toFormatter(row, column, cellValue, index) {
- let this_fields = this.fields.filter(fil => fil.prop === column.property);
- if (this_fields.length > 0) {
- let format = _.get(this_fields[0], `format`, false);
- if (format) {
- let res;
- if (_.isFunction(format)) {
- res = format(cellValue);
- } else {
- res = this.toFormat({
- model: this_fields[0].prop,
- value: cellValue,
- });
- }
- return res;
- } else return cellValue;
- }
- },
- handleOpera(data, method, confirm = false, methodZh, label, index, confirmWord) {
- let self = true;
- if (_.isFunction(methodZh)) {
- methodZh = methodZh(data);
- } else if (!_.isString(methodZh)) {
- methodZh = label;
- self = false;
- }
- if (confirm) {
- let word = self ? methodZh : `您确认${methodZh}该数据?`;
- if (confirmWord) word = confirmWord;
- this.$confirm(word, '提示', {
- confirmButtonText: '确定',
- cancelButtonText: '取消',
- type: 'warning',
- })
- .then(() => {
- this.$emit(method, { data, index });
- })
- .catch(() => {});
- } else {
- this.$emit(method, { data, index });
- }
- },
- handleSelectionChange(selection, row) {
- // console.log(selection);
- // console.log(row);
- //根据row是否再pageSelected中,判断是添加还是删除
- let res = [];
- if (this.pageSelected.find(i => i.id === row.id)) {
- res = this.pageSelected.filter(f => f.id !== row.id);
- } else {
- this.pageSelected.push(row);
- res = this.pageSelected;
- }
- this.$set(this, `pageSelected`, res);
- this.$emit(`handleSelect`, _.uniqBy(res, 'id'));
- },
- handleSelectAll(selection) {
- //处于没全选状态,选择之后一定是全选,只有处于全选状态时,才会反选(全取消)
- // console.log(selection);
- let res = [];
- if (selection.length > 0) {
- //全选
- res = _.uniqBy(this.pageSelected.concat(selection), 'id');
- } else {
- //全取消
- res = _.differenceBy(this.pageSelected, this.data, 'id');
- }
- this.$set(this, `pageSelected`, res);
- this.$emit(`handleSelect`, res);
- },
- initSelection() {
- this.$nextTick(() => {
- this.$refs.table.clearSelection();
- this.selected.forEach(info => {
- let d = this.data.filter(p => p.id === info.id);
- if (d.length > 0) this.$refs.table.toggleRowSelection(d[0]);
- });
- });
- },
- selectReset() {
- this.$refs.table.clearSelection();
- },
- display(item, row) {
- let display = _.get(item, `display`, true);
- if (display === true) return true;
- else {
- let res = display(row);
- return res;
- }
- },
- //
- changePage(page = this.currentPage) {
- this.$emit('query', { skip: (page - 1) * this.limit, limit: this.limit, ...this.searchInfo });
- },
- sizeChange(limit) {
- this.limit = limit;
- this.currentPage = 1;
- this.$emit('query', { skip: 0, limit: this.limit, ...this.searchInfo });
- },
- getFilterList() {
- let res = this.fields.filter(f => _.get(f, 'filter', false));
- this.$set(this, `useFilter`, res.length > 0);
- res.map(i => {
- if (i.filter === 'date' && this.searchInfo[i.porp] === undefined) this.$set(this.searchInfo, i.prop, []);
- });
- res = [...res, ...this.filter];
- this.$set(this, `filterList`, res);
- },
- filterSearch() {
- this.currentPage = 1;
- this.$emit('query', { skip: 0, limit: this.limit, ...this.searchInfo });
- },
- rowClick(row, column, event) {
- this.$emit(`rowClick`, row);
- },
- toClear(prop) {
- delete this.searchInfo[prop];
- },
- filterReturn(data, item) {
- let { prop, filterReturn } = item;
- if (filterReturn) this.$emit('filterReturn', { data, prop });
- },
- // 计算合计
- computedSum({ columns, data }) {
- if (columns.length <= 0 || data.length <= 0) return '';
- const result = [];
- const reg = new RegExp(/^\d+$/);
- for (const column of columns) {
- // 判断有没有prop属性
- const prop = _.get(column, 'property');
- if (!prop) {
- result.push('');
- continue;
- }
- // 判断是否需要计算
- const inlist = this.sumcol.find(f => f == prop);
- if (!inlist) {
- result.push('');
- continue;
- }
- let res = 0;
- // 整理出要计算的属性(只取出数字或者可以为数字的值)
- const resetList = data.map(i => {
- const d = _.get(i, prop);
- const res = reg.test(d);
- if (res) return d * 1;
- else return 0;
- });
- if (this.sumres === 'total') {
- res = this.totalComputed(resetList);
- } else if (this.sumres === 'avg') {
- res = this.avgComputed(resetList);
- } else if (this.sumres === 'max') {
- res = this.maxComputed(resetList);
- } else if (this.sumres === 'min') {
- res = this.minComputed(resetList);
- }
- result.push(res);
- }
- result[0] = '合计';
- return result;
- },
- // 合计计算
- totalComputed(data) {
- const total = data.reduce((p, n) => p + n, 0);
- return total;
- },
- // 平均值计算
- avgComputed(data) {
- const total = this.totalComputed(data);
- return _.round(_.divide(total, data.length), 2);
- },
- // 最大值计算
- maxComputed(data) {
- return _.max(data);
- },
- // 最小值计算
- minComputed(data) {
- return _.min(data);
- },
- },
- watch: {
- selected: {
- handler(val) {
- if (val.length > 0) {
- this.pageSelected = val;
- this.initSelection();
- }
- },
- immediate: true,
- },
- data: {
- handler(val, oval) {
- if (this.select) {
- this.initSelection();
- }
- },
- },
- fields: {
- handler(val, oval) {
- if (val) this.getFilterList();
- },
- immediate: true,
- },
- },
- };
- </script>
- <style lang="less" scoped></style>
|