zouxuan 5 ヶ月 前
コミット
bad0b41354

+ 26 - 39
cooleshow-app/src/main/java/com/yonge/cooleshow/admin/controller/StudentController.java

@@ -1,26 +1,18 @@
 package com.yonge.cooleshow.admin.controller;
 
+import cn.hutool.core.net.URLEncodeUtil;
+import com.alibaba.fastjson.JSON;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.yonge.cooleshow.auth.api.client.SysUserFeignService;
 import com.yonge.cooleshow.auth.api.entity.SysUser;
-import com.yonge.cooleshow.biz.dal.dto.VipSubmitReq;
 import com.yonge.cooleshow.biz.dal.dto.search.StudentSearch;
 import com.yonge.cooleshow.biz.dal.dto.search.VipRecordSearch;
-import com.yonge.cooleshow.biz.dal.entity.Student;
-import com.yonge.cooleshow.biz.dal.entity.TenantActivationCode;
-import com.yonge.cooleshow.biz.dal.entity.TenantAlbumPurchase;
-import com.yonge.cooleshow.biz.dal.entity.TenantGroup;
-import com.yonge.cooleshow.biz.dal.entity.TenantGroupAlbum;
+import com.yonge.cooleshow.biz.dal.entity.*;
 import com.yonge.cooleshow.biz.dal.enums.ClientEnum;
-import com.yonge.cooleshow.biz.dal.service.MemberPriceSettingsService;
-import com.yonge.cooleshow.biz.dal.service.StudentService;
-import com.yonge.cooleshow.biz.dal.service.TenantActivationCodeService;
-import com.yonge.cooleshow.biz.dal.service.TenantAlbumPurchaseService;
-import com.yonge.cooleshow.biz.dal.service.TenantGroupAlbumService;
-import com.yonge.cooleshow.biz.dal.service.TenantGroupService;
-import com.yonge.cooleshow.biz.dal.service.VipCardRecordService;
+import com.yonge.cooleshow.biz.dal.service.*;
 import com.yonge.cooleshow.biz.dal.vo.StudentVo;
 import com.yonge.cooleshow.biz.dal.vo.VipRecordVo;
+import com.yonge.cooleshow.biz.dal.wrapper.FileImportInfoWrapper;
 import com.yonge.cooleshow.biz.dal.wrapper.StudentWrapper;
 import com.yonge.cooleshow.common.controller.BaseController;
 import com.yonge.cooleshow.common.entity.HttpResponseResult;
@@ -39,55 +31,39 @@ import io.swagger.annotations.ApiOperation;
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpStatus;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
 
 import javax.annotation.Resource;
 import javax.servlet.http.HttpServletResponse;
 import javax.validation.Valid;
 import java.io.IOException;
 import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 import java.util.stream.Collectors;
 
 @RestController
 @RequestMapping("${app-config.url.admin:}/student")
 @Api(value = "学生表", tags = "学生表")
 public class StudentController extends BaseController {
-    @Autowired
+    @Resource
     private StudentService studentService;
-
     @Resource
     private SysUserFeignService sysUserFeignService;
-
-    @Autowired
-    private MemberPriceSettingsService memberPriceSettingsService;
-
-    @Autowired
+    @Resource
     private VipCardRecordService vipCardRecordService;
-
-    @Autowired
+    @Resource
     private TenantGroupService tenantGroupService;
-
-    @Autowired
+    @Resource
     private TenantActivationCodeService tenantActivationCodeService;
-    @Autowired
+    @Resource
     private TenantAlbumPurchaseService tenantAlbumPurchaseService;
-    @Autowired
+    @Resource
     private TenantGroupAlbumService tenantGroupAlbumService;
+    @Resource
+    private ExcelAnalyseCoreService excelAnalyseCoreService;
 
     @GetMapping("/detail/{id}")
     @ApiOperation(value = "详情", notes = "传入id")
@@ -329,6 +305,17 @@ public class StudentController extends BaseController {
         return succeed();
     }
 
+    @PostMapping("/import")
+    @ApiOperation(value = "学员导入")
+    public HttpResponseResult<FileImportInfo> importFile(@RequestBody FileImportInfoWrapper.FileImport wrapper) {
+
+        wrapper.setImportUrl(URLEncodeUtil.encode(wrapper.getImportUrl()));
+
+        // 读取数据
+        return HttpResponseResult.succeed(excelAnalyseCoreService.analyseReadExcelData(
+                JSON.parseObject(JSON.toJSONString(wrapper), FileImportInfoWrapper.FileImportInfo.class)));
+    }
+
     @PostMapping("/update")
     @ApiOperation(value = "修改", notes = "传入Student")
     public HttpResponseResult<Boolean> update(@Validated @RequestBody StudentWrapper.Student student) {

+ 211 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/execl/analysis/StudentImportAnalysis.java

@@ -0,0 +1,211 @@
+package com.yonge.cooleshow.biz.dal.execl.analysis;
+
+import com.alibaba.excel.EasyExcel;
+import com.alibaba.excel.enums.CellExtraTypeEnum;
+import com.alibaba.excel.metadata.Sheet;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.microsvc.toolkit.middleware.excel.analysis.AnalysisContext;
+import com.microsvc.toolkit.middleware.excel.analysis.DataAnalysis;
+import com.microsvc.toolkit.middleware.excel.util.DownloadManager;
+import com.yonge.cooleshow.biz.dal.execl.entity.StudentImportWrapper;
+import com.yonge.cooleshow.biz.dal.execl.listener.StudentImportListener;
+import com.yonge.cooleshow.biz.dal.service.EasyExcelService;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+
+import java.io.File;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+
+@Slf4j
+@Getter
+@Setter
+public class StudentImportAnalysis extends DataAnalysis<StudentImportAnalysis> {
+
+
+    private List<StudentImportWrapper.StudentImport> studentImportWrappers;
+
+    // Excel解析服务
+    private EasyExcelService easyExcelService;
+
+    private final Map<String, StudentImportWrapper.StudentImport> recordMap = Maps.newHashMap();
+    private final Map<String, Long> subjectMap = Maps.newHashMap();
+    private final Map<String, Long> tenantMap = Maps.newHashMap();
+    private final Map<String, Long> tenantGroupMap = Maps.newHashMap();
+    private final List<String> phones = Lists.newArrayList();
+    private final List<String> existPhones = Lists.newArrayList();
+    public StudentImportAnalysis(AnalysisContext context) {
+        super(context);
+    }
+
+    public static StudentImportAnalysis build(EasyExcelService easyExcelService) {
+        StudentImportAnalysis analysis = new StudentImportAnalysis(AnalysisContext.builder().build());
+        analysis.setEasyExcelService(easyExcelService);
+        analysis.setStudentImportWrappers(Lists.newArrayList());
+        return analysis;
+
+    }
+
+
+    /**
+     * 读取文件数据到内存
+     *
+     * @param path 本地文件地址
+     */
+    @Override
+    public void read(String path) {
+
+        File file = new File(path);
+        List<Sheet> sheets = EasyExcel.read(file).build().getSheets();
+        if (CollectionUtils.isNotEmpty(sheets)) {
+
+            sheets.forEach(item -> {
+                // 读取数据
+                EasyExcel.read(file, StudentImportWrapper.StudentImport.class, new StudentImportListener(getStudentImportWrappers(), item.getSheetName()))
+                        .extraRead(CellExtraTypeEnum.MERGE).sheet(item.getSheetName()).doRead();
+            });
+
+        }
+
+        // 删除本地缓存文件
+        DownloadManager.getInstance().deleteOnExit(path);
+    }
+
+    /**
+     * 校验数据合法
+     *
+     * @return Map<Integer, String>
+     */
+    @Override
+    public Map<Integer, String> verify() {
+
+        // 加载校验数据参数
+        if (Objects.nonNull(getStudentImportWrappers())) {
+            loadVerifyParamData();
+        }
+
+        Map<Integer, String> verifyDataMap = Maps.newLinkedHashMap();
+
+        // 校验每条入库记录数据合法性
+        StringBuffer ret = new StringBuffer();
+        for (StudentImportWrapper.StudentImport item : getStudentImportWrappers()) {
+
+            if (StringUtils.isEmpty(item.getUserName())) {
+                ret.append("学生姓名不能为空;");
+            }else {
+                if(!item.getUserName().matches("^[\\u4e00-\\u9fa5]{2,10}$")){
+                    ret.append("真实姓名格式不正确;");
+                }
+            }
+            if (StringUtils.isEmpty(item.getPhone())) {
+                ret.append("手机号不能为空;");
+            }else {
+                //手机号校验
+                if (!item.getPhone().matches("^1[3-9]\\d{9}$")) {
+                    ret.append("手机号格式不正确;");
+                }else {
+                    //校验是否重复
+                    if(phones.contains(item.getPhone())){
+                        ret.append("手机号重复;");
+                    }else {
+                        if(existPhones.contains(item.getPhone())){
+                            ret.append("手机号已存在;");
+                        }
+                        phones.add(item.getPhone());
+                    }
+                }
+            }
+            if (StringUtils.isEmpty(item.getGender())) {
+                ret.append("性别不能为空;");
+            }
+            if (StringUtils.isEmpty(item.getBirthday())) {
+                ret.append("出生日期不能为空;");
+            }else {
+                if (!item.getBirthday().matches("^\\d{4}-\\d{2}-\\d{2}$")) {
+                    ret.append("出生日期格式不正确;");
+                }
+            }
+            if (StringUtils.isEmpty(item.getSubjectName())) {
+                ret.append("声部不能为空;");
+            }else {
+                String[] split = item.getSubjectName().replaceAll(" ", "").replaceAll(",", ",").split(",");
+                for (String s : split) {
+                    if (!subjectMap.containsKey(s)) {
+                        ret.append("声部无效:").append(s);
+                    }
+                    item.setSubjectId(subjectMap.get(s));
+                }
+            }
+            if (StringUtils.isEmpty(item.getTenantName())) {
+                ret.append("机构名称不能为空;");
+            }else {
+                if (!tenantMap.containsKey(item.getTenantName())) {
+                    ret.append("机构无效:").append(item.getTenantName());
+                }
+                item.setTenantId(tenantMap.get(item.getTenantName()));
+            }
+            if (StringUtils.isEmpty(item.getTenantGroupName())) {
+                ret.append("小组名称不能为空;");
+            }else {
+                if (!tenantGroupMap.containsKey(item.getTenantName())) {
+                    ret.append("小组名称无效:").append(item.getTenantName());
+                }
+                item.setTenantGroupId(tenantGroupMap.get(item.getTenantName()));
+            }
+            if (StringUtils.isNotEmpty(ret)) {
+                verifyDataMap.put(item.getRowIndex(), ret.toString());
+                ret = new StringBuffer(); // 重置数据状态
+            }
+        }
+
+        // 数据校验记录信息
+        getContext().total(getStudentImportWrappers().size()).failure(verifyDataMap.size())
+                .setSuccess(getContext().getTotal() - getContext().getFailure());
+
+        return verifyDataMap;
+    }
+
+    /**
+     * 数据转换
+     */
+    @Override
+    public void convert() {
+
+    }
+
+    /**
+     * 加载校验数据参数
+     */
+    private void loadVerifyParamData() {
+        //获取所有的手机号和身份证号
+        List<String> phones = getStudentImportWrappers().stream()
+                .map(StudentImportWrapper.StudentImport::getPhone)
+                .filter(StringUtils::isNotBlank)
+                .distinct()
+                .collect(Collectors.toList());
+        if (CollectionUtils.isNotEmpty(phones)) {
+            existPhones.addAll(easyExcelService.getPhones(phones,"STUDENT"));
+        }
+        tenantGroupMap.putAll(easyExcelService.getTenantGroupMap());
+        subjectMap.putAll(easyExcelService.getSubjectMap());
+        tenantMap.putAll(easyExcelService.getTenantMap());
+    }
+
+
+    /**
+     * 数据对象
+     * @return RoomInfoAnalysis
+     */
+    @Override
+    public StudentImportAnalysis get() {
+        return this;
+    }
+
+}

+ 2 - 2
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/execl/analysis/TeacherImportAnalysis.java

@@ -208,7 +208,7 @@ public class TeacherImportAnalysis extends DataAnalysis<TeacherImportAnalysis> {
                 .distinct()
                 .collect(Collectors.toList());
         if (CollectionUtils.isNotEmpty(phones)) {
-            existPhones.addAll(easyExcelService.getPhones(phones));
+            existPhones.addAll(easyExcelService.getPhones(phones, "TEACHER"));
         }
         List<String> idCardNos = getTeacherImportWrappers().stream()
                 .map(TeacherImportWrapper.TeacherImport::getIdCardNo)
@@ -216,7 +216,7 @@ public class TeacherImportAnalysis extends DataAnalysis<TeacherImportAnalysis> {
                 .distinct()
                 .collect(Collectors.toList());
         if (CollectionUtils.isNotEmpty(idCardNos)) {
-            existIdCardNos.addAll(easyExcelService.getIdCardNos(idCardNos));
+            existIdCardNos.addAll(easyExcelService.getIdCardNos(idCardNos, "TEACHER"));
         }
         subjectMap.putAll(easyExcelService.getSubjectMap());
         tenantMap.putAll(easyExcelService.getTenantMap());

+ 140 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/execl/entity/StudentImportWrapper.java

@@ -0,0 +1,140 @@
+package com.yonge.cooleshow.biz.dal.execl.entity;
+
+import com.alibaba.excel.annotation.ExcelIgnore;
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.alibaba.excel.converters.Converter;
+import com.alibaba.excel.enums.CellDataTypeEnum;
+import com.alibaba.excel.metadata.CellData;
+import com.alibaba.excel.metadata.GlobalConfiguration;
+import com.alibaba.excel.metadata.property.ExcelContentProperty;
+import com.yonge.cooleshow.common.enums.ESettlementFrom;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.apache.commons.lang3.StringUtils;
+
+@Data
+public class StudentImportWrapper {
+
+    @Data
+    @Builder
+    @NoArgsConstructor
+    @AllArgsConstructor
+    public static class StudentImport{
+        @ExcelProperty(value = "学生姓名")
+        private String userName;
+
+        @ExcelProperty(value = "手机号")
+        private String phone;
+
+        @ExcelProperty(value = "声部")
+        private String subjectName;
+
+        @ExcelIgnore
+        private Long subjectId;
+
+        @ExcelProperty(value = "出生日期")
+        private String birthday;
+
+        @ExcelProperty(value = "性别")
+        private String gender;
+
+        @ExcelProperty(value = "所属机构")
+        private String tenantName;
+
+        @ExcelIgnore
+        private Long tenantId;
+
+        @ExcelProperty(value = "小组")
+        private String tenantGroupName;
+
+        @ExcelIgnore
+        private Long tenantGroupId;
+
+        @ExcelIgnore
+        private Long updateBy;
+
+        @ExcelIgnore
+        private Long userId;
+
+        @ExcelIgnore
+        private Integer rowIndex;
+
+        @ExcelIgnore
+        private String sheetName;
+
+
+        public StudentImport rowIndex(Integer rowIndex) {
+            this.rowIndex = rowIndex;
+            return this;
+        }
+
+        public StudentImport sheetName(String sheetName) {
+            this.sheetName = sheetName;
+            return this;
+        }
+
+    }
+
+    public static class BooleanConvert implements Converter<Boolean> {
+
+        @Override
+        public Class<Boolean> supportJavaTypeKey() {
+            return Boolean.class;
+        }
+
+        @Override
+        public CellDataTypeEnum supportExcelTypeKey() {
+            return CellDataTypeEnum.STRING;
+        }
+
+        @Override
+        public Boolean convertToJavaData(CellData cellData, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) throws Exception {
+            String stringValue = cellData.getStringValue();
+            if (StringUtils.isNotEmpty(stringValue)) {
+                return "是".equals(stringValue) || "1".equals(stringValue);
+            }
+            return null;
+        }
+
+        @Override
+        public CellData convertToExcelData(Boolean aBoolean, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) throws Exception {
+            return null;
+        }
+    }
+
+
+    public static class SettlementFromConvert implements Converter<ESettlementFrom> {
+
+        @Override
+        public Class<ESettlementFrom> supportJavaTypeKey() {
+            return ESettlementFrom.class;
+        }
+
+        @Override
+        public CellDataTypeEnum supportExcelTypeKey() {
+            return CellDataTypeEnum.STRING;
+        }
+
+        @Override
+        public ESettlementFrom convertToJavaData(CellData cellData, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) throws Exception {
+            String stringValue = cellData.getStringValue();
+            if (StringUtils.isNotEmpty(stringValue)) {
+                if ("不结算".equals(stringValue)) {
+                    return ESettlementFrom.NO;
+                } else if ("结算给老师".equals(stringValue)) {
+                    return ESettlementFrom.TEACHER;
+                } else if ("结算给机构".equals(stringValue)) {
+                    return ESettlementFrom.TENANT;
+                }
+            }
+            return null;
+        }
+
+        @Override
+        public CellData<ESettlementFrom> convertToExcelData(ESettlementFrom o, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) throws Exception {
+            return null;
+        }
+    }
+}

+ 92 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/execl/listener/StudentImportListener.java

@@ -0,0 +1,92 @@
+package com.yonge.cooleshow.biz.dal.execl.listener;
+
+import com.alibaba.excel.context.AnalysisContext;
+import com.alibaba.excel.enums.RowTypeEnum;
+import com.alibaba.excel.event.AnalysisEventListener;
+import com.alibaba.excel.metadata.CellExtra;
+import com.google.common.collect.Lists;
+import com.yonge.cooleshow.biz.dal.execl.entity.StudentImportWrapper;
+import lombok.Getter;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * 课件信息读取监听器
+ * Created by Eric.Shang on 2020/7/1.
+ */
+@Slf4j
+@Getter
+public class StudentImportListener extends AnalysisEventListener<StudentImportWrapper.StudentImport> {
+
+    // 课件信息
+    private final List<StudentImportWrapper.StudentImport> importList;
+    // sheet名称
+    private final String sheetName;
+    // 合并标识
+    private Boolean mergeFlag;
+
+    public StudentImportListener(List<StudentImportWrapper.StudentImport> examinations, String sheetName) {
+        // 单元测试数据
+        this.importList = Optional.ofNullable(examinations).orElse(Lists.newArrayList());
+        // sheet名称
+        this.sheetName = sheetName;
+    }
+
+    /**
+     * 读取每行数据触发
+     * @param  examination 数据内容
+     * @param analysisContext AnalysisContext
+     */
+    @Override
+    public void invoke(StudentImportWrapper.StudentImport examination, AnalysisContext analysisContext) {
+        // 忽略空行读取
+        //analysisContext.readWorkbookHolder().setIgnoreEmptyRow(false);
+        // 读取数据
+        getImportList().add(examination.rowIndex(getImportList().size() + 2).sheetName(getSheetName()));
+    }
+
+    /**
+     * 空行数据判定
+     * @param context AnalysisContext
+     * @return boolean
+     */
+    @Override
+    public boolean hasNext(AnalysisContext context) {
+        // 忽略空行判定
+        if (RowTypeEnum.EMPTY.equals(context.readRowHolder().getRowType())){
+            doAfterAllAnalysed(context);
+            return false;
+        }
+
+        return super.hasNext(context);
+    }
+
+    /**
+     * 数据解板读完触发
+     * @param analysisContext AnalysisContext
+     */
+    @Override
+    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
+        // 这里也要保存数据,确保最后遗留的数据也存储到数据库
+    }
+
+    /**
+     * 额外信息(批注、超链接、合并单元格信息读取)
+     * @param extra CellExtra
+     * @param context AnalysisContext
+     */
+    @Override
+    public void extra(CellExtra extra, AnalysisContext context) {
+        switch (extra.getType()) {
+            case MERGE:
+                mergeFlag = false;
+                break;
+            case COMMENT:
+            case HYPERLINK:
+            default:
+                break;
+        }
+    }
+}

+ 5 - 3
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/EasyExcelService.java

@@ -2,7 +2,6 @@ package com.yonge.cooleshow.biz.dal.service;
 
 import com.yonge.cooleshow.biz.dal.entity.TenantAccountRecord;
 
-import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 
@@ -27,9 +26,12 @@ public interface EasyExcelService {
     //获取机构map
     Map<String,Long> getTenantMap();
 
+    //获取小组map
+    Map<String,Long> getTenantGroupMap();
+
     //根据手机号获取已存在的老师手机号
-    List<String> getPhones(List<String> phones);
+    List<String> getPhones(List<String> phones, String userType);
 
     //根据身份证号获取已存在的老师身份证号
-    List<String> getIdCardNos(List<String> idCardNos);
+    List<String> getIdCardNos(List<String> idCardNos, String userType);
 }

+ 7 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/StudentService.java

@@ -8,6 +8,7 @@ import com.yonge.cooleshow.biz.dal.dto.search.QueryMyFollowSearch;
 import com.yonge.cooleshow.biz.dal.dto.search.StudentSearch;
 import com.yonge.cooleshow.biz.dal.entity.Student;
 import com.yonge.cooleshow.biz.dal.entity.Subject;
+import com.yonge.cooleshow.biz.dal.execl.entity.StudentImportWrapper;
 import com.yonge.cooleshow.biz.dal.vo.MyFollow;
 import com.yonge.cooleshow.biz.dal.vo.StudentHomeVo;
 import com.yonge.cooleshow.biz.dal.vo.StudentVo;
@@ -125,6 +126,12 @@ public interface StudentService extends IService<Student> {
                             Long suerId);
 
     /**
+     * 导入学生
+     * @param dataList 数据列表
+     */
+    void importStudent(List<StudentImportWrapper.StudentImport> dataList);
+
+    /**
      * 学生修改机构
      * @param student 学生信息
      * @param toTenantId 机构ID

+ 13 - 4
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/EasyExcelServiceImpl.java

@@ -2,6 +2,7 @@ package com.yonge.cooleshow.biz.dal.service.impl;
 
 import com.yonge.cooleshow.biz.dal.entity.Subject;
 import com.yonge.cooleshow.biz.dal.entity.TenantAccountRecord;
+import com.yonge.cooleshow.biz.dal.entity.TenantGroup;
 import com.yonge.cooleshow.biz.dal.entity.TenantInfo;
 import com.yonge.cooleshow.biz.dal.service.*;
 import lombok.extern.slf4j.Slf4j;
@@ -28,6 +29,8 @@ public class EasyExcelServiceImpl implements EasyExcelService {
     @Resource
     private TenantInfoService tenantInfoService;
     @Resource
+    private TenantGroupService tenantGroupService;
+    @Resource
     private SysUserService sysUserService;
 
     @Override
@@ -51,12 +54,18 @@ public class EasyExcelServiceImpl implements EasyExcelService {
     }
 
     @Override
-    public List<String> getPhones(List<String> phones) {
-        return sysUserService.getDao().existPhones(phones,"TEACHER");
+    public Map<String, Long> getTenantGroupMap() {
+        List<TenantGroup> list = tenantGroupService.lambdaQuery().list();
+        return CollectionUtils.isEmpty(list) ? null : list.stream().collect(Collectors.toMap(TenantGroup::getName, TenantGroup::getId));
+    }
+
+    @Override
+    public List<String> getPhones(List<String> phones, String userType) {
+        return sysUserService.getDao().existPhones(phones,userType);
     }
 
     @Override
-    public List<String> getIdCardNos(List<String> idCardNos) {
-        return sysUserService.getDao().existIdCardNos(idCardNos,"TEACHER");
+    public List<String> getIdCardNos(List<String> idCardNos, String userType) {
+        return sysUserService.getDao().existIdCardNos(idCardNos,userType);
     }
 }

+ 22 - 6
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/ExcelAnalyseCoreServiceImpl.java

@@ -7,9 +7,9 @@ import com.microsvc.toolkit.middleware.excel.analysis.AnalysisContext;
 import com.microsvc.toolkit.middleware.oss.OssPluginContext;
 import com.microsvc.toolkit.middleware.oss.impl.TencentOssPlugin;
 import com.yonge.cooleshow.biz.dal.entity.FileImportInfo;
+import com.yonge.cooleshow.biz.dal.execl.analysis.StudentImportAnalysis;
 import com.yonge.cooleshow.biz.dal.execl.analysis.TeacherImportAnalysis;
 import com.yonge.cooleshow.biz.dal.execl.analysis.TenantAccountRecordImportAnalysis;
-import com.yonge.cooleshow.biz.dal.execl.entity.TeacherImportWrapper;
 import com.yonge.cooleshow.biz.dal.execl.entity.TenantAccountRecordImport;
 import com.yonge.cooleshow.biz.dal.service.*;
 import com.yonge.cooleshow.biz.dal.wrapper.FileImportInfoWrapper;
@@ -45,6 +45,8 @@ public class ExcelAnalyseCoreServiceImpl implements ExcelAnalyseCoreService {
     private TenantAccountRecordService tenantAccountRecordService;
     @Resource
     private TeacherService teacherService;
+    @Resource
+    private StudentService studentService;
 
     /**
      * 异步读取数据
@@ -93,6 +95,7 @@ public class ExcelAnalyseCoreServiceImpl implements ExcelAnalyseCoreService {
                     readTeacherExcelData(wrapper);
                     break;
                 case STUDENT: // 学生导入
+                    readStudentExcelData(wrapper);
                     break;
                 default:
                     break;
@@ -150,15 +153,28 @@ public class ExcelAnalyseCoreServiceImpl implements ExcelAnalyseCoreService {
         createFileImportRecord(wrapper, context);
 
         // 入库业务数据
-        List<TeacherImportWrapper.TeacherImport> collect = analysis.getTeacherImportWrappers().stream()
-                .filter(x -> !Optional.ofNullable(x.getPhone()).orElse("").equals("."))
-                .collect(Collectors.toList());
         if (context.getFailure() > 0) {
-            log.info("readTeacherExcelData collect.size={}", collect.size());
+            log.info("readExaminationExcelData collect.size={}", analysis.getTeacherImportWrappers().size());
             return;
         }
+        teacherService.importTeacher(analysis.getTeacherImportWrappers());
+    }
+
+    private void readStudentExcelData(FileImportInfoWrapper.FileImportInfo wrapper) {
+
+        // 解析excel文件,生成EchoInfoAnalysis对象
+        StudentImportAnalysis analysis = StudentImportAnalysis.build(easyExcelService).start(wrapper.getImportUrl()).get();
+
+        AnalysisContext context = analysis.getContext();
+        // 生成导入数据记录
+        createFileImportRecord(wrapper, context);
 
-        teacherService.importTeacher(collect);
+        // 入库业务数据
+        if (context.getFailure() > 0) {
+            log.info("readStudentExcelData collect.size={}", analysis.getStudentImportWrappers().size());
+            return;
+        }
+        studentService.importStudent(analysis.getStudentImportWrappers());
     }
 
     /**

+ 108 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/StudentServiceImpl.java

@@ -22,6 +22,8 @@ import com.yonge.cooleshow.biz.dal.dto.search.StudentSearch;
 import com.yonge.cooleshow.biz.dal.entity.*;
 import com.yonge.cooleshow.biz.dal.enums.*;
 import com.yonge.cooleshow.biz.dal.enums.im.EImUserFriendSourceForm;
+import com.yonge.cooleshow.biz.dal.execl.entity.StudentImportWrapper;
+import com.yonge.cooleshow.biz.dal.execl.entity.TeacherImportWrapper;
 import com.yonge.cooleshow.biz.dal.mapper.SysUserMapper;
 import com.yonge.cooleshow.biz.dal.mapper.TenantGroupAlbumMapper;
 import com.yonge.cooleshow.biz.dal.mapper.TenantGroupMapper;
@@ -47,6 +49,7 @@ import com.yonge.toolset.mybatis.support.PageUtil;
 import com.yonge.toolset.thirdparty.message.MessageSenderPluginContext;
 import com.yonge.toolset.utils.date.DateUtil;
 import com.yonge.toolset.utils.easyexcel.ExcelDataReaderProperty;
+import com.yonge.toolset.utils.idcard.IdcardInfoExtractor;
 import com.yonge.toolset.utils.string.ValueUtil;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
@@ -117,6 +120,8 @@ public class StudentServiceImpl extends ServiceImpl<StudentDao, Student> impleme
     private SysMusicCompareRecordService sysMusicCompareRecordService;
     @Resource
     private CourseScheduleService courseScheduleService;
+    @Resource
+    private UserTenantBindRecordService userTenantBindRecordService;
 
     @Override
     public StudentVo detail(Long userId) {
@@ -615,6 +620,109 @@ public class StudentServiceImpl extends ServiceImpl<StudentDao, Student> impleme
         }
     }
 
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void importStudent(List<StudentImportWrapper.StudentImport> studentImports) {
+        //设置默认头像
+        Date now = new Date();
+        String defaultHeard = sysConfigService.findConfigValue(SysConfigConstant.STUDENT_AVATAR);
+        List<SysUser> existUser = sysUserMapper.findUserByPhones(studentImports.stream()
+                .map(StudentImportWrapper.StudentImport::getPhone).collect(Collectors.toList()));
+        Map<String, SysUser> existUserMap = existUser.stream().collect(Collectors.toMap(SysUser::getPhone, o -> o));
+        List<SysUser> sysUsers = new ArrayList<>();
+        for (StudentImportWrapper.StudentImport studentImport : studentImports) {
+            SysUser sysUser = existUserMap.get(studentImport.getPhone());
+            if(sysUser == null) {
+                sysUser = new SysUser();
+                sysUser.setAvatar(defaultHeard);
+                sysUser.setPhone(studentImport.getPhone());
+                sysUser.setUsername(studentImport.getUserName());
+                sysUser.setBirthdate(DateUtil.stringToDate(studentImport.getBirthday(), DateUtil.DEFAULT_PATTERN));
+                sysUser.setGender("男".equals(studentImport.getGender()) ? 1 : 0);
+                sysUser.setTenantId(studentImport.getTenantId());
+                sysUser.setCreateTime(now);
+            }
+            if(StringUtils.isEmpty(sysUser.getPassword())){
+                //初始密码,klx+手机号四位
+                String password = "klx" + sysUser.getPhone().substring(sysUser.getPhone().length() - 4);
+                sysUser.setPassword(new BCryptPasswordEncoder().encode(password));
+            }
+            if (StringUtil.isEmpty(sysUser.getUserType())) {
+                sysUser.setUserType("STUDENT");
+            } else if (!sysUser.getUserType().contains("STUDENT")) {
+                sysUser.setUserType(sysUser.getUserType() + ",STUDENT");
+            }
+            sysUser.setUpdateTime(now);
+            sysUsers.add(sysUser);
+        }
+        //获取需要新增的用户
+        List<SysUser> addUsers = sysUsers.stream().filter(o -> o.getId() == null).collect(Collectors.toList());
+        if (org.apache.commons.collections.CollectionUtils.isNotEmpty(addUsers)) {
+            sysUserMapper.batchInsert(addUsers);
+        }
+        //获取修改的用户
+        List<SysUser> updateUsers = sysUsers.stream().filter(o -> o.getId() != null).collect(Collectors.toList());
+        if (org.apache.commons.collections.CollectionUtils.isNotEmpty(updateUsers)) {
+            sysUserMapper.batchUpdate(updateUsers);
+        }
+        //获取所有用户编号
+        List<Long> userIds = sysUsers.stream().map(SysUser::getId).collect(Collectors.toList());
+        //机构学员添加机构绑定记录
+        List<UserTenantBindRecord> userTenantBindRecords = userTenantBindRecordService.lambdaQuery().in(UserTenantBindRecord::getUserId, userIds).list();
+        Map<Long, UserTenantBindRecord> userTenantBindRecordMap = userTenantBindRecords.stream().collect(Collectors.toMap(UserTenantBindRecord::getUserId, o -> o));
+        List<UserTenantBindRecord> bindRecords = new ArrayList<>();
+        //保存老师信息
+        Map<String,StudentImportWrapper.StudentImport> studentImportMap = studentImports.stream()
+                .collect(Collectors.toMap(StudentImportWrapper.StudentImport::getPhone, o -> o));
+        List<Student> students = new ArrayList<>();
+        for (SysUser sysUser : sysUsers) {
+            StudentImportWrapper.StudentImport studentImport = studentImportMap.get(sysUser.getPhone());
+            Student student = new Student();
+            student.setUserId(sysUser.getId());
+            student.setTenantId(sysUser.getTenantId());
+            student.setSubjectId(studentImport.getSubjectId().toString());
+            student.setAvatar(sysUser.getAvatar());
+            student.setCreateTime(now);
+            student.setLockFlag(UserLockFlag.NORMAL);
+            student.setTenantGroupId(studentImport.getTenantGroupId());
+            students.add(student);
+
+            //机构学员添加机构绑定记录
+            UserTenantBindRecord userTenantBindRecord = userTenantBindRecordMap.get(sysUser.getId());
+            if (userTenantBindRecord == null) {
+                userTenantBindRecord = new UserTenantBindRecord();
+                userTenantBindRecord.setUserId(sysUser.getId());
+                userTenantBindRecord.setUserType("STUDENT");
+                userTenantBindRecord.setTenantId(sysUser.getTenantId());
+                userTenantBindRecord.setBindStatus(true);
+                userTenantBindRecord.setBindTime(now);
+                bindRecords.add(userTenantBindRecord);
+            }
+        }
+        this.saveBatch(students);
+        if (CollectionUtils.isNotEmpty(bindRecords)) {
+            userTenantBindRecordService.saveBatch(bindRecords);
+        }
+        for (SysUser sysUser : sysUsers) {
+            try {
+                imGroupCoreService.register(String.valueOf(sysUser.getId()), ClientEnum.STUDENT.getCode(),
+                        sysUser.getUsername(), sysUser.getAvatar());
+                // 加好友
+                if (sysUser.getTenantId() != null && sysUser.getTenantId() != -1L) {
+                    // 自动与机构老师成为好友
+                    QueryWrapper<Teacher> queryWrapper = new QueryWrapper<>();
+                    queryWrapper.lambda().eq(Teacher::getTenantId, sysUser.getTenantId());
+                    List<Teacher> teacherList = teacherDao.selectList(queryWrapper);
+                    teacherList.forEach(next ->
+                            imUserFriendService.saveUserFriend(next.getUserId(), new HashSet<>(ImmutableList.of(sysUser.getId())), EImUserFriendSourceForm.TEACHER)
+                    );
+                }
+            } catch (Exception e) {
+                log.error("导入IM账号到三方 studentId={}", sysUser.getId(), e);
+            }
+        }
+    }
+
     @Transactional(rollbackFor = Exception.class)
     @Override
     public void updateTenant(Student student, Long toTenantId) {

+ 3 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/wrapper/StudentWrapper.java

@@ -147,6 +147,9 @@ public class StudentWrapper {
         @ExcelProperty(value = "性别")
         private String gender;
 
+        @ExcelProperty(value = "所属机构")
+        private String tenantName;
+
         @ExcelProperty(value = "小组")
         private String tenantGroupName;