From 2dc1c8dcea601ffd36a59ff7bf2afc842b5a83ec Mon Sep 17 00:00:00 2001 From: wuzhen Date: Tue, 6 Jan 2026 09:42:54 +0800 Subject: [PATCH 1/3] =?UTF-8?q?wuzhen=E6=9B=B4=E6=96=B0=E8=B4=A2=E5=8A=A1?= =?UTF-8?q?=E9=A2=84=E7=AE=97=E5=AF=BC=E5=85=A5=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/vite/plugins/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/vite/plugins/index.ts b/web/vite/plugins/index.ts index 9ef8faf1..ea1fd477 100644 --- a/web/vite/plugins/index.ts +++ b/web/vite/plugins/index.ts @@ -1,5 +1,5 @@ import vue from '@vitejs/plugin-vue'; -import vueDevTools from 'vite-plugin-vue-devtools'; +import vueDevTools from 'vite-plugin-vue-devtools'; // 临时禁用以解决localStorage兼容性问题 import createUnoCss from './unocss'; import createAutoImport from './auto-import'; From fe0d528fccb8952023c6f6eb0d452f8a8422b67b Mon Sep 17 00:00:00 2001 From: wuzhen Date: Tue, 6 Jan 2026 09:47:49 +0800 Subject: [PATCH 2/3] feat(cw): add budget execution import backend and frontend files --- .../CwBudgetExecutionImportController.java | 75 ++++++ .../domain/CwBudgetExecutionImportBatch.java | 58 ++++ .../domain/CwBudgetExecutionImportItem.java | 100 +++++++ .../domain/vo/CwBudgetExecutionImportVo.java | 43 +++ .../CwBudgetExecutionImportListener.java | 139 ++++++++++ .../CwBudgetExecutionImportBatchMapper.java | 14 + .../CwBudgetExecutionImportItemMapper.java | 17 ++ .../ICwBudgetExecutionImportService.java | 24 ++ .../CwBudgetExecutionImportServiceImpl.java | 89 ++++++ .../cw/CwBudgetExecutionImportItemMapper.xml | 30 +++ web/src/api/cw/budgetExecutionImport.ts | 54 ++++ web/src/views/cw/budgetExecutionImport.vue | 7 + .../views/cw/budgetExecutionImport/index.vue | 254 ++++++++++++++++++ 13 files changed, 904 insertions(+) create mode 100644 backend/ruoyi-modules/ruoyi-cw/src/main/java/org/dromara/cw/controller/CwBudgetExecutionImportController.java create mode 100644 backend/ruoyi-modules/ruoyi-cw/src/main/java/org/dromara/cw/domain/CwBudgetExecutionImportBatch.java create mode 100644 backend/ruoyi-modules/ruoyi-cw/src/main/java/org/dromara/cw/domain/CwBudgetExecutionImportItem.java create mode 100644 backend/ruoyi-modules/ruoyi-cw/src/main/java/org/dromara/cw/domain/vo/CwBudgetExecutionImportVo.java create mode 100644 backend/ruoyi-modules/ruoyi-cw/src/main/java/org/dromara/cw/listener/CwBudgetExecutionImportListener.java create mode 100644 backend/ruoyi-modules/ruoyi-cw/src/main/java/org/dromara/cw/mapper/CwBudgetExecutionImportBatchMapper.java create mode 100644 backend/ruoyi-modules/ruoyi-cw/src/main/java/org/dromara/cw/mapper/CwBudgetExecutionImportItemMapper.java create mode 100644 backend/ruoyi-modules/ruoyi-cw/src/main/java/org/dromara/cw/service/ICwBudgetExecutionImportService.java create mode 100644 backend/ruoyi-modules/ruoyi-cw/src/main/java/org/dromara/cw/service/impl/CwBudgetExecutionImportServiceImpl.java create mode 100644 backend/ruoyi-modules/ruoyi-cw/src/main/resources/mapper/cw/CwBudgetExecutionImportItemMapper.xml create mode 100644 web/src/api/cw/budgetExecutionImport.ts create mode 100644 web/src/views/cw/budgetExecutionImport.vue create mode 100644 web/src/views/cw/budgetExecutionImport/index.vue diff --git a/backend/ruoyi-modules/ruoyi-cw/src/main/java/org/dromara/cw/controller/CwBudgetExecutionImportController.java b/backend/ruoyi-modules/ruoyi-cw/src/main/java/org/dromara/cw/controller/CwBudgetExecutionImportController.java new file mode 100644 index 00000000..8a1e61ae --- /dev/null +++ b/backend/ruoyi-modules/ruoyi-cw/src/main/java/org/dromara/cw/controller/CwBudgetExecutionImportController.java @@ -0,0 +1,75 @@ +package org.dromara.cw.controller; + +import jakarta.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.dromara.common.web.core.BaseController; +import org.dromara.common.core.domain.R; +import org.dromara.common.log.annotation.Log; +import org.dromara.common.log.enums.BusinessType; +import org.dromara.common.excel.utils.ExcelUtil; +import org.dromara.cw.domain.vo.CwBudgetExecutionImportVo; +import org.dromara.cw.listener.CwBudgetExecutionImportListener; +import cn.dev33.satoken.annotation.SaCheckPermission; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.http.MediaType; + +import java.io.InputStream; + +/** + * 预算执行导入 Controller + */ +@Slf4j +@RestController +@RequestMapping("/cw/budgetExecutionImport") +public class CwBudgetExecutionImportController extends BaseController { + + /** + * 导入数据 + * + * @param file 导入文件 + */ + @Log(title = "预算执行导入", businessType = BusinessType.IMPORT) + @SaCheckPermission("cw:budgetExecutionImport:import") + @PostMapping(value = "/importData", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) + public R importData(@RequestPart("file") MultipartFile file) throws Exception { + try (InputStream is = file.getInputStream()) { + ExcelUtil.importExcel(is, CwBudgetExecutionImportVo.class, new CwBudgetExecutionImportListener()); + return R.ok(); + } catch (Exception e) { + log.error("导入失败", e); + throw e; + } + } + + /** + * 获取导入模板(导出空模板) + */ + @SaCheckPermission("cw:budgetExecutionImport:import") + @PostMapping("/importTemplate") + public void importTemplate(HttpServletResponse response) { + ExcelUtil.exportExcel(java.util.List.of(), "预算执行导入模板", CwBudgetExecutionImportVo.class, response); + } + + /** + * 查询导入批次分页列表 + */ + @SaCheckPermission("cw:budgetExecutionImport:list") + @GetMapping("/batch/list") + public org.dromara.common.mybatis.core.page.TableDataInfo batchList(org.dromara.common.mybatis.core.page.PageQuery pageQuery) { + var service = org.dromara.common.core.utils.SpringUtils.getBean(org.dromara.cw.service.ICwBudgetExecutionImportService.class); + return service.queryBatchPageList(pageQuery); + } + + /** + * 查询导入明细分页列表 + */ + @SaCheckPermission("cw:budgetExecutionImport:list") + @GetMapping("/item/list") + public org.dromara.common.mybatis.core.page.TableDataInfo itemList(@RequestParam("batchId") Long batchId, org.dromara.common.mybatis.core.page.PageQuery pageQuery) { + var service = org.dromara.common.core.utils.SpringUtils.getBean(org.dromara.cw.service.ICwBudgetExecutionImportService.class); + return service.queryItemPageList(batchId, pageQuery); + } +} + + diff --git a/backend/ruoyi-modules/ruoyi-cw/src/main/java/org/dromara/cw/domain/CwBudgetExecutionImportBatch.java b/backend/ruoyi-modules/ruoyi-cw/src/main/java/org/dromara/cw/domain/CwBudgetExecutionImportBatch.java new file mode 100644 index 00000000..cacf4311 --- /dev/null +++ b/backend/ruoyi-modules/ruoyi-cw/src/main/java/org/dromara/cw/domain/CwBudgetExecutionImportBatch.java @@ -0,0 +1,58 @@ +package org.dromara.cw.domain; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.dromara.common.mybatis.core.domain.BaseEntity; + +import java.math.BigDecimal; +import java.util.Date; + +/** + * 预算执行导入批次对象 cw_budget_execution_import_batch + * + * @author ruoyi + * @date 2026-01-05 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("cw_budget_execution_import_batch") +public class CwBudgetExecutionImportBatch extends BaseEntity { + + private static final long serialVersionUID = 1L; + + @TableId(value = "id") + private Long id; + + private String batchNo; + + private String fileName; + + private Integer totalCount; + + private Integer successCount; + + private Integer failedCount; + + private Long importBy; + + private Date importTime; + + private String status; + + private String remark; + + private BigDecimal totalAmount; + + private Long createBy; + + private Date createTime; + + private Long updateBy; + + private Date updateTime; +} + + + diff --git a/backend/ruoyi-modules/ruoyi-cw/src/main/java/org/dromara/cw/domain/CwBudgetExecutionImportItem.java b/backend/ruoyi-modules/ruoyi-cw/src/main/java/org/dromara/cw/domain/CwBudgetExecutionImportItem.java new file mode 100644 index 00000000..80f130e8 --- /dev/null +++ b/backend/ruoyi-modules/ruoyi-cw/src/main/java/org/dromara/cw/domain/CwBudgetExecutionImportItem.java @@ -0,0 +1,100 @@ +package org.dromara.cw.domain; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.annotation.TableField; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.dromara.common.mybatis.core.domain.BaseEntity; + +import java.math.BigDecimal; +import java.util.Date; + +/** + * 预算执行导入明细对象 cw_budget_execution_import_item + * + * @author ruoyi + * @date 2026-01-05 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("cw_budget_execution_import_item") +public class CwBudgetExecutionImportItem extends BaseEntity { + + private static final long serialVersionUID = 1L; + + @TableId(value = "id") + private Long id; + + private Long batchId; + + private Integer rowNo; + + private String serialNo; + + private String purpose; + + private BigDecimal amount; + + private String deptPaymentCategory; + + private String funcSubject; + + private String fundNature; + + private String indicatorSource; + + private String paymentType; + + private String payeeBank; + + private String payee; + + private String payeeAccount; + + private String projectType; + + private String project; + + private java.sql.Date receiptDate; + + private String localIndicatorDocNo; + + private String budgetSource; + + private String indicatorId; + + @TableField("ext_field_1") + private String extField1; + + @TableField("ext_field_2") + private String extField2; + + @TableField("ext_field_3") + private String extField3; + + @TableField("ext_field_4") + private String extField4; + + @TableField("ext_field_5") + private String extField5; + + private String otherFields; + + private String rawData; + + private String importStatus; + + private String errorMessage; + + private Long createBy; + + private Date createTime; + + private Date updateTime; + + private Long updateBy; +} + + + diff --git a/backend/ruoyi-modules/ruoyi-cw/src/main/java/org/dromara/cw/domain/vo/CwBudgetExecutionImportVo.java b/backend/ruoyi-modules/ruoyi-cw/src/main/java/org/dromara/cw/domain/vo/CwBudgetExecutionImportVo.java new file mode 100644 index 00000000..e5126f4c --- /dev/null +++ b/backend/ruoyi-modules/ruoyi-cw/src/main/java/org/dromara/cw/domain/vo/CwBudgetExecutionImportVo.java @@ -0,0 +1,43 @@ +package org.dromara.cw.domain.vo; + +import lombok.Data; +import java.math.BigDecimal; +import java.util.Date; + +/** + * Excel 导入映射 VO + */ +@Data +public class CwBudgetExecutionImportVo { + private String serialNo; + private String purpose; + private BigDecimal amount; + private String deptPaymentCategory; + private String funcSubject; + private String fundNature; + private String indicatorSource; + private String paymentType; + private String payeeBank; + private String payee; + private String payeeAccount; + private String projectType; + private String project; + /** + * 收到回单的时间,使用 String 避免 Excel 解析严格类型导致异常, + * 在 Listener 中做灵活解析为 Date + */ + private String receiptDate; + private String localIndicatorDocNo; + private String budgetSource; + private String indicatorId; + private String extField1; + private String extField2; + private String extField3; + private String extField4; + private String extField5; + private String otherFields; + // 额外字段:原始行号由监听器填充 + private Integer rowNo; +} + + diff --git a/backend/ruoyi-modules/ruoyi-cw/src/main/java/org/dromara/cw/listener/CwBudgetExecutionImportListener.java b/backend/ruoyi-modules/ruoyi-cw/src/main/java/org/dromara/cw/listener/CwBudgetExecutionImportListener.java new file mode 100644 index 00000000..3c661e48 --- /dev/null +++ b/backend/ruoyi-modules/ruoyi-cw/src/main/java/org/dromara/cw/listener/CwBudgetExecutionImportListener.java @@ -0,0 +1,139 @@ +package org.dromara.cw.listener; + +import cn.idev.excel.context.AnalysisContext; +import lombok.extern.slf4j.Slf4j; +import org.dromara.common.excel.core.ExcelResult; +import org.dromara.common.excel.core.DefaultExcelListener; +import org.dromara.common.satoken.utils.LoginHelper; +import org.dromara.common.core.utils.DateUtils; +import org.dromara.common.core.utils.SpringUtils; +import org.dromara.cw.domain.CwBudgetExecutionImportItem; +import org.dromara.cw.domain.CwBudgetExecutionImportBatch; +import org.dromara.cw.domain.vo.CwBudgetExecutionImportVo; +import org.dromara.cw.service.ICwBudgetExecutionImportService; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +/** + * 预算执行导入监听器 + */ +@Slf4j +public class CwBudgetExecutionImportListener extends DefaultExcelListener { + + private final ICwBudgetExecutionImportService importService; + private final Long operUserId; + private final List buffer = new ArrayList<>(); + + public CwBudgetExecutionImportListener() { + super(true); + this.importService = SpringUtils.getBean(ICwBudgetExecutionImportService.class); + this.operUserId = LoginHelper.getUserId(); + } + + @Override + public void invoke(CwBudgetExecutionImportVo data, AnalysisContext context) { + try { + CwBudgetExecutionImportItem item = new CwBudgetExecutionImportItem(); + // 尽量从解析上下文获取原始 Excel 行号(更可靠),否则使用 VO 中的 rowNo + try { + int rowIndex = context.readRowHolder().getRowIndex(); // 0-based + item.setRowNo(rowIndex + 1); + } catch (Exception ex) { + // fallback + item.setRowNo(data.getRowNo()); + } + item.setSerialNo(data.getSerialNo()); + item.setPurpose(data.getPurpose()); + item.setAmount(data.getAmount()); + item.setDeptPaymentCategory(data.getDeptPaymentCategory()); + item.setFuncSubject(data.getFuncSubject()); + item.setFundNature(data.getFundNature()); + item.setIndicatorSource(data.getIndicatorSource()); + item.setPaymentType(data.getPaymentType()); + item.setPayeeBank(data.getPayeeBank()); + item.setPayee(data.getPayee()); + item.setPayeeAccount(data.getPayeeAccount()); + item.setProjectType(data.getProjectType()); + item.setProject(data.getProject()); + // 灵活解析回单时间(Excel 中可能为字符串或日期格式不一致) + try { + if (data.getReceiptDate() != null) { + // receiptDate 在 VO 中为 String(已改),尝试解析为 Date + java.util.Date parsed = DateUtils.parseDate(data.getReceiptDate()); + if (parsed != null) { + item.setReceiptDate(new java.sql.Date(parsed.getTime())); + } else { + // 解析失败时记录为 null,并在明细中标记错误以便人工排查 + item.setReceiptDate(null); + item.setImportStatus("fail"); + item.setErrorMessage("回单时间解析失败: " + data.getReceiptDate()); + // 将该行仍加入buffer以便入库和后续查看;可以选择跳过或计为失败 + } + } + } catch (Exception e) { + item.setReceiptDate(null); + item.setImportStatus("fail"); + item.setErrorMessage("回单时间解析异常: " + e.getMessage()); + } + item.setLocalIndicatorDocNo(data.getLocalIndicatorDocNo()); + item.setBudgetSource(data.getBudgetSource()); + item.setIndicatorId(data.getIndicatorId()); + item.setExtField1(data.getExtField1()); + item.setExtField2(data.getExtField2()); + item.setExtField3(data.getExtField3()); + item.setExtField4(data.getExtField4()); + item.setExtField5(data.getExtField5()); + item.setOtherFields(data.getOtherFields()); + item.setImportStatus("pending"); + item.setCreateBy(operUserId); + item.setCreateTime(new Date()); + buffer.add(item); + } catch (Exception e) { + log.error("导入行处理异常", e); + } + } + + @Override + public void doAfterAllAnalysed(AnalysisContext context) { + log.info("Excel 解析完成,准备写入数据库,行数={}", buffer.size()); + if (!buffer.isEmpty()) { + // 创建批次 + CwBudgetExecutionImportBatch batch = new CwBudgetExecutionImportBatch(); + batch.setBatchNo(String.valueOf(System.currentTimeMillis())); + batch.setFileName("excel_import"); + batch.setTotalCount(buffer.size()); + batch.setSuccessCount(0); + batch.setFailedCount(0); + batch.setImportBy(operUserId); + batch.setImportTime(new Date()); + batch.setStatus("running"); + batch.setCreateBy(operUserId); + batch.setCreateTime(new Date()); + Long batchId = importService.insertBatch(batch); + + // 赋值 batchId 并批量插入 + BigDecimal totalAmount = BigDecimal.ZERO; + for (int i = 0; i < buffer.size(); i++) { + CwBudgetExecutionImportItem it = buffer.get(i); + it.setBatchId(batchId); + // 确保 rowNo 非空(数据库约束),若为空则用解析顺序作为行号 + if (it.getRowNo() == null) { + it.setRowNo(i + 1); + } + totalAmount = totalAmount.add(it.getAmount() == null ? BigDecimal.ZERO : it.getAmount()); + } + importService.batchInsertItems(buffer); + + // 更新批次汇总 + importService.updateBatchSummary(batchId, buffer.size(), 0, totalAmount); + log.info("导入完成,batchId={}, totalAmount={}, rows={}", batchId, totalAmount, buffer.size()); + } + } + + // 使用 DefaultExcelListener 提供的默认实现 +} + + diff --git a/backend/ruoyi-modules/ruoyi-cw/src/main/java/org/dromara/cw/mapper/CwBudgetExecutionImportBatchMapper.java b/backend/ruoyi-modules/ruoyi-cw/src/main/java/org/dromara/cw/mapper/CwBudgetExecutionImportBatchMapper.java new file mode 100644 index 00000000..2cdd7968 --- /dev/null +++ b/backend/ruoyi-modules/ruoyi-cw/src/main/java/org/dromara/cw/mapper/CwBudgetExecutionImportBatchMapper.java @@ -0,0 +1,14 @@ +package org.dromara.cw.mapper; + +import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; +import org.dromara.cw.domain.CwBudgetExecutionImportBatch; + +/** + * 批次 Mapper + */ +public interface CwBudgetExecutionImportBatchMapper extends BaseMapperPlus { + +} + + + diff --git a/backend/ruoyi-modules/ruoyi-cw/src/main/java/org/dromara/cw/mapper/CwBudgetExecutionImportItemMapper.java b/backend/ruoyi-modules/ruoyi-cw/src/main/java/org/dromara/cw/mapper/CwBudgetExecutionImportItemMapper.java new file mode 100644 index 00000000..608dc0e8 --- /dev/null +++ b/backend/ruoyi-modules/ruoyi-cw/src/main/java/org/dromara/cw/mapper/CwBudgetExecutionImportItemMapper.java @@ -0,0 +1,17 @@ +package org.dromara.cw.mapper; + +import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; +import org.dromara.cw.domain.CwBudgetExecutionImportItem; + +import java.util.List; + +/** + * 明细 Mapper + */ +public interface CwBudgetExecutionImportItemMapper extends BaseMapperPlus { + + int batchInsert(List list); +} + + + diff --git a/backend/ruoyi-modules/ruoyi-cw/src/main/java/org/dromara/cw/service/ICwBudgetExecutionImportService.java b/backend/ruoyi-modules/ruoyi-cw/src/main/java/org/dromara/cw/service/ICwBudgetExecutionImportService.java new file mode 100644 index 00000000..463e60c7 --- /dev/null +++ b/backend/ruoyi-modules/ruoyi-cw/src/main/java/org/dromara/cw/service/ICwBudgetExecutionImportService.java @@ -0,0 +1,24 @@ +package org.dromara.cw.service; + +import org.dromara.cw.domain.CwBudgetExecutionImportBatch; +import org.dromara.cw.domain.CwBudgetExecutionImportItem; + +import java.math.BigDecimal; +import java.util.List; +import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.common.mybatis.core.page.PageQuery; + +public interface ICwBudgetExecutionImportService { + + Long insertBatch(CwBudgetExecutionImportBatch batch); + + Boolean batchInsertItems(List items); + + Boolean updateBatchSummary(Long batchId, int successCount, int failedCount, BigDecimal totalAmount); + + TableDataInfo queryBatchPageList(PageQuery pageQuery); + + TableDataInfo queryItemPageList(Long batchId, PageQuery pageQuery); +} + + diff --git a/backend/ruoyi-modules/ruoyi-cw/src/main/java/org/dromara/cw/service/impl/CwBudgetExecutionImportServiceImpl.java b/backend/ruoyi-modules/ruoyi-cw/src/main/java/org/dromara/cw/service/impl/CwBudgetExecutionImportServiceImpl.java new file mode 100644 index 00000000..44cf142a --- /dev/null +++ b/backend/ruoyi-modules/ruoyi-cw/src/main/java/org/dromara/cw/service/impl/CwBudgetExecutionImportServiceImpl.java @@ -0,0 +1,89 @@ +package org.dromara.cw.service.impl; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.dromara.cw.domain.CwBudgetExecutionImportBatch; +import org.dromara.cw.domain.CwBudgetExecutionImportItem; +import org.dromara.cw.mapper.CwBudgetExecutionImportBatchMapper; +import org.dromara.cw.mapper.CwBudgetExecutionImportItemMapper; +import org.dromara.cw.service.ICwBudgetExecutionImportService; + +import java.math.BigDecimal; +import java.util.Date; +import java.util.List; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; + +/** + * 导入服务实现 + */ +@Slf4j +@RequiredArgsConstructor +@Service +public class CwBudgetExecutionImportServiceImpl implements ICwBudgetExecutionImportService { + + private final CwBudgetExecutionImportBatchMapper batchMapper; + private final CwBudgetExecutionImportItemMapper itemMapper; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long insertBatch(CwBudgetExecutionImportBatch batch) { + batch.setCreateTime(new Date()); + batch.setUpdateTime(new Date()); + int r = batchMapper.insert(batch); + if (r > 0) { + return batch.getId(); + } + return null; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public Boolean batchInsertItems(List items) { + if (items == null || items.isEmpty()) { + return false; + } + // 避免依赖外部 XML 的 batchInsert 映射,在这里使用 MyBatis-Plus 的通用 insert 批量处理 + int count = 0; + for (CwBudgetExecutionImportItem item : items) { + int r = itemMapper.insert(item); + if (r > 0) { + count++; + } + } + return count == items.size(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public Boolean updateBatchSummary(Long batchId, int successCount, int failedCount, BigDecimal totalAmount) { + CwBudgetExecutionImportBatch update = new CwBudgetExecutionImportBatch(); + update.setId(batchId); + update.setSuccessCount(successCount); + update.setFailedCount(failedCount); + update.setTotalCount(successCount + failedCount); + update.setTotalAmount(totalAmount); + update.setUpdateTime(new Date()); + int r = batchMapper.updateById(update); + return r > 0; + } + + @Override + public org.dromara.common.mybatis.core.page.TableDataInfo queryBatchPageList(org.dromara.common.mybatis.core.page.PageQuery pageQuery) { + Page page = pageQuery.build(); + var pageResult = batchMapper.selectPage(page, null); + return org.dromara.common.mybatis.core.page.TableDataInfo.build(pageResult); + } + + @Override + public org.dromara.common.mybatis.core.page.TableDataInfo queryItemPageList(Long batchId, org.dromara.common.mybatis.core.page.PageQuery pageQuery) { + Page page = pageQuery.build(); + var lqw = com.baomidou.mybatisplus.core.toolkit.Wrappers.lambdaQuery().eq(CwBudgetExecutionImportItem::getBatchId, batchId); + var pageResult = itemMapper.selectPage(page, lqw); + log.info("查询导入明细: batchId={}, pageNum={}, pageSize={}, result total={}", batchId, page.getCurrent(), page.getSize(), pageResult.getTotal()); + return org.dromara.common.mybatis.core.page.TableDataInfo.build(pageResult); + } +} + + diff --git a/backend/ruoyi-modules/ruoyi-cw/src/main/resources/mapper/cw/CwBudgetExecutionImportItemMapper.xml b/backend/ruoyi-modules/ruoyi-cw/src/main/resources/mapper/cw/CwBudgetExecutionImportItemMapper.xml new file mode 100644 index 00000000..1f2ed881 --- /dev/null +++ b/backend/ruoyi-modules/ruoyi-cw/src/main/resources/mapper/cw/CwBudgetExecutionImportItemMapper.xml @@ -0,0 +1,30 @@ + + + + + + INSERT INTO cw_budget_execution_import_item + (id, batch_id, row_no, serial_no, purpose, amount, dept_payment_category, func_subject, + fund_nature, indicator_source, payment_type, payee_bank, payee, payee_account, + project_type, project, receipt_date, local_indicator_doc_no, budget_source, indicator_id, + ext_field_1, ext_field_2, ext_field_3, ext_field_4, ext_field_5, + other_fields, raw_data, import_status, error_message, create_by, create_time, update_time, update_by) + VALUES + + (#{item.id}, #{item.batchId}, #{item.rowNo}, #{item.serialNo}, #{item.purpose}, #{item.amount}, + #{item.deptPaymentCategory}, #{item.funcSubject}, #{item.fundNature}, #{item.indicatorSource}, + #{item.paymentType}, #{item.payeeBank}, #{item.payee}, #{item.payeeAccount}, + #{item.projectType}, #{item.project}, #{item.receiptDate}, #{item.localIndicatorDocNo}, + #{item.budgetSource}, #{item.indicatorId}, #{item.extField1}, #{item.extField2}, + #{item.extField3}, #{item.extField4}, #{item.extField5}, + #{item.otherFields}, #{item.rawData}, #{item.importStatus}, #{item.errorMessage}, + #{item.createBy}, #{item.createTime}, #{item.updateTime}, #{item.updateBy}) + + + + + + + diff --git a/web/src/api/cw/budgetExecutionImport.ts b/web/src/api/cw/budgetExecutionImport.ts new file mode 100644 index 00000000..5d74824b --- /dev/null +++ b/web/src/api/cw/budgetExecutionImport.ts @@ -0,0 +1,54 @@ +import request from '@/utils/request'; + +/** + * 导入预算执行数据 + * @param file File + */ +export const importBudgetExecution = (file: File) => { + const formData = new FormData(); + formData.append('file', file); + return request({ + url: '/cw/budgetExecutionImport/importData', + method: 'post', + data: formData, + headers: { + 'Content-Type': 'multipart/form-data' + } + }); +}; + +/** + * 下载导入模板 + */ +export const downloadBudgetExecutionTemplate = () => { + return request({ + url: '/cw/budgetExecutionImport/importTemplate', + method: 'post', + responseType: 'blob' + }); +}; + +/** + * 查询批次分页 + */ +export const listImportBatches = (params?: any) => { + return request({ + url: '/cw/budgetExecutionImport/batch/list', + method: 'get', + params + }); +}; + +/** + * 查询明细分页 + */ +export const listImportItems = (batchId: number, params?: any) => { + return request({ + url: '/cw/budgetExecutionImport/item/list', + method: 'get', + params: { batchId, ...params } + }); +}; + + + diff --git a/web/src/views/cw/budgetExecutionImport.vue b/web/src/views/cw/budgetExecutionImport.vue new file mode 100644 index 00000000..3c525c4e --- /dev/null +++ b/web/src/views/cw/budgetExecutionImport.vue @@ -0,0 +1,7 @@ + + + + diff --git a/web/src/views/cw/budgetExecutionImport/index.vue b/web/src/views/cw/budgetExecutionImport/index.vue new file mode 100644 index 00000000..52503281 --- /dev/null +++ b/web/src/views/cw/budgetExecutionImport/index.vue @@ -0,0 +1,254 @@ + + + + + + + From 69186e7331f86fa8767d3b17dd9f74844428bc4a Mon Sep 17 00:00:00 2001 From: wuzhen Date: Tue, 6 Jan 2026 09:51:05 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E6=8F=90=E4=BA=A4=E2=80=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- remaining_garbled_fields.txt | 71 ++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 remaining_garbled_fields.txt diff --git a/remaining_garbled_fields.txt b/remaining_garbled_fields.txt new file mode 100644 index 00000000..4e91b5c7 --- /dev/null +++ b/remaining_garbled_fields.txt @@ -0,0 +1,71 @@ +剩余乱码字段列表 +================================================================================ + +rs_overseas_application.serial_number +rs_overseas_application.gender +rs_overseas_application.birth_date +rs_overseas_application.photo +rs_overseas_application.id_number +rs_overseas_application.political_status +rs_overseas_application.registered_address +rs_overseas_application.department +rs_overseas_application.professional_title +rs_overseas_application.administrative_level +rs_overseas_application.personnel_category +rs_overseas_application.registration_unit +rs_overseas_application.unit_leader_signature +rs_overseas_application.office_phone +rs_overseas_application.mobile_phone +rs_overseas_application.document_name +rs_overseas_application.document_number +rs_overseas_application.destination_country +rs_overseas_application.exit_reason +rs_overseas_application.visit_relationship +rs_overseas_application.remarks +rs_overseas_application.emergency_contact +rs_overseas_application.signature +rs_overseas_application.stamped_registration_file_path +rs_overseas_application.stamped_registration_file_name +rs_overseas_application.stamped_file_upload_time +rs_overseas_application.stamped_file_upload_status +rs_overseas_application.stamped_file_oss_id +rs_overseas_application.party_retention_file_path +rs_overseas_application.party_retention_file_name +rs_overseas_application.party_retention_upload_time +rs_overseas_application.party_retention_upload_status +rs_overseas_application.party_retention_file_oss_id +rs_overseas_application.attachment_count +rs_overseas_application.approval_status +rs_overseas_application.current_approver_id +rs_overseas_application.approval_level +rs_overseas_application.attachment_ids +rs_overseas_application_attachment.attachment_id +rs_overseas_application_attachment.upload_time +rs_overseas_itinerary_change.change_id +rs_overseas_registration.registration_id +rs_overseas_registration.application_id +rs_overseas_registration.name +rs_overseas_registration.gender +rs_overseas_registration.birth_date +rs_overseas_registration.photo +rs_overseas_registration.id_number +rs_overseas_registration.political_status +rs_overseas_registration.registered_address +rs_overseas_registration.department +rs_overseas_registration.position +rs_overseas_registration.administrative_level +rs_overseas_registration.personnel_category +rs_overseas_registration.status +rs_overseas_registration.registration_time +rs_overseas_registration.remarks +rs_overseas_registration_history.history_id +rs_overseas_registration_history.registration_id +rs_overseas_registration_history.actual_departure_date +rs_overseas_registration_history.actual_return_date +rs_overseas_registration_history.actual_duration_days +rs_overseas_registration_history.actual_destination +rs_overseas_registration_history.completion_status +rs_overseas_registration_history.completion_notes +rs_overseas_registration_history.evidence_files +rs_overseas_registration_history.actual_cost +rs_overseas_registration_history.cost_notes