pc端element表格实现动态列及导出xlsx

一、首先实现动态列,为了防止刷新恢复初始状态,用pinia持久化存储

实现效果:

实现代码:

//主页面代码
//template
<el-button type="primary" @click="selectDialogRef.openDialog()"> 简表设置 </el-button>
<el-table :data="dataList">
  <el-table-column v-if="isShowColums('chineseName')" prop="chineseName" label="企业中文全称"/>
// .... 剩下的列以此类推   都用isShowColums传入绑定的属性名控制显示隐藏
</el-table>
<select-dialog ref="selectDialogRef"></select-dialog>
//js
import { xxxStore } from '/@/stores/xxxList';  // 替换自己的仓库名
const SelectDialog = defineAsyncComponent(() => import('./select.vue'));
const selectDialogRef = ref();
//控制列展示
function isShowColums(field: string) {
	return xxxStore().$state.xxxList.findIndex((a: string) => a == field) != -1;  
// findIndex找不到的话是-1  则会返回false  同理找到则为true
}
// 弹框插件子组件代码
<template>
	<el-dialog title="简表设置" v-model="visible" :close-on-click-modal="false" draggable>
		<!-- 列选择器 -->
		<el-checkbox-group v-model="selectedColumn">
			<el-checkbox v-for="col in columns" :key="col.prop" :label="col.prop">{{ col.label }}</el-checkbox>
		</el-checkbox-group>
		<template #footer>
			<span class="dialog-footer">
				<el-button @click="visible = false">取消</el-button>
				<el-button type="primary" @click="onSubmit" :disabled="loading">确认</el-button>
			</span>
		</template>
	</el-dialog>
</template>

<script setup lang="ts">
import { xxxStore } from '/@/stores/xxxList';
const xxx = xxxStore();
const loading = ref(false);
const visible = ref(false);
const selectedColumn = ref([]);
const columns = [
	// 这里写入表格对应的字段和中文名称
	{ label: '企业中文全称', prop: 'chineseName' },
	{ label: '组织机构代码', prop: 'organizationCode' },
    ......
];
// 打开弹窗
const openDialog = () => {
	visible.value = true;
	// 从仓库内获取表格展示信息
	selectedColumn.value = xxx.$state.xxxList;
};
// 提交
const onSubmit = async () => {
	try {
		loading.value = true;
		xxx.changeList(selectedColumn.value);
		useMessage().success('设置成功');
		visible.value = false;
	} catch (err: any) {
		console.error(err.msg);
	} finally {
		loading.value = false;
	}
};
// 暴露变量
defineExpose({
	openDialog,
});
</script>
//pinia仓库代码
//确认下载了pinia
import { defineStore } from 'pinia';

/**
 * 创建并导出字典存储的 Vue3 store 对象
 * @function
 *
 */
export const xxxStore = defineStore('xxxList', {
	state: () => ({
       //这里是设置默认展示的列
		xxxList: [
			'chineseName',
			'organizationCode',
            ......
		],
	}),
	actions: {
		getEnterpriseList() {
			return this.enterpriseList;
		},

		changetList(list: []) {
           //先清除再录入  防止数据一直加  当然可以用set处理 我不太精通就没用
			this.xxxList = [];
			this.xxxList = list;
		},
	},
	persist: {
		enabled: true, // 这个配置代表存储生效,而且是整个store都存储
	},
});

二、导出文件  后端给了接口   把选中的对象数组和选中的字段数组传给后端就可以返回文件流
 实现效果:

实现代码

//template
	<el-button type="primary" @click="exportExcel"> 导出 </el-button>
	<el-table
				:data="dataList"
				@selection-change="selectionChangHandle"
			>
   </el-table>
//js
const columns = [
	// 与子组件一样的数据列   这里使用主要是为了后端要中文字段
	{ label: '企业中文全称', prop: 'chineseName' },
	{ label: '组织机构代码', prop: 'organizationCode' },
    ........
];
// 多选事件
const selectionChangHandle = (objs:[]) => {
// 拿到选中对象数组
	selectObj.value = objs;
};
// 导出excel
const exportExcel = () => {
	// 中文字段名
	const newArray = xxxStore().$state.xxxList.map((prop) => {
		const column = columns.find((item) => item.prop === prop);
		return column ? column.label : null;
	});
	// 中文对象数组---保留原有字段顺序---这里是为了防止导出之后不按页面上表头顺序排列
	const selectArray = selectObj.value.map((item) => {
		const newItem = {};
		columns.forEach((column) => {
			const key = column.prop;
			if (item.hasOwnProperty(key)) {
				newItem[column.label] = item[key];
			}
		});
		return newItem;
	});
	// 过滤对象数组只保留需要的字段
	const filteredDataArray = selectArray.map((item) => {
		return newArray.reduce((acc, prop) => {
			if (item.hasOwnProperty(prop)) {
				acc[prop] = item[prop];
			}
			return acc;
		}, {});
	});
    //调用接口
	xxxApi({ fieldNames: newArray, data: filteredDataArray }).then((response) => {
		handleBlobFile(response, '示例.xlsx');  //
	});
};
function handleBlobFile(response: any, fileName: string) {
	// 处理返回的文件流
	const blob = response;
	console.info(blob);
	if (blob && blob.size === 0) {
		useMessage().error('内容为空,无法下载');
		return;
	}
	// debugger;
	if (blob.type === 'application/json') { 
		//说明有问题了
		blob.text().then((text:any) => {
			const jsonData = JSON.parse(text);
			// 现在,jsonData 是一个 JSON 对象
			if (jsonData.code === 1) { 
				useMessage().error(jsonData.msg);
			}
		});
	}
	const link = document.createElement('a');

	// 兼容一下 入参不是 File Blob 类型情况
	var binaryData = [] as any;
	binaryData.push(response);
	link.href = window.URL.createObjectURL(new Blob(binaryData));
	link.download = fileName;
	document.body.appendChild(link);
	link.click();
	window.setTimeout(function () {
		// @ts-ignore
		URL.revokeObjectURL(blob);
		document.body.removeChild(link);
	}, 0);
}

  • 7
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值