后端部分: 其中查询数据的服务省略

1、引用

 <dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.3.3</version></dependency>

2、controller

package com.rs.cphs.sys.controller;import com.alibaba.excel.EasyExcel;
import com.alibaba.fastjson.JSON;
import com.rs.common.exception.BusinessException;
import com.rs.common.response.ResponseResult;
import com.rs.common.utils.ResponseUtil;
import com.rs.cphs.common.util.Pageful;
import com.rs.cphs.sys.dto.ThirdDictMappingDTO;
import com.rs.cphs.sys.dto.ThirdDictMappingUpdateDTO;
import com.rs.cphs.sys.service.ImportListener;
import com.rs.cphs.sys.service.RedunMdmCodeDetailService;
import com.rs.cphs.sys.service.ThirdDictMappingService;
import com.rs.cphs.sys.service.impl.ThirdDictMappingServiceImpl;
import com.rs.cphs.sys.vo.ThirdDictMappingVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.List;/*** @Description:* @CreateDate: 2025-06-04 13:45:06* @Version: 7.0* @Author: zhuchuang* @Copyright: 2022-2032 Cloud HIS, All rights reserved.*/
@Api(tags = "三方字典对照管理")
@RestController
@RequestMapping("/api/thirdDictMapping")
@Slf4j
@Validated
public class ThirdDictMappingController {@Resourceprivate ThirdDictMappingService dictMappingService;@Resourceprivate RedunMdmCodeDetailService redunMdmCodeDetailService;ApiOperation("根据输入字典分类导出模板")@GetMapping(value = "/exportTemplate")public void exportTemplate(@RequestParam String publicDictCategory, @RequestParam String publicDictCategoryName, HttpServletResponse response) throws IOException {log.info("下载字典对照模板, 入参inputDictCategory: {}", publicDictCategory);// 1. 设置响应头response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");String fileName = URLEncoder.encode("dictMapping.xlsx", StandardCharsets.UTF_8);response.setHeader("Content-Disposition", "attachment;filename=" + fileName);// 2. 查询数据List<ThirdDictMappingVO> dataList = dictMappingService.getThirdDictMappingInfo(publicDictCategory, publicDictCategoryName);if (dataList == null || dataList.isEmpty()) {log.warn("没有找到对应的字典对照数据,publicDictCategory: {}", publicDictCategory);// 如果没有数据,可以选择抛出异常或返回空文件response.getWriter().write("没有找到对应的字典对照数据");}// 3. 写入ExcelEasyExcel.write(response.getOutputStream(), ThirdDictMappingVO.class).sheet("三方字典对照模板").doWrite(dataList);}@ApiOperation("导入字典对照")@PostMapping(value = "/importTemplate")public ResponseResult<Boolean> importTemplate(@RequestParam("file") MultipartFile file) throws IOException {if (file.isEmpty()) {log.error("导入字典对照失败,文件不能为空");throw new BusinessException("文件不能为空");}EasyExcel.read(file.getInputStream(), ThirdDictMappingVO.class, new ImportListener((ThirdDictMappingServiceImpl) dictMappingService, redunMdmCodeDetailService)).sheet().doRead();return ResponseUtil.makeSuccess(true);}
}

3、导入监听service

package com.rs.cphs.sys.service;import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.util.StringUtils;
import com.rs.common.exception.BusinessException;
import com.rs.cphs.sys.dao.entity.ThirdDictMappingEntity;
import com.rs.cphs.sys.dto.RedunMdmCodeDetailQueryDTO;
import com.rs.cphs.sys.service.impl.ThirdDictMappingServiceImpl;
import com.rs.cphs.sys.vo.RedunMdmCodeDetailVO;
import com.rs.cphs.sys.vo.ThirdDictMappingVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;import java.util.ArrayList;
import java.util.List;/*** @Description:* @CreateDate: 2025-06-04 16:15:14* @Version: 7.0* @Author: zhuchuang* @Copyright: 2022-2032 NeuSoft Cloud HIS, All rights reserved.*/
@Slf4jpublic class ImportListener extends AnalysisEventListener<ThirdDictMappingVO> {private List<ThirdDictMappingVO> cachedList = new ArrayList<>();private final ThirdDictMappingServiceImpl thirdDictMappingServiceImpl;private final RedunMdmCodeDetailService redunMdmCodeDetailService;public ImportListener(ThirdDictMappingServiceImpl thirdDictMappingServiceImpl,  RedunMdmCodeDetailService redunMdmCodeDetailService) {this.thirdDictMappingServiceImpl = thirdDictMappingServiceImpl;this.redunMdmCodeDetailService = redunMdmCodeDetailService;}@Overridepublic void invoke(ThirdDictMappingVO thirdDictMappingVO, AnalysisContext analysisContext) {// 单行校验if (StringUtils.isBlank(thirdDictMappingVO.getThirdDictCode()) || StringUtils.isBlank(thirdDictMappingVO.getThirdDictName()) ||StringUtils.isBlank(thirdDictMappingVO.getThirdPartyCode()) || StringUtils.isBlank(thirdDictMappingVO.getThirdPartyName())|| StringUtils.isBlank(thirdDictMappingVO.getPublicDictCode()) || StringUtils.isBlank(thirdDictMappingVO.getPublicDictName())|| StringUtils.isBlank(thirdDictMappingVO.getPublicDictCategory()) || StringUtils.isBlank(thirdDictMappingVO.getPublicDictCategoryName())) {throw new BusinessException("第" + analysisContext.readRowHolder().getRowIndex() + "行:数据有为空的情况");}// 判断三方厂商是否存在RedunMdmCodeDetailQueryDTO queryDTO = new RedunMdmCodeDetailQueryDTO();queryDTO.setConsInfoCode(thirdDictMappingVO.getThirdPartyCode());queryDTO.setConsInfoName(thirdDictMappingVO.getThirdPartyName());List<RedunMdmCodeDetailVO> redunMdmCodeDetailVOList = redunMdmCodeDetailService.getList(queryDTO);if (CollectionUtils.isEmpty(redunMdmCodeDetailVOList)) {throw new BusinessException("第" + analysisContext.readRowHolder().getRowIndex() + "行:三方厂商不存在");}cachedList.add(thirdDictMappingVO);try {// 每1000条批量入库if (cachedList.size() >= 1000) {// cachedList 转成 List<ThirdDictMappingEntity>List<ThirdDictMappingEntity> thirdDictMappingList = cachedList.stream().map(vo -> {ThirdDictMappingEntity entity = new ThirdDictMappingEntity();entity.setPublicDictCode(vo.getPublicDictCode());entity.setPublicDictName(vo.getPublicDictName());entity.setPublicDictCategory(vo.getPublicDictCategory());entity.setPublicDictCategoryName(vo.getPublicDictCategoryName());entity.setThirdPartyCode(vo.getThirdPartyCode());entity.setThirdPartyName(vo.getThirdPartyName());entity.setThirdDictCode(vo.getThirdDictCode());entity.setThirdDictName(vo.getThirdDictName());return entity;}).toList();thirdDictMappingServiceImpl.saveBatch(thirdDictMappingList);cachedList.clear();}} catch (BusinessException e) {log.error("导入三方对照数据入库失败", e);throw new BusinessException("导入三方对照数据入库失败:" + e.getMessage());}}@Overridepublic void doAfterAllAnalysed(AnalysisContext analysisContext) {try {if (!cachedList.isEmpty()) {List<ThirdDictMappingEntity> thirdDictMappingList = cachedList.stream().map(vo -> {ThirdDictMappingEntity entity = new ThirdDictMappingEntity();entity.setPublicDictCode(vo.getPublicDictCode());entity.setPublicDictName(vo.getPublicDictName());entity.setPublicDictCategory(vo.getPublicDictCategory());entity.setPublicDictCategoryName(vo.getPublicDictCategoryName());entity.setThirdPartyCode(vo.getThirdPartyCode());entity.setThirdPartyName(vo.getThirdPartyName());entity.setThirdDictCode(vo.getThirdDictCode());entity.setThirdDictName(vo.getThirdDictName());return entity;}).toList();thirdDictMappingServiceImpl.saveBatch(thirdDictMappingList);}} catch (BusinessException e) {log.error("导入三方对照数据入库失败", e);throw new BusinessException("导入三方对照数据入库失败:" + e.getMessage());}}
}

前端代码:前段给出导出导入页面及方法的代码,其他省略

1、前端样式

2、接口定义: 前端请求requestCphs方法直接解析了后端ResponseResult返回的接口

/*** 导出模板接口* @param publicDictCategory * @returns */
export const exportTemplate = async (publicDictCategory: string, publicDictCategoryName: string) => {return await requestCphs(`/api/thirdDictMapping/exportTemplate`, { params: { publicDictCategory: publicDictCategory, publicDictCategoryName: publicDictCategoryName }, method: 'get' , responseType: 'blob'})
}/*** 导入模板接口* @param file * @returns */
export const importTemplate = async (file: File) => {const formData = new FormData();formData.append('file', file);return await requestCphs(`/api/thirdDictMapping/importTemplate`, {method: 'post',data: formData,headers: { 'Content-Type': 'multipart/form-data' },});
}

3、导入页面控件

<template><el-dialogv-mod="dialogVisible":title="$t('pages.system.third-dict-mapping.import')"width="700px"top="10vh":before-close="handleClose"><div class="import-container"><!-- 文件选择按钮 --><inputtype="file"ref="fileInput"accept=".xlsx, .xls"@change="handleFileChange"style="display: none"/><el-buttonaction="upload"@click="openFileDialog">{{t('pages.system.third-dict-mapping.message.importTitle')}}</el-button><span v-if="sectedFile">{{t('pages.system.third-dict-mapping.message.importSected')}}:{{ sectedFile.name }}</span><!-- 导入按钮 --><el-buttonaction="import"@click="handleImport":disabled="!sectedFile">{{t('pages.system.third-dict-mapping.message.importData')}}</el-button></div><template #footer><el-button action="close" @click="handleClose" /></template></el-dialog>
</template>
<script lang="ts" setup>
import { useVMod } from '@vueuse/core'
const { t } = useI18n()
import { message } from '@hio/hio-biz/src/utils/message'const props = defineProps({visible: {type: Boolean,required: true,},
})// 状态管理
const fileInput = ref(null);
const sectedFile = ref(null);// 打开文件选择框
const openFileDialog = () => {fileInput.value.click();
};// 处理文件选择
const handleFileChange = (e: { target: { files: any[]; }; }) => {const file = e.target.files[0];if (file) {// 验证文件类型const isExc = file.type.includes('exc') || file.name.endsWith('.xls') || file.name.endsWith('.xlsx');if (!isExc) {message(t('pages.system.third-dict-mapping.message.importWarning'), { type: 'warning' });return;}sectedFile.value = file;}
};// 导入数据
const handleImport = async () => {if (!sectedFile.value) {message(t('pages.system.third-dict-mapping.message.importInfo'), { type: 'info' });return;}emit('handleThirdImportClick', sectedFile)
};const emit = defineEmits(['update:visible', 'handleThirdImportClick'])
const dialogVisible = useVMod(props, 'visible', emit)const handleClose = () => {dialogVisible.value = false
}</script><style lang="scss" scoped>.span-option {margin-left:5px;font-size: 15px;}
</style>

4、导出页面控件

<template><el-dialogv-model="dialogVisible":title="$t('pages.system.third-dict-mapping.export')"width="700px"top="10vh":before-close="handleClose"><el-form ref="formRef" :model="formData" :rules="rules"><el-form-item :label="$t('pages.system.third-dict-mapping.publicDictCategory')" prop="publicDictCategory"><el-select v-model="formData.publicDictCategory" :placeholder="$t('pages.system.third-dict-mapping.placeholder.publicDictCategory')" @change="changeThirdDict"><el-optionv-for="item in props.dict?.PUBLIC_DICT_CATEGORY || []":key="item.value":label="item.name":value="item.value":filterable="true"></el-option></el-select></el-form-item></el-form><template #footer><el-standard-button action="close" @click="handleClose" /><el-standard-button action="export" @click="handleExportClick" /></template></el-dialog>
</template>
<script lang="ts" setup>
import { useVModel } from '@vueuse/core'
import { GuaForm } from '@el/one-ui'
import {ThirdDictMapping} from "~/api/third-dict-mapping/data";
const { t } = useI18n()const props = defineProps({visible: {type: Boolean,required: true,},// business为undefined时,表示新增,否则表示编辑dict:{type: Object as PropType<Record<string, any>>,}
})const emit = defineEmits(['update:visible', 'handleThirdExportClick'])const formRef = ref<InstanceType<typeof GuaForm>>()const rules = ref({publicDictCategory: [{ required: true, message: t('pages.system.third-dict-mapping.placeholder.publicDictCategory'), trigger: 'blur' },]
})const formData: Partial<ThirdDictMapping> = reactive({})const dialogVisible = useVModel(props, 'visible', emit)const handleClose = () => {dialogVisible.value = false
}const handleExportClick = () => {formRef.value?.validate((valid: Boolean) => {if (valid) {emit('handleThirdExportClick', formData.publicDictCategory, formData.publicDictCategoryName)}})
}
const changeThirdDict = () => {const selected = props.dict?.PUBLIC_DICT_CATEGORY?.find((item: any) => item.value === formData.publicDictCategory)formData.publicDictCategoryName = selected ? selected.name : ''
}</script><style lang="scss" scoped>.span-option {margin-left:5px;font-size: 15px;}
</style>

5、主页导入导出控件引用

<third-dict-mapping-exportv-if="visibleExport"v-model:visible="visibleExport"@handleThirdExportClick="handleThirdExportClick":dict="dict"></third-dict-mapping-export><third-dict-mapping-importv-if="visibleImport"v-model:visible="visibleImport"@handleThirdImportClick="handleThirdImportClick"></third-dict-mapping-import>import thirdDictMappingExport from './widget/third-dict-mapping-export.vue'
import thirdDictMappingImport from './widget/third-dict-mapping-import.vue'

主页导入导出方法实现

const visibleExport = ref(false)
const visibleImport = ref(false)const thirdImportClick = () => {visibleImport.value = true
}/*** 导入*/
const handleThirdImportClick = async (selectedFile: { value: File; }) => {try {const response = await importTemplate(selectedFile.value)// 处理响应if (response) {message(t('pages.system.third-dict-mapping.message.importSuccess'), { type: 'success' });visibleImport.value = falsegetData()} else {message(t('pages.system.third-dict-mapping.message.importFail'), { type: 'error' });}} catch (error) {console.error(error)message(t('pages.system.third-dict-mapping.message.importFail'), { type: 'error' });}
}/*** 导出*/
const thirdExportClick = () => {visibleExport.value = true
}/*** 导出*/
const handleThirdExportClick = async (publicDictCategory: string, publicDictCategoryName: string) => {try {const result = await exportTemplate(publicDictCategory, publicDictCategoryName)if (result) {const blob = new Blob([result], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'});// 创建下载链接const url = window.URL.createObjectURL(blob);const a = document.createElement('a');a.href = url;a.download = `${publicDictCategory}_dict_mapping_${new Date().toISOString().slice(0, 10)}.xlsx`; // 设置下载文件名document.body.appendChild(a);a.click();// 清理资源document.body.removeChild(a);window.URL.revokeObjectURL(url);message(t('pages.system.third-dict-mapping.message.exportSuccess'), {type: 'success'})}else {message(t('pages.system.third-dict-mapping.message.exportFail'), {type: 'error'})}visibleExport.value = false} catch (error) {console.error(error)message(t('pages.system.third-dict-mapping.message.exportFail'), {type: 'error'})}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/85009.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/85009.shtml
英文地址,请注明出处:http://en.pswp.cn/bicheng/85009.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

机器学习中的数据准备关键技术

有效的数据准备对于构建强大的机器学习模型至关重要。本文档总结并阐述了为监督和非监督学习任务准备数据的关键技术。 1. 理解数据类型 有两种数据类型。定性数据描述对象的特征&#xff0c;而定量数据描述对象的数量。 定性&#xff08;分类&#xff09;数据 名义&#x…

深度学习——基于卷积神经网络实现食物图像分类【3】(保存最优模型)

文章目录 引言一、项目概述二、环境配置三、数据预处理3.1 数据转换设置3.2 数据集准备 四、自定义数据集类五、CNN模型架构六、训练与评估流程6.1 训练函数6.2 评估与模型保存 七、完整训练流程八、模型保存与加载8.1 保存模型8.2 加载模型 九、优化建议十、常见问题解决十一、…

《棒球百科》棒球怎么玩·棒球9号位

用最简单的方式介绍棒球的核心玩法和规则&#xff0c;完全零基础也能看懂&#xff1a; 一句话目标 进攻方&#xff1a;用球棒把球打飞&#xff0c;然后拼命跑完4个垒包&#xff08;逆时针绕一圈&#xff09;得分。 防守方&#xff1a;想尽办法让进攻方出局&#xff0c;阻止他…

语言模型是怎么工作的?通俗版原理解读!

大模型为什么能聊天、写代码、懂医学&#xff1f; 我们从四个关键模块&#xff0c;一步步拆开讲清楚 &#x1f447; ✅ 模块一&#xff1a;模型的“本事”从哪来&#xff1f;靠训练数据 别幻想它有意识&#xff0c;它的能力&#xff0c;全是“喂”出来的&#xff1a; 吃过成千…

nrf52811墨水屏edp_service.c文件学习

on_connect函数 /**brief Function for handling the ref BLE_GAP_EVT_CONNECTED event from the S110 SoftDevice.** param[in] p_epd EPD Service structure.* param[in] p_ble_evt Pointer to the event received from BLE stack.*/ static void on_connect(ble_epd_t …

Nginx-2 详解处理 Http 请求

Nginx-2 详解处理 Http 请求 Nginx 作为当今最流行的开源 Web 服务器之一&#xff0c;以其高性能、高稳定性和丰富的功能而闻名。在处理 HTTP请求 的过程中&#xff0c;Nginx 采用了模块化的设计&#xff0c;将整个请求处理流程划分为若干个阶段&#xff0c;每个阶段都可以由特…

40-Oracle 23 ai Bigfile~Smallfile-Basicfile~Securefile矩阵对比

小伙伴们是不是在文件选择上还默认给建文件4G/个么&#xff0c;在oracle每个版本上系统默认属性是什么&#xff0c;选择困难症了没&#xff0c;一起一次性文件存储和默认属性看透。 基于Oracle历代在存储架构的技术演进分析&#xff0c;结合版本升级和23ai新特性&#xff0c;一…

【一】零基础--分层强化学习概览

分层强化学习&#xff08;Hierarchical Reinforcement Learning, HRL&#xff09;最早一般视为1993 年封建强化学习的提出. 一、HL的基础理论 1.1 MDP MDP&#xff08;马尔可夫决策过程&#xff09;&#xff1a;MDP是一种用于建模序列决策问题的框架&#xff0c;包含状态&am…

Java延时

在 Java 中实现延时操作主要有以下几种方式&#xff0c;根据使用场景选择合适的方法&#xff1a; 1. Thread.sleep()&#xff08;最常用&#xff09; java 复制 下载 try {// 延时 1000 毫秒&#xff08;1秒&#xff09;Thread.sleep(1000); } catch (InterruptedExcepti…

电阻篇---下拉电阻的取值

下拉电阻的取值需要综合考虑电路驱动能力、功耗、信号完整性、噪声容限等多方面因素。以下是详细的取值分析及方法&#xff1a; 一、下拉电阻的核心影响因素 1. 驱动能力与电流限制 单片机 IO 口驱动能力&#xff1a;如 STM32 的 IO 口在输入模式下的漏电流通常很小&#xf…

NY271NY274美光科技固态NY278NY284

美光科技NY系列固态硬盘深度剖析&#xff1a;技术、市场与未来 技术前沿&#xff1a;232层NAND架构与性能突破 在存储技术的赛道上&#xff0c;美光科技&#xff08;Micron&#xff09;始终是行业领跑者。其NY系列固态硬盘&#xff08;SSD&#xff09;凭借232层NAND闪存架构的…

微信开发者工具 插件未授权使用,user uni can not visit app

参考&#xff1a;https://www.jingpinma.cn/archives/159.html 问题描述 我下载了一个别人的小程序&#xff0c;想运行看看效果&#xff0c;结果报错信息如下 原因 其实就是插件没有安装&#xff0c;需要到小程序平台安装插件。处理办法如下 在 app.json 里&#xff0c;声…

UE5 读取配置文件

使用免费的Varest插件&#xff0c;可以读取本地的json数据 获取配置文件路径&#xff1a;当前配置文件在工程根目录&#xff0c;打包后在 Windows/项目名称 下 读取json 打包后需要手动复制配置文件到Windows/项目名称 下

【kdump专栏】KEXEC机制中SME(安全内存加密)

【kdump专栏】KEXEC机制中SME&#xff08;安全内存加密&#xff09; 原始代码&#xff1a; /* Ensure that these pages are decrypted if SME is enabled. */ 533 if (pages) 534 arch_kexec_post_alloc_pages(page_address(pages), 1 << order, 0);&#x1f4cc…

C# vs2022 找不到指定的 SDK“Microsof.NET.Sdk

找不到指定的 SDK"Microsof.NET.Sdk 第一查 看 系统盘目录 C:\Program Files\dotnet第二 命令行输入 dotnet --version第三 检查环境变量总结 只要执行dotnet --version 正常返回版本号此问题即解决 第一查 看 系统盘目录 C:\Program Files\dotnet 有2种方式 去检查 是否…

Pytest断言全解析:掌握测试验证的核心艺术

Pytest断言全解析&#xff1a;掌握测试验证的核心艺术 一、断言的本质与重要性 什么是断言&#xff1f; 断言是自动化测试中的验证检查点&#xff0c;用于确认代码行为是否符合预期。在Pytest中&#xff0c;断言直接使用Python原生assert语句&#xff0c;当条件不满足时抛出…

【编译原理】题目合集(一)

未经许可,禁止转载。 文章目录 选择填空综合选择 将编译程序分成若干个“遍”是为了 (D.利用有限的机器内存,但降低了执行效率) A.提高程序的执行效率 B.使程序的结构更加清晰 C.利用有限的机器内存并提高执行效率 D.利用有限的机器内存,但降低了执行效率 词法分析…

uni-app项目实战笔记13--全屏页面的absolute定位布局和fit-content自适应内容宽度

本篇主要实现全屏页面的布局&#xff0c;其中还涉及内容自适应宽度。 创建一个preview.vue页面用于图片预览&#xff0c;写入以下代码&#xff1a; <template><view class"preview"><swiper circular><swiper-item v-for"item in 5&quo…

OVS Faucet Tutorial笔记(下)

官方文档&#xff1a; OVS Faucet Tutorial 5、Routing Faucet Router 通过控制器模拟三层网关&#xff0c;提供 ARP 应答、路由转发功能。 5.1 控制器配置 5.1.1 编辑控制器yaml文件&#xff0c;增加router配置 rootserver1:~/faucet/inst# vi faucet.yaml dps:switch-1:d…

PCB设计教程【大师篇】stm32开发板PCB布线(信号部分)

前言 本教程基于B站Expert电子实验室的PCB设计教学的整理&#xff0c;为个人学习记录&#xff0c;旨在帮助PCB设计新手入门。所有内容仅作学习交流使用&#xff0c;无任何商业目的。若涉及侵权&#xff0c;请随时联系&#xff0c;将会立即处理 1. 布线优先级与原则 - 遵循“重…