wjj преди 3 дни
родител
ревизия
c639f2dc97

+ 136 - 0
fs-admin/src/main/java/com/fs/his/controller/FsImportMemberController.java

@@ -0,0 +1,136 @@
+package com.fs.his.controller;
+
+import java.io.IOException;
+import java.net.URLEncoder;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import com.alibaba.excel.EasyExcel;
+import com.fs.his.dto.MemberExcelDTO;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.enums.BusinessType;
+import com.fs.his.domain.FsImportMember;
+import com.fs.his.service.IFsImportMemberService;
+import com.fs.common.utils.poi.ExcelUtil;
+import com.fs.common.core.page.TableDataInfo;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * 导入会员Controller
+ * 
+ * @author fs
+ * @date 2026-05-25
+ */
+@RestController
+@RequestMapping("/importMember/importMember")
+public class FsImportMemberController extends BaseController
+{
+    @Autowired
+    private IFsImportMemberService fsImportMemberService;
+
+    /**
+     * 查询导入会员列表
+     */
+    @PreAuthorize("@ss.hasPermi('importMember:importMember:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(FsImportMember fsImportMember)
+    {
+        startPage();
+        List<FsImportMember> list = fsImportMemberService.selectFsImportMemberList(fsImportMember);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出导入会员列表
+     */
+    @PreAuthorize("@ss.hasPermi('importMember:importMember:export')")
+    @Log(title = "导入会员", businessType = BusinessType.EXPORT)
+    @GetMapping("/export")
+    public AjaxResult export(FsImportMember fsImportMember)
+    {
+        List<FsImportMember> list = fsImportMemberService.selectFsImportMemberList(fsImportMember);
+        ExcelUtil<FsImportMember> util = new ExcelUtil<FsImportMember>(FsImportMember.class);
+        return util.exportExcel(list, "导入会员数据");
+    }
+
+    /**
+     * 获取导入会员详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('importMember:importMember:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return AjaxResult.success(fsImportMemberService.selectFsImportMemberById(id));
+    }
+
+    /**
+     * 新增导入会员
+     */
+    @PreAuthorize("@ss.hasPermi('importMember:importMember:add')")
+    @Log(title = "导入会员", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody FsImportMember fsImportMember)
+    {
+        return toAjax(fsImportMemberService.insertFsImportMember(fsImportMember));
+    }
+
+    /**
+     * 修改导入会员
+     */
+    @PreAuthorize("@ss.hasPermi('importMember:importMember:edit')")
+    @Log(title = "导入会员", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody FsImportMember fsImportMember)
+    {
+        return toAjax(fsImportMemberService.updateFsImportMember(fsImportMember));
+    }
+
+    /**
+     * 删除导入会员
+     */
+    @PreAuthorize("@ss.hasPermi('importMember:importMember:remove')")
+    @Log(title = "导入会员", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(fsImportMemberService.deleteFsImportMemberByIds(ids));
+    }
+
+
+    @PostMapping("/import")
+    public AjaxResult importMember(@RequestParam("file") MultipartFile file) {
+        if (file.isEmpty()) {
+            return AjaxResult.error("文件不能为空");
+        }
+
+        // 校验文件类型
+        String filename = file.getOriginalFilename();
+        if (filename == null || (!filename.endsWith(".xlsx") && !filename.endsWith(".xls"))) {
+            return AjaxResult.error("请上传Excel文件(.xlsx或.xls)");
+        }
+        Map<String, Object> map = fsImportMemberService.importExcel(file);
+        return AjaxResult.success("导入成功", map);
+    }
+
+    @GetMapping("/template")
+    public void downloadTemplate(HttpServletResponse response) throws IOException {
+        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
+        response.setCharacterEncoding("utf-8");
+        String fileName = URLEncoder.encode("用户导入模板", "UTF-8");
+        response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
+
+        // 创建模板,只有表头
+        List<MemberExcelDTO> list = new ArrayList<>();
+        EasyExcel.write(response.getOutputStream(), MemberExcelDTO.class)
+                .sheet("模板")
+                .doWrite(list);
+    }
+}

+ 20 - 2
fs-service/src/main/java/com/fs/his/domain/FsImportMember.java

@@ -1,11 +1,18 @@
 package com.fs.his.domain;
 
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
+import com.fasterxml.jackson.annotation.JsonFormat;
 import com.fs.common.annotation.Excel;
 import lombok.Data;
 import com.fs.common.core.domain.BaseEntity;
 import lombok.EqualsAndHashCode;
 
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.Pattern;
+import java.util.Date;
+
 /**
  * 导入会员对象 fs_import_member
  *
@@ -13,14 +20,14 @@ import lombok.EqualsAndHashCode;
  * @date 2026-05-25
  */
 @Data
-@EqualsAndHashCode(callSuper = true)
-public class FsImportMember extends BaseEntity{
+public class FsImportMember{
 
     /** $column.columnComment */
     private Long id;
 
     /** $column.columnComment */
     @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
+    @NotBlank(message = "姓名不能为空")
     private String memberName;
 
     /** $column.columnComment */
@@ -29,11 +36,22 @@ public class FsImportMember extends BaseEntity{
 
     /** $column.columnComment */
     @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
+    @NotBlank(message = "电话不能为空")
+    @Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确")
     private String memberPhone;
 
     /** 状态 0-未生成 1-已生成 */
     @Excel(name = "状态 0-未生成 1-已生成")
     private Integer status;
 
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @TableField(fill = FieldFill.INSERT)
+    private Date createTime;
+
+    /** 更新时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private Date updateTime;
+
 
 }

+ 17 - 0
fs-service/src/main/java/com/fs/his/dto/MemberExcelDTO.java

@@ -0,0 +1,17 @@
+package com.fs.his.dto;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import lombok.Data;
+
+@Data
+public class MemberExcelDTO {
+
+    @ExcelProperty("姓名")
+    private String memberName;
+
+    @ExcelProperty("电话")
+    private String memberPhone;
+
+    @ExcelProperty("地址")
+    private String address;
+}

+ 100 - 0
fs-service/src/main/java/com/fs/his/listenner/MemberImportListener.java

@@ -0,0 +1,100 @@
+package com.fs.his.listenner;
+
+import com.alibaba.excel.context.AnalysisContext;
+import com.alibaba.excel.event.AnalysisEventListener;
+import com.fs.his.domain.FsImportMember;
+import com.fs.his.dto.MemberExcelDTO;
+import com.fs.his.service.IFsImportMemberService;
+import com.google.common.collect.Maps;
+import org.apache.commons.lang3.StringUtils;
+import org.checkerframework.checker.nullness.qual.Nullable;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.BeansException;
+import org.springframework.dao.DuplicateKeyException;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class MemberImportListener  extends AnalysisEventListener<MemberExcelDTO> {
+    // 每批处理数量
+    private static final int BATCH_COUNT = 500;
+
+    private final List<MemberExcelDTO> cachedData  = new ArrayList<>(BATCH_COUNT);
+
+    private final IFsImportMemberService fsImportMemberService;
+
+    // 导入结果统计
+    private int successCount = 0;
+    private int failCount = 0;
+    private final List<String> errorMsgs = new ArrayList<>();
+
+    public MemberImportListener(IFsImportMemberService fsImportMemberService) {
+        this.fsImportMemberService = fsImportMemberService;
+    }
+
+    @Override
+    public void invoke(MemberExcelDTO data, AnalysisContext context) {
+        // 数据校验
+        if (StringUtils.isBlank(data.getMemberName())) {
+            failCount++;
+            errorMsgs.add("第" + context.readRowHolder().getRowIndex() + "行:姓名不能为空");
+            return;
+        }
+        if (StringUtils.isBlank(data.getMemberPhone())) {
+            failCount++;
+            errorMsgs.add("第" + context.readRowHolder().getRowIndex() + "行:电话不能为空");
+            return;
+        }
+        if (!data.getMemberPhone().matches("^1[3-9]\\d{9}$")) {
+            failCount++;
+            errorMsgs.add("第" + context.readRowHolder().getRowIndex() + "行:手机号格式错误");
+            return;
+        }
+
+        cachedData.add(data);
+
+        // 达到批量阈值,执行保存
+        if (cachedData.size() >= BATCH_COUNT) {
+            saveData();
+            cachedData.clear();
+        }
+    }
+
+    @Override
+    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
+        // 保存剩余数据
+        saveData();
+    }
+
+    private void saveData() {
+        if (cachedData.isEmpty()) return;
+
+        try {
+            fsImportMemberService.batchInsert(cachedData);
+            successCount += cachedData.size();
+        } catch (DuplicateKeyException e) {
+            for (MemberExcelDTO dto : cachedData) {
+                try {
+                    FsImportMember member = new FsImportMember();
+                    BeanUtils.copyProperties(dto, member);
+                    member.setStatus(0);
+                    fsImportMemberService.insertFsImportMember(member);
+                    successCount++;
+                } catch (DuplicateKeyException ex) {
+                    failCount++;
+                    errorMsgs.add("第" + dto.getMemberPhone() + " 已存在");
+                }
+            }
+        }
+    }
+
+    public Map<String, Object> getResult(){
+        HashMap<String, Object> map = Maps.newHashMap();
+        map.put("successCount", successCount);
+        map.put("failCount", failCount);
+        map.put("errorMsgs", errorMsgs);
+        return map;
+    }
+}

+ 9 - 0
fs-service/src/main/java/com/fs/his/mapper/FsImportMemberMapper.java

@@ -3,6 +3,7 @@ package com.fs.his.mapper;
 import java.util.List;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.fs.his.domain.FsImportMember;
+import org.apache.ibatis.annotations.Param;
 
 /**
  * 导入会员Mapper接口
@@ -58,4 +59,12 @@ public interface FsImportMemberMapper extends BaseMapper<FsImportMember>{
      * @return 结果
      */
     int deleteFsImportMemberByIds(Long[] ids);
+
+    /**
+     * 批量插入导入会员
+     * 
+     * @param memberList 导入会员列表
+     * @return 结果
+     */
+    int batchInsertFsImportMember(@Param("memberList") List<FsImportMember> memberList);
 }

+ 8 - 0
fs-service/src/main/java/com/fs/his/service/IFsImportMemberService.java

@@ -1,8 +1,12 @@
 package com.fs.his.service;
 
 import java.util.List;
+import java.util.Map;
+
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.fs.his.domain.FsImportMember;
+import com.fs.his.dto.MemberExcelDTO;
+import org.springframework.web.multipart.MultipartFile;
 
 /**
  * 导入会员Service接口
@@ -58,4 +62,8 @@ public interface IFsImportMemberService extends IService<FsImportMember>{
      * @return 结果
      */
     int deleteFsImportMemberById(Long id);
+
+    void batchInsert(List<MemberExcelDTO> list);
+
+    Map<String,Object> importExcel(MultipartFile file);
 }

+ 39 - 0
fs-service/src/main/java/com/fs/his/service/impl/FsImportMemberServiceImpl.java

@@ -1,13 +1,24 @@
 package com.fs.his.service.impl;
 
+import java.io.IOException;
+import java.util.Collections;
 import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import com.alibaba.excel.EasyExcel;
 import com.fs.common.utils.DateUtils;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fs.his.dto.MemberExcelDTO;
+import com.fs.his.listenner.MemberImportListener;
+import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import com.fs.his.mapper.FsImportMemberMapper;
 import com.fs.his.domain.FsImportMember;
 import com.fs.his.service.IFsImportMemberService;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.multipart.MultipartFile;
 
 /**
  * 导入会员Service业务层处理
@@ -91,4 +102,32 @@ public class FsImportMemberServiceImpl extends ServiceImpl<FsImportMemberMapper,
     {
         return baseMapper.deleteFsImportMemberById(id);
     }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void batchInsert(List<MemberExcelDTO> list) {
+        List<FsImportMember> importMembers = list.stream().map(item -> {
+            FsImportMember member = new FsImportMember();
+            BeanUtils.copyProperties(item, member);
+            member.setStatus(0);
+            member.setCreateTime(DateUtils.getNowDate());
+            member.setUpdateTime(DateUtils.getNowDate());
+            return member;
+        }).collect(Collectors.toList());
+        baseMapper.batchInsertFsImportMember(importMembers);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Map<String, Object> importExcel(MultipartFile file) {
+        MemberImportListener listener = new MemberImportListener(this);
+        try {
+            EasyExcel.read(file.getInputStream(), MemberExcelDTO.class, listener)
+                    .sheet()
+                    .doRead();
+        } catch (IOException e) {
+            throw new RuntimeException("Excel读取失败", e);
+        }
+        return listener.getResult();
+    }
 }

+ 16 - 0
fs-service/src/main/resources/mapper/his/FsImportMemberMapper.xml

@@ -76,4 +76,20 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             #{id}
         </foreach>
     </delete>
+
+    <insert id="batchInsertFsImportMember">
+        INSERT INTO fs_import_member
+        (member_name, address, member_phone, status, create_time, update_time)
+        VALUES
+        <foreach collection="memberList" item="item" separator=",">
+            (
+            #{item.memberName},
+            #{item.address},
+            #{item.memberPhone},
+            #{item.status},
+            #{item.createTime},
+            #{item.updateTime}
+            )
+        </foreach>
+    </insert>
 </mapper>