|
@@ -0,0 +1,294 @@
|
|
|
+<template>
|
|
|
+ <div id="c-table">
|
|
|
+ <el-table
|
|
|
+ ref="table"
|
|
|
+ :row-key="rowKey"
|
|
|
+ :data="data"
|
|
|
+ border
|
|
|
+ stripe
|
|
|
+ size="mini"
|
|
|
+ :max-height="height !== null ? height : ''"
|
|
|
+ @select="handleSelectionChange"
|
|
|
+ @select-all="handleSelectAll"
|
|
|
+ :show-summary="useSum"
|
|
|
+ @row-click="rowClick"
|
|
|
+ :summary-method="computedSum"
|
|
|
+ >
|
|
|
+ <el-table-column type="selection" width="55" v-if="select" :prop="rowKey" :reserve-selection="true"> </el-table-column>
|
|
|
+ <template v-for="(item, index) in fields">
|
|
|
+ <template v-if="item.custom">
|
|
|
+ <el-table-column
|
|
|
+ :key="index"
|
|
|
+ align="center"
|
|
|
+ :label="item.label"
|
|
|
+ v-bind="item.options"
|
|
|
+ :show-overflow-tooltip="item.showTip === false ? item.showTip : true"
|
|
|
+ >
|
|
|
+ <template v-slot="{ row }">
|
|
|
+ <slot :name="item.model" 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.model"
|
|
|
+ :formatter="toFormatter"
|
|
|
+ :sortable="true"
|
|
|
+ v-bind="item.options"
|
|
|
+ :show-overflow-tooltip="item.showTip === false ? item.showTip : true"
|
|
|
+ >
|
|
|
+ </el-table-column>
|
|
|
+ </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)">
|
|
|
+ <template v-if="vOpera">
|
|
|
+ <el-link
|
|
|
+ v-opera="item.method"
|
|
|
+ :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 v-else>
|
|
|
+ <el-link
|
|
|
+ :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>
|
|
|
+ </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="sizes,total, prev, pager, next"
|
|
|
+ :page-sizes="[10, 50, 100, 150, 200]"
|
|
|
+ :total="total"
|
|
|
+ :page-size="limit"
|
|
|
+ :current-page.sync="currentPage"
|
|
|
+ @current-change="changePage"
|
|
|
+ @size-change="sizeChange"
|
|
|
+ >
|
|
|
+ </el-pagination>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+export default {
|
|
|
+ name: 'c-table',
|
|
|
+ props: {
|
|
|
+ fields: { type: Array, required: true },
|
|
|
+ data: { type: Array, required: true },
|
|
|
+ opera: { type: Array, default: () => [] },
|
|
|
+ rowKey: { type: String, default: '_id' },
|
|
|
+ select: { type: Boolean, default: false },
|
|
|
+ selected: { type: Array, default: () => [] },
|
|
|
+ usePage: { type: Boolean, default: true },
|
|
|
+ total: { type: Number, default: 0 },
|
|
|
+ useSum: { type: Boolean, default: false },
|
|
|
+ sumcol: { type: Array, default: () => [] },
|
|
|
+ sumres: { type: String, default: 'total' },
|
|
|
+ // limit: { type: Number, default: 10 },
|
|
|
+ height: null,
|
|
|
+ operaWidth: { type: Number, default: 200 },
|
|
|
+ vOpera: { type: Boolean, default: false },
|
|
|
+ },
|
|
|
+ components: {},
|
|
|
+ data: function () {
|
|
|
+ return {
|
|
|
+ pageSelected: [],
|
|
|
+ currentPage: 1,
|
|
|
+ limit: this.$limit,
|
|
|
+ };
|
|
|
+ },
|
|
|
+ created() {},
|
|
|
+ methods: {
|
|
|
+ toFormatter(row, column, cellValue, index) {
|
|
|
+ let this_fields = this.fields.filter((fil) => fil.model === 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].model,
|
|
|
+ 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) {
|
|
|
+ //根据row是否再pageSelected中,判断是添加还是删除
|
|
|
+ let isSelecteds = _.cloneDeep(this.pageSelected);
|
|
|
+ const is_has = isSelecteds.findIndex((f) => f[this.rowKey] === row[this.rowKey]);
|
|
|
+ if (is_has <= -1) {
|
|
|
+ // 没有找到,属于添加
|
|
|
+ isSelecteds.push(row);
|
|
|
+ } else {
|
|
|
+ // 找到了,删除
|
|
|
+ isSelecteds.splice(is_has, 1);
|
|
|
+ }
|
|
|
+ this.$set(this, 'pageSelected', isSelecteds);
|
|
|
+ this.$emit(`handleSelect`, isSelecteds);
|
|
|
+ },
|
|
|
+ handleSelectAll(selection) {
|
|
|
+ //处于没全选状态,选择之后一定是全选,只有处于全选状态时,才会反选(全取消)
|
|
|
+ // console.log(selection);
|
|
|
+ let res = [];
|
|
|
+ if (selection.length > 0) {
|
|
|
+ //全选
|
|
|
+ res = _.uniqBy(this.pageSelected.concat(selection), this.rowKey);
|
|
|
+ } else {
|
|
|
+ //全取消
|
|
|
+ res = _.differenceBy(this.pageSelected, this.data, this.rowKey);
|
|
|
+ }
|
|
|
+ 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();
|
|
|
+ },
|
|
|
+ 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 });
|
|
|
+ },
|
|
|
+ rowClick(row, column, event) {
|
|
|
+ this.$emit(`rowClick`, row);
|
|
|
+ },
|
|
|
+ display(item, row) {
|
|
|
+ let display = _.get(item, `display`, true);
|
|
|
+ if (display === true) return true;
|
|
|
+ else {
|
|
|
+ let res = display(row);
|
|
|
+ return res;
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 计算合计
|
|
|
+ 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);
|
|
|
+ return d * 1;
|
|
|
+ });
|
|
|
+ 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) {
|
|
|
+ // console.log(data);
|
|
|
+ const total = data.reduce((p, n) => p + parseFloat(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);
|
|
|
+ },
|
|
|
+ },
|
|
|
+};
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="less" scoped></style>
|