<template> <div> <ns-view-list-table v-bind="tableConfig" :model="data" ref="mainRef" :scroll="{ x: 1500, y: 350 }"> </ns-view-list-table> <!-- 新增数据库数据 --> <a-drawer :width="500" :visible="visible" :body-style="{ paddingBottom: '80px' }" :footer-style="{ textAlign: 'right' }" destroyOnClose @close="onClose"> <div class="ns-form-title"><div class="title">能源种类</div></div> <a-form ref="formRef" :model="formState" :rules="rules" :label-col="labelCol" :wrapper-col="wrapperCol"> <a-form-item ref="name" label="能耗名称" name="energyType"> <a-input v-model:value="formState.energyType" @keydown="handleKeyDown" :maxlength="10" placeholder="请输入能源种类" /> </a-form-item> <a-form-item label="计量单位" name="unit"> <a-cascader v-model:value="formState.unit" :options="measurementUnit" /> </a-form-item> <a-form-item label="能耗类型"> <a-select v-model:value="formState.energyConsumptionType" @change="changeEnergyType" placeholder="请选择能耗类型"> <a-select-option v-for="(item, index) in energyTypeOptions" :key="index" :value="item.dicKey"> {{ item.cnValue }} </a-select-option> </a-select> </a-form-item> <a-form-item label="自动采集节点" name="collectionNode"> <a-tree-select v-model:value="formState.collectionNode" :tree-line="true" :tree-data="treeData"> </a-tree-select> </a-form-item> <a-form-item label="计算碳排" name="isComputeCarbon"> <a-radio-group v-model:value="formState.isComputeCarbon" @change="changeRadio"> <a-radio :value="0">是</a-radio> <a-radio :value="1">否</a-radio> </a-radio-group> </a-form-item> <a-form-item label="排放类型" name="emissionType" :required="isRequired" v-if="isRequired"> <a-select v-model:value="formState.emissionType" placeholder="请选择排放类型" :disabled="!isRequired"> <a-select-option v-for="(item, index) in emissionTypeDic" :key="index" :value="item.id"> {{ item.cnValue }} </a-select-option> </a-select> </a-form-item> </a-form> <div class="ns-form-title"><div class="title">能耗统计</div></div> <a-table :columns="addColumns" :data-source="addData" size="small" :pagination="false"> <template #bodyCell="{ column, text, record }"> <template v-if="column.key === 'action'"> <a-switch :checked="record.type === 1 ? true : false" :class="{ 'blue-background': record.type === 1 ? true : false, 'grey-background': record.type === 1 ? false : true, }" @click="changeSwitch(record)" /> </template> </template> </a-table> <div class="ns-form-title" style="display: flex"> <div class="title">凭证上传</div> </div> <a-upload :file-list="fileList" name="file" accept=".pdf" @remove="handleFileRemove" :before-upload="beforeUpload" @change="handleChange"> <a-button style="margin-left: 6px; color: #4f95ff; border-color: #4f95ff"> <upload-outlined></upload-outlined> 上传凭证 </a-button> </a-upload> <div style=" display: flex; flex-direction: column; border-radius: 4px; background: rgba(250, 250, 250, 1); color: rgba(153, 153, 153, 1); padding: 5px; "> <span>1.仅支持pdf格式文件或文件夹</span> <span>2.文件名命名规则为【能源种类_年份】</span> <span>3.每次上传自动覆盖</span> </div> <template #footer> <a-button style="margin-right: 8px" @click="onClose">取消</a-button> <a-button type="primary" @click="onSubmit">确定</a-button> </template> </a-drawer> <!-- 上传凭证弹窗 --> <!-- <a-modal :visible="openUpload" title="凭证上传" @ok="handleOk" @cancel="closeOpenUpload"> <a-upload-dragger v-model:fileList="fileList" name="file" :multiple="true" action="https://www.mocky.io/v2/5cc8019d300000980a055e76" @change="handleChange" @drop="handleDrop" > <p class="ant-upload-drag-icon"> <inbox-outlined></inbox-outlined> </p> <p class="ant-upload-hint" style="display: flex;flex-direction: column;"> <p>1.仅支持pdf格式文件或文件夹</p> <p>2.文件命名规则为【能源种类_年份】</p> <p>3.每次上传自动覆盖</p> </p> </a-upload-dragger> </a-modal> --> <!-- 凭证下载 --> <a-drawer :visible="downLoadVisible" :width="500" @close="onCloseDownLoad" :footer-style="{ textAlign: 'right' }"> <div class="ns-form-title" style="display: flex"> <div class="title">凭证列表</div> <a-button type="primary" ghost style="margin-left: 16px" @click="onSubmitDownLoad" :disabled="selectedRowKeysSet.length === 0"> 批量下载 </a-button> </div> <a-table :columns="downLoadColumns" :data-source="downLoadData" bordered rowKey="id" :rowSelection="{ selectedRowKeys: selectedRowKeysSet, onChange: onSelectionChangeSet, }" style="margin-top: 15px" :pagination="false"> <template #bodyCell="{ column, text, record }"> <template v-if="column.key === 'action'"> <span> <a @click="downLoad(record)">下载</a> </span> </template> </template> </a-table> <template #footer> <a-button style="margin-right: 8px" @click="onCloseDownLoad">取消</a-button> <a-button type="primary" @click="onSubmitDownLoad">确定</a-button> </template> </a-drawer> </div> </template> <script lang="ts" setup> import { ref, toRaw, defineExpose, createVNode } from 'vue'; import type { Rule } from 'ant-design-vue/es/form'; import { Pagination, message, Modal, Upload } from 'ant-design-vue'; import { UploadOutlined } from '@ant-design/icons-vue'; import type { TreeSelectProps, UploadChangeParam, UploadProps } from 'ant-design-vue'; import { NsMessage } from '/nerv-lib/component'; import dayjs, { Dayjs } from 'dayjs'; import { http } from '/nerv-lib/util/http'; import { Cookies } from '/nerv-lib/util/cookie'; import { tableColumns } from '../config'; import { energyConsumption, carbonEmissionFactorLibrary, uploadPic, } from '/@/api/carbonEmissionFactorLibrary'; import { dict } from '/@/api'; import { group } from '/@/api/deviceManage'; defineOptions({ energyType: 'EnergyConsumption', // 与页面路由name一致缓存才可生效 components: { 'a-pagination': Pagination, }, }); const orgId = ref(''); const result = JSON.parse(sessionStorage.getItem('ORGID')!); orgId.value = result; const fetch = (api, params = { orgId }, config) => { return http.post(api, params, config); }; const selectYear = ref<Dayjs>(dayjs(new Date().getFullYear().toString())); const total = ref<number>(); const queryParams = ref({ pageNum: 1, pageSize: 10, orgId: orgId.value, year: selectYear.value.format('YYYY'), }); const isRequired = ref(false); const visible = ref(false); const openUpload = ref<boolean>(false); const data = ref([]); interface FormState { energyType: string; unit: string; collectionNode: string; emissionType: string | undefined; isComputeCarbon: string; janFlag: string; febFlag: string; marFlag: string; aprFlag: string; mayFlag: string; junFlag: string; julFlag: string; augFlag: string; sepFlag: string; octFlag: string; novFlag: string; decFlag: string; } const formRef = ref(); const labelCol = { span: 5 }; const wrapperCol = { span: 19 }; const switchLabelCol = { span: 10 }; const switchWrapperCol = { span: 14 }; const formState = ref({ orgId: orgId.value, }); // 定义form表单的必填 const rules: Record<string, Rule[]> = { energyType: [{ required: true, message: '请输入能源种类', trigger: 'change' }], isComputeCarbon: [{ required: true, message: '请选择是否计算碳排', trigger: 'change' }], unit: [{ required: true, message: '请选择计量单位', trigger: 'change' }], }; const handleKeyDown = (event: KeyboardEvent) => { // Check if the pressed key is a space if (event.code === 'Space') { event.preventDefault(); } }; // 排放类型的变量 const emissionTypeDic = ref(); // 计量单位的变量 const measurementUnit = ref([]); // 定义自动采集节点数的变量 const treeData = ref<TreeSelectProps['treeData']>([]); // 年份选择改变触发 const changeYearData = () => { queryParams.value.year = selectYear.value; // getTableList(); }; const mainRef = ref(); const year = selectYear.value.format('YYYY'); const tableConfig = ref({ title: '能耗统计', api: energyConsumption.pageList, params: queryParams.value, rowSelection: null, headerActions: [ { label: '新增', name: 'userAdd', type: 'primary', handle: () => { getDictList(); getSummaryMethod(); visible.value = true; }, }, { label: '导入', type: 'primary', name: 'energyConsumptionImport', extra: { api: energyConsumption.import, // 导入接口名 params: { orgId, year, }, title: '碳排统计', // 弹窗title templateName: 'energyConsumption', // 所使用的文件名称 indexName: '能源种类', // 匹配类型字段 message: [ { label: '1、若必填项未填写,则不能进行导入操作' }, { label: `2、当重复时,则更新数据。` }, { label: '3、数据将从模版的第五行进行导入。' }, { label: '4、文件导入勿超过5MB。' }, ], }, }, { label: '导出', type: 'primary', handle: () => { const exportQuery = { orgId: orgId.value, year: mainRef.value.nsTableRef.formParamsRef.year ? mainRef.value.nsTableRef.formParamsRef.year : selectYear.value.format('YYYY'), }; const config = { responseType: 'blob', }; fetch(energyConsumption.export, exportQuery, config) .then((res) => { // 创建一个 URL 对象,指向图片数据的 blob const url = window.URL.createObjectURL(new Blob([res])); // 创建一个 <a> 标签,用于触发下载 const link = document.createElement('a'); link.href = url; link.setAttribute('download', '能耗统计导出.xlsx'); // 设置下载的文件名 document.body.appendChild(link); link.click(); // 清理 URL 对象 window.URL.revokeObjectURL(url); }) .catch((error) => { console.error('下载失败:', error); }); }, }, // { // label: '模板下载', // type: 'primary', // handle: () => { // doWnload('/hx-ai-intelligent/asset/file/energyConsumption.xlsx'); // }, // }, // { // label: '上传凭证', // type: 'primary', // handle: () => { // openUpload.value = true; // }, // }, { label: '凭证下载', type: 'primary', handle: () => { fetch(energyConsumption.voucherDownloadList, { bizType: 3, orgId: orgId.value, year: tableConfig.value.params.year, }).then((res) => { downLoadData.value = res.data; }); downLoadVisible.value = true; }, }, ], columns: [ { title: '序号', customRender: (text: any) => { return text.index + 1; }, width: 100, }, { title: '能源种类', dataIndex: 'energyType', width: 100, ellipsis: true, }, { title: '计量单位', className: 'unitName', dataIndex: 'unitName', width: 100, }, { title: '全年', dataIndex: 'yearly', width: 100, }, { title: '1月', dataIndex: 'jan', width: 100, customRender: (value) => { let text; let color; switch (value.record.janFlag) { case 1: text = value.record.jan ? value.record.jan : ''; color = 'rgba(243, 97, 99, 1)'; break; case 0: text = value.record.jan ? value.record.jan : ''; color = 'rgba(57, 215, 187, 1)'; break; } // 使用内联样式设置颜色 return createVNode('div', { style: { color: color } }, text); }, }, { title: '2月', dataIndex: 'feb', width: 100, customRender: (value) => { let text; let color; switch (value.record.febFlag) { case 1: text = value.record.feb ? value.record.feb : ''; color = 'rgba(243, 97, 99, 1)'; break; case 0: text = value.record.feb ? value.record.feb : ''; color = 'rgba(57, 215, 187, 1)'; break; } // 使用内联样式设置颜色 return createVNode('div', { style: { color: color } }, text); }, }, { title: '3月', dataIndex: 'mar', width: 100, customRender: (value) => { let text; let color; switch (value.record.marFlag) { case 1: text = value.record.mar ? value.record.mar : ''; color = 'rgba(243, 97, 99, 1)'; break; case 0: text = value.record.mar ? value.record.mar : ''; color = 'rgba(57, 215, 187, 1)'; break; } // 使用内联样式设置颜色 return createVNode('div', { style: { color: color } }, text); }, }, { title: '4月', dataIndex: 'apr', width: 100, customRender: (value) => { let text; let color; switch (value.record.aprFlag) { case 1: text = value.record.apr ? value.record.apr : ''; color = 'rgba(243, 97, 99, 1)'; break; case 0: text = value.record.apr ? value.record.apr : ''; color = 'rgba(57, 215, 187, 1)'; break; } // 使用内联样式设置颜色 return createVNode('div', { style: { color: color } }, text); }, }, { title: '5月', dataIndex: 'may', width: 100, customRender: (value) => { let text; let color; switch (value.record.mayFlag) { case 1: text = value.record.may ? value.record.may : ''; color = 'rgba(243, 97, 99, 1)'; break; case 0: text = value.record.may ? value.record.may : ''; color = 'rgba(57, 215, 187, 1)'; break; } // 使用内联样式设置颜色 return createVNode('div', { style: { color: color } }, text); }, }, { title: '6月', dataIndex: 'jun', width: 100, customRender: (value) => { let text; let color; switch (value.record.junFlag) { case 1: text = value.record.jun ? value.record.jun : ''; color = 'rgba(243, 97, 99, 1)'; break; case 0: text = value.record.jun ? value.record.jun : ''; color = 'rgba(57, 215, 187, 1)'; break; } // 使用内联样式设置颜色 return createVNode('div', { style: { color: color } }, text); }, }, { title: '7月', dataIndex: 'jul', width: 100, customRender: (value) => { let text; let color; switch (value.record.julFlag) { case 1: text = value.record.jul ? value.record.jul : ''; color = 'rgba(243, 97, 99, 1)'; break; case 0: text = value.record.jul ? value.record.jul : ''; color = 'rgba(57, 215, 187, 1)'; break; } // 使用内联样式设置颜色 return createVNode('div', { style: { color: color } }, text); }, }, { title: '8月', dataIndex: 'aug', width: 100, customRender: (value) => { let text; let color; switch (value.record.augFlag) { case 1: text = value.record.aug ? value.record.aug : ''; color = 'rgba(243, 97, 99, 1)'; break; case 0: text = value.record.aug ? value.record.aug : ''; color = 'rgba(57, 215, 187, 1)'; break; } // 使用内联样式设置颜色 return createVNode('div', { style: { color: color } }, text); }, }, { title: '9月', dataIndex: 'sep', width: 100, customRender: (value) => { let text; let color; switch (value.record.sepFlag) { case 1: text = value.record.sep ? value.record.sep : ''; color = 'rgba(243, 97, 99, 1)'; break; case 0: text = value.record.sep ? value.record.sep : ''; color = 'rgba(57, 215, 187, 1)'; break; } // 使用内联样式设置颜色 return createVNode('div', { style: { color: color } }, text); }, }, { title: '10月', dataIndex: 'oct', width: 100, customRender: (value) => { let text; let color; switch (value.record.octFlag) { case 1: text = value.record.oct ? value.record.oct : ''; color = 'rgba(243, 97, 99, 1)'; break; case 0: text = value.record.oct ? value.record.oct : ''; color = 'rgba(57, 215, 187, 1)'; break; } // 使用内联样式设置颜色 return createVNode('div', { style: { color: color } }, text); }, }, { title: '11月', dataIndex: 'nov', width: 100, customRender: (value) => { let text; let color; switch (value.record.novFlag) { case 1: text = value.record.nov ? value.record.nov : ''; color = 'rgba(243, 97, 99, 1)'; break; case 0: text = value.record.nov ? value.record.nov : ''; color = 'rgba(57, 215, 187, 1)'; break; } // 使用内联样式设置颜色 return createVNode('div', { style: { color: color } }, text); }, }, { title: '12月', dataIndex: 'dece', width: 100, customRender: (value) => { let text; let color; switch (value.record.decFlag) { case 1: text = value.record.dece ? value.record.dece : ''; color = 'rgba(243, 97, 99, 1)'; break; case 0: text = value.record.dece ? value.record.dece : ''; color = 'rgba(57, 215, 187, 1)'; break; } // 使用内联样式设置颜色 return createVNode('div', { style: { color: color } }, text); }, }, ], columnActions: { title: '操作', actions: [ { label: '编辑', name: 'userEdit', handle: (record: any) => { getDictList(); getSummaryMethod(record.id); visible.value = true; fetch(energyConsumption.findById, { id: record.id }).then((res) => { if (res.data.emissionType) { res.data.emissionType = Number(res.data.emissionType); } changeEnergyType(res.data.energyConsumptionType); if (res.data.unit) { let selectDevice = ref([Number(res.data.unit)]); findParentIds(measurementUnit.value, res.data.unit, selectDevice.value); res.data.unit = selectDevice; } formState.value = res.data; emissionType.value = res.data.emissionType; if (formState.value.isComputeCarbon === 0) { isRequired.value = true; } else { isRequired.value = false; } }); fetch(uploadPic.select, { bizId: record.id, bizType: 3 }).then((res) => { fileList.value = res.data.map((item) => ({ uid: item.id.toString(), // 使用文件的id作为唯一标识 name: item.fileName, // 文件名 status: 'done', // 设置默认状态为已完成 type: 'done', url: item.filePath, // 文件的URL,这里假设用示例的URL格式 })); }); }, }, { label: '删除', name: 'userDelete', dynamicParams: { id: 'id' }, confirm: true, isReload: true, api: energyConsumption.del, }, ], }, formConfig: { schemas: [ { field: 'year', label: '年份', component: 'NsDatePicker', defaultValue: selectYear.value.format('YYYY'), componentProps: { picker: 'year', valueFormat: 'YYYY', }, }, ], params: {}, }, rowKey: 'id', }); const doWnload = (url) => { const a = document.createElement('a'); document.body.appendChild(a); a.href = encodeURI(url); //设置下载的文件名 // a.download = fileName.value; //触发a标签的点击事件,进行下载 a.click(); }; const getSummaryMethod = (id) => { const queryData = { orgId: orgId.value, }; if (id) { queryData.id = id; } fetch(energyConsumption.energyAcquisition, queryData).then((res) => { addData.value = res.data; }); }; const addColumns = [ { title: '月份', dataIndex: 'month', align: 'center' }, { title: '汇总方式', dataIndex: 'access', align: 'center' }, { title: '操作', key: 'action', dataIndex: 'type', align: 'center' }, ]; const addData = ref([]); //开关 const changeSwitch = (data: any) => { data.type = data.type === 1 ? 0 : 1; data.access = data.type === 1 ? '自动' : '手动'; addData.value = [...addData.value]; console.log(addData.value); formState.value.summaryMethodList = addData.value; }; defineExpose({ mainRef, }); // 定义一个递归函数来查找每一级的id 设备类型回显 层级方法 function findParentIds(tree: any, targetId: number, result: any) { for (let item of tree) { if (item.children && item.children.length > 0) { if (item.children.some((child: any) => child.value === targetId)) { result.unshift(item.value); // 将当前节点的id添加到结果数组的最前面 findParentIds(tree, item.value, result); // 递归查找父级节点的id break; // 找到后可以退出循环 } } } } // 获取表格数据 const getTableList = () => { fetch(energyConsumption.pageList, queryParams.value).then((res) => { data.value = res.data.records; }); }; // 分页器 const onChange = (pageNumber: number, size: number) => { queryParams.value.pageNum = pageNumber; queryParams.value.pageSize = size; mainRef.value?.nsTableRef.reload(); }; const changeEnergyType = (value) => { formState.value.collectionNode = ''; // 获取自动采集节点的数据 fetch(group.queryDeviceGroupTree, { energyType: value, orgId: orgId.value }).then((res) => { treeData.value = res.data; treeData.value = transformData(treeData.value); }); }; // 将数据转换为树形结构 const transformData = (data: any[]) => { return data.map((item) => ({ title: item.pointName, value: item.id, key: item.id, children: item.children ? transformData(item.children) : [], })); }; // 计算碳排切换 const emissionType = ref(); const changeRadio = (e) => { if (e.target.value === 0) { isRequired.value = true; if (emissionType.value) { formState.value.emissionType = emissionType.value; } } else { isRequired.value = false; formState.value.emissionType = ''; } }; // 点击确定提交 const onSubmit = () => { formRef.value .validate() .then(() => { console.log('values', formState, toRaw(formState)); formState.value.year = mainRef.value.nsTableRef.formParamsRef.year ? mainRef.value.nsTableRef.formParamsRef.year : selectYear.value.format('YYYY'); if (formState.value.unit) { formState.value.unit = formState.value.unit.join(',').split(',')[1]; } if (formState.value.id) { fetch(energyConsumption.update, formState.value).then((res) => { if (fileList.value.length !== 0) { const formData = ref(new FormData()); fileList.value.forEach((file) => { if (file.type !== 'done') { formData.value.append('files', file.originFileObj); } }); formData.value.append('bizType', 3); formData.value.append('bizId', formState.value.id); delIds.value.forEach((item) => { formData.value.append('deleteList', item); }); fetch(uploadPic.uploadfiles, formData.value) .then((res) => { message.success('操作成功!'); visible.value = false; delIds.value = []; formState.value = { orgId: orgId.value, }; mainRef.value?.nsTableRef.reload(); }) .catch((error) => { console.log('error', error); }); } else { visible.value = false; delIds.value = []; formState.value = { orgId: orgId.value, }; message.success('操作成功!'); mainRef.value?.nsTableRef.reload(); } }); } else { fetch(energyConsumption.creat, formState.value).then((res) => { if (res.data === '新增数据已存在') { visible.value = false; delIds.value = []; NsMessage.warning(res.data); } else { if (fileList.value.length !== 0) { const formData = ref(new FormData()); fileList.value.forEach((file) => { formData.value.append('files', file.originFileObj); }); formData.value.append('bizType', 3); formData.value.append('bizId', res.data); fetch(uploadPic.uploadfiles, formData.value) .then((res) => { message.success('操作成功!'); visible.value = false; delIds.value = []; formState.value = { orgId: orgId.value, }; mainRef.value?.nsTableRef.reload(); }) .catch((error) => { console.log('error', error); }); } else { visible.value = false; delIds.value = []; formState.value = { orgId: orgId.value, }; message.success('操作成功!'); mainRef.value?.nsTableRef.reload(); } } }); } }) .catch((error) => { console.log('error', error); }); }; const energyTypeOptions = ref([]); // 获取字典值 const getDictList = async () => { // 获取能耗类型 const options = await dict({ params: { dicKey: 'ENERGY_TYPE' } }); energyTypeOptions.value = options.data.data; // 获取排放类型的数据 fetch(energyConsumption.getDicList, { grp: 'EMISSION_TYPE' }).then((res) => { emissionTypeDic.value = res.data; }); // 获取计量单位的数据 fetch(carbonEmissionFactorLibrary.dictionaryUnitManagement, { grp: 'MEASUREMENT_UNIT' }).then( (res) => { measurementUnit.value = res.data; measurementUnit.value = measurementUnit.value.map((item) => ({ value: item.id, label: item.cnValue, children: item.children ? item.children.map((child) => ({ value: child.id, label: child.cnValue, })) : [], })); }, ); }; // 点击新增按钮 const addNewData = () => { getDictList(); visible.value = true; }; // 点击编辑按钮 const editData = (record) => { getDictList(); visible.value = true; fetch(energyConsumption.findById, { id: record.id }).then((res) => { if (res.data.unitName) { res.data.unitName = res.data.unitName.split(','); } formState.value = res.data; }); }; // 点击删除 const delData = (record) => { Modal.confirm({ title: '警告', content: '确定要删除吗?', okText: '确定', okType: 'primary', cancelText: '取消', onOk() { fetch(energyConsumption.del, { id: record.id }).then((res) => { message.success('操作成功!'); mainRef.value?.nsTableRef.reload(); }); }, onCancel() { console.log('Cancel'); }, }); }; // 关闭新增抽屉 const onClose = () => { visible.value = false; delIds.value = []; formState.value = { orgId: orgId.value, }; fileList.value = []; formRef.value.resetFields(); }; // 点击上传凭证按钮 const uploadVoucher = () => { openUpload.value = true; }; // 上传凭证弹窗点击确定 const handleOk = (e: MouseEvent) => { console.log(e); openUpload.value = false; }; // 上传凭证相关方法及变量 const fileList = ref<UploadProps['fileList']>([]); const isValidFileName = (filename: string): boolean => { const regex = /^[\s\S]+_\d{4}\.pdf$/; return regex.test(filename); }; const beforeUpload: UploadProps['beforeUpload'] = (file) => { const filename = file.name; if (!isValidFileName(filename)) { message.error('文件名不符合规则'); return Upload.LIST_IGNORE; // 阻止文件上传 } return false; }; const handleChange = (info: UploadChangeParam) => { // fileList.value = [...info.fileList]; const { fileList: newFileList } = info; // 删除fileList中的第一条数据 if (newFileList.length > 1) { delIds.value.push(info.fileList[0].uid); newFileList.shift(); // 删除第一条数据 } // 更新fileList fileList.value = [...newFileList]; }; const delIds = ref([]); const handleFileRemove = (file) => { delIds.value.push(file.uid); const newFileList = []; fileList.value.forEach((item) => { if (item.uid !== file.uid) { newFileList.push(item); } }); fileList.value = newFileList; }; // 关闭上传凭证弹窗 const closeOpenUpload = () => { openUpload.value = false; }; // 凭证下载 const downLoadVisible = ref(false); const downLoadColumns = [ { title: '序号', customRender: (text: any) => { return text.index + 1; }, }, { title: '能源类型', dataIndex: 'bizName', }, { title: '文件名', dataIndex: 'fileName', ellipsis: true, }, { title: '操作', key: 'action', }, ]; const downLoadData = ref([]); const selectedRowKeysSet = ref([]); const onSelectionChangeSet = (selectedKeys, selectedRows) => { selectedRowKeysSet.value = selectedKeys; }; const downLoad = (record) => { const deleteId = ref(new FormData()); deleteId.value.append('id', record.id); const config = { responseType: 'blob', }; fetch(uploadPic.download, deleteId.value, config) .then((res) => { // 创建一个 URL 对象,指向图片数据的 blob const url = window.URL.createObjectURL(new Blob([res])); // 创建一个 <a> 标签,用于触发下载 const link = document.createElement('a'); link.href = url; link.setAttribute('download', record.fileName); // 设置下载的文件名 document.body.appendChild(link); link.click(); // 清理 URL 对象 window.URL.revokeObjectURL(url); }) .catch((error) => { console.error('下载图片失败:', error); }); }; const onSubmitDownLoad = () => { const deleteIds = ref(new FormData()); selectedRowKeysSet.value.forEach((item) => { deleteIds.value.append('ids', item); }); const config = { responseType: 'blob', }; fetch(uploadPic.downloadZip, deleteIds.value, config) .then((res) => { // 创建一个 URL 对象,指向图片数据的 blob const url = window.URL.createObjectURL(new Blob([res])); // 创建一个 <a> 标签,用于触发下载 const link = document.createElement('a'); link.href = url; link.setAttribute('download', '能耗统计凭证.zip'); // 设置下载的文件名 document.body.appendChild(link); link.click(); // 清理 URL 对象 window.URL.revokeObjectURL(url); onCloseDownLoad(); }) .catch((error) => { console.error('下载图片失败:', error); }); }; const onCloseDownLoad = () => { selectedRowKeysSet.value = []; downLoadVisible.value = false; }; </script> <style scoped lang="less"> :deep(.ant-table-title) { display: flex; } :deep(.ant-table-container) { padding: 0px 16px; } .buttonGroup { margin-left: 1vw; width: 30vw; display: flex; justify-content: space-around; } .ns-form-title { font-weight: bold; user-select: text; } .title { text-align: left; height: 32px; line-height: 32px; font-weight: bold; user-select: text; position: relative; padding-left: 9px; } .title::before { content: ''; position: absolute; left: 0; top: 50%; transform: translateY(-50%); height: 13px; width: 3px; border-radius: 1px; background-color: #2778ff; } .blue-background.ant-switch-checked { background-color: linear-gradient( 180deg, rgba(1, 206, 255, 1) 0%, rgba(57, 215, 187, 1) 100% ) !important; } .blue-background.ant-switch-checked .ant-switch-handle { background-color: linear-gradient( 180deg, rgba(1, 206, 255, 1) 0%, rgba(57, 215, 187, 1) 100% ) !important; } .grey-background.ant-switch { background-color: rgba(238, 238, 238, 1) !important; } .grey-background.ant-switch .ant-switch-handle { background-color: rgba(238, 238, 238, 1) !important; } .ant-switch-checked { background-color: rgba(57, 215, 187, 1) !important; } .grey-background.ant-switch .ant-switch-handle { background-color: rgba(238, 238, 238, 1) !important; } :deep(.ant-table-container) { padding: unset; } </style> <style scoped> th.column-money, td.column-money { text-align: right !important; } </style>