This commit is contained in:
Paidax
2024-04-30 15:04:35 +08:00
parent 9affbf3f04
commit 6c8e8f518a
5 changed files with 401 additions and 5 deletions
@@ -54,7 +54,8 @@ public class loginController {
""").setParam("loginname", loginname).setParam("username", username);
sql.setVar("schoolCode", Globals.schoolCode);
Cnd cnd = Cnd.NEW();
cnd.and("LOWER(u.loginname)", "=", loginname.trim().toLowerCase());
// cnd.and("LOWER(u.loginname)", "=", loginname.trim().toLowerCase());
cnd.and(Cnd.exps("LOWER(u.loginname)", "=", loginname.trim().toLowerCase()).or("LOWER(u.mobile)", "=", loginname.trim().toLowerCase()));
cnd.and("LOWER(u.username)", "=", username.trim().toLowerCase());
sql.setCondition(cnd);
sql.setCallback(Sqls.callback.map());
@@ -1,22 +1,33 @@
package io.v.nutz.retired.user.controller;
import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import io.v.nutz.activity.models.ActivityUserScope;
import io.v.nutz.annontation.ViReturn;
import io.v.nutz.base.page.Pagination;
import io.v.nutz.base.result.Result;
import io.v.nutz.base.utils.PinyinUtil;
import io.v.nutz.member.UserMode;
import io.v.nutz.modules.models.PageForm;
import io.v.nutz.retired.group.model.RetiredGroup;
import io.v.nutz.retired.group.model.RetiredUserHistory;
import io.v.nutz.retired.partyBranch.model.RetiredPartyBranch;
import io.v.nutz.retired.user.contants.RetiredUserChangeType;
import io.v.nutz.retired.user.mode.RetiredUserTemplate;
import io.v.nutz.retired.user.model.RetiredUserChange;
import io.v.nutz.sys.models.Sys_user;
import io.v.nutz.sys.models.Sys_user_role;
import io.v.nutz.sys.services.SysUserService;
import io.v.nutz.util.ViTool;
import io.v.nutz.web.commons.utils.ShiroUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.nutz.aop.interceptor.ioc.TransAop;
import org.nutz.dao.Chain;
@@ -31,14 +42,21 @@ import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Lang;
import org.nutz.lang.random.R;
import org.nutz.lang.util.NutMap;
import org.nutz.mvc.annotation.AdaptBy;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
import org.nutz.mvc.annotation.Param;
import org.nutz.mvc.upload.TempFile;
import org.nutz.mvc.upload.UploadAdaptor;
import org.springframework.beans.BeanUtils;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.Function;
import java.util.stream.Collectors;
@IocBean
@@ -318,5 +336,139 @@ public class RetiredUserListController {
return null;
}
/**
* 离退休人员,导入下载模版
*
* @param response
*/
@At
@Ok("void")
@RequiresPermissions("retired.user.list")
public void downloadImport(HttpServletResponse response) {
try {
ViTool.excelResponse(response, "离退休人员导入模版.xlsx");
ExportParams exportParams = new ExportParams();
exportParams.setType(ExcelType.XSSF);
Workbook sheets = ExcelExportUtil.exportExcel(exportParams, RetiredUserTemplate.class, new ArrayList<>());
ServletOutputStream outputStream = response.getOutputStream();
sheets.write(outputStream);
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
@At
@AdaptBy(type = UploadAdaptor.class, args = {"ioc:fileUpload"})
@Aop(TransAop.READ_COMMITTED)
@RequiresPermissions("retired.user.list")
public Object doImport(TempFile file) {
try {
List<RetiredUserTemplate> retiredUserImportList = ExcelImportUtil.importExcel(file.getFile(), RetiredUserTemplate.class, new ImportParams());
List<Sys_user> users = sysUserService.query(Cnd.where("idcard", "is not", null).and("idcard", "!=", ""));
Map<String, Sys_user> userMap = users.stream().collect(Collectors.toMap(Sys_user::getIdcard, Function.identity(), (o1, o2) -> o1));
List<RetiredUserTemplate> errorInfos = new ArrayList<>();
//需要新增的离退休人员
List<Sys_user> needInsertUserList = new ArrayList<>();
//需要修改的离退休人员
List<Sys_user> needUpdateUserList = new ArrayList<>();
List<ActivityUserScope> userScopeList = new ArrayList<>();
Sql sql = Sqls.create("SELECT MAX(DISTINCT groupId) AS groupId FROM activity_user_scope");
NutMap query = (NutMap) Daos.query(dao, sql.toString(), Sqls.callback.map());
String groupName = DateUtil.thisYear() + "" + (DateUtil.thisMonth() + 1) + "月离退休教职工";
for (RetiredUserTemplate template : retiredUserImportList) {
if (StrUtil.isBlank(template.getUsername())) {
template.setErrorMsg("获取不到该用户的姓名!");
errorInfos.add(template);
continue;
} else if (StrUtil.isBlank(template.getIdCard())) {
template.setErrorMsg("获取不到该用户的身份证号!");
errorInfos.add(template);
continue;
}
Sys_user user = new Sys_user();
user.setRetired(true);
user.setRetireNature(template.getRetireNature());
user.setUsername(template.getUsername().trim());
user.setSex(template.getSex());
user.setNation(template.getNation());
// user.setBirthday(template.getBirthday());
// user.setPartyJoiningTime(DateUtil.parse(template.getPartyJoiningTime(),"yyyy-MM"));
// user.setWorkStartDate(DateUtil.parse(template.getWorkStartDate(),"yyyy-MM"));
// user.setSchoolTime(template.getSchoolTime());
user.setEducation(template.getEducation());
user.setHometown(template.getHometown());
user.setJobTitle(template.getJobTitle());
user.setTreatment(template.getTreatment());
// user.setRetirementTime(DateUtil.parse(template.getRetirementTime(),"yyyy-MM"));
user.setIdcard(template.getIdCard());
user.setMedicalCertificateNumber(template.getMedicalCertificateNumber());
user.setOriginalDepartment(template.getOriginalDepartment());
user.setFamilyName(template.getFamilyName());
user.setHomeAddress(template.getHomeAddress());
user.setRetirePhone(template.getRetirePhone());
user.setRetireNotes(template.getRetireNotes());
user.setBasicDiseaseInfo(template.getBasicDiseaseInfo());
Sys_user sysUser = userMap.get(template.getIdCard());
ActivityUserScope userScope = new ActivityUserScope();
userScope.setGroupName(groupName);
userScope.setGroupId(Integer.parseInt(query.getString("groupId")));
if (Lang.isNotEmpty(sysUser)) {
user.setId(sysUser.getId());
userScope.setUserId(sysUser.getId());
needUpdateUserList.add(user);
} else {
String pinYinHeadChar = PinyinUtil.getPinYinHeadChar(template.getUsername().trim());
String idCardLastSix = template.getIdCard().substring(template.getIdCard().length() - 6);
user.setLoginname(pinYinHeadChar + idCardLastSix);
Sys_user initUser = UserMode.initUser(user);
initUser.setRetired(true);
userScope.setUserId(initUser.getId());
needInsertUserList.add(initUser);
}
userScopeList.add(userScope);
}
if (Lang.isNotEmpty(needInsertUserList)) {
sysUserService.dao().fastInsert(needInsertUserList);
}
if (Lang.isNotEmpty(needInsertUserList)) {
sysUserService.dao().updateIgnoreNull(needUpdateUserList);
}
if (Lang.isNotEmpty(userScopeList)) {
sysUserService.dao().insert(userScopeList);
}
if (Lang.isNotEmpty(errorInfos)) {
NutMap nutMap = NutMap.NEW();
nutMap.setv("totalCount", retiredUserImportList.size());
nutMap.setv("successCount", (needUpdateUserList.size() + needUpdateUserList.size()));
nutMap.setv("errorCount", errorInfos.size());
nutMap.setv("errorList", errorInfos.stream().map(v -> {
return NutMap.NEW().addv("姓名", v.getUsername()).addv("错误原因", v.getErrorMsg());
}).collect(Collectors.toList()));
return Result.success(nutMap);
}
return Result.success();
} catch (Exception e) {
e.printStackTrace();
return Result.error();
}
}
}
@@ -0,0 +1,86 @@
package io.v.nutz.retired.user.mode;
import cn.afterturn.easypoi.excel.annotation.Excel;
import lombok.Data;
/**
* @version 1.0
* @Author zzr
* @nameRetiredUserTemplate
* @Date 2024/4/29 17:32
* @注释 离退休人员导入模版
*/
@Data
public class RetiredUserTemplate {
// @Excel(name = "工号")
private String loginName;
@Excel(name = "性质")
private String retireNature;
@Excel(name = "姓名")
private String username;
@Excel(name = "性别")
private String sex;
@Excel(name = "民族")
private String nation;
@Excel(name = "出生年月",importFormat = "yyyy-MM")
private String birthday;
@Excel(name = "入党时间",importFormat = "yyyy-MM")
private String partyJoiningTime;
@Excel(name = "所属支部")
private String belongBranch;
@Excel(name = "工作时间",importFormat = "yyyy-MM")
private String workStartDate;
@Excel(name = "进校时间",importFormat = "yyyy-MM")
private String schoolTime;
@Excel(name = "文化程度")
private String education;
@Excel(name = "籍贯")
private String hometown;
@Excel(name = "职称")
private String jobTitle;
@Excel(name = "待遇")
private String treatment;
@Excel(name = "退休时间",importFormat = "yyyy-MM")
private String retirementTime;
@Excel(name = "身份证号码")
private String idCard;
@Excel(name = "医疗证号")
private String medicalCertificateNumber;
@Excel(name = "基础病信息")
private String basicDiseaseInfo;
@Excel(name = "原部门")
private String originalDepartment;
@Excel(name = "家属姓名")
private String familyName;
@Excel(name = "家庭住址")
private String homeAddress;
@Excel(name = "联系方式")
private String retirePhone;
@Excel(name = "备注")
private String retireNotes;
private String errorMsg;
}
@@ -236,13 +236,13 @@ layout("/layouts/platform.html"){
<el-col :span="12">
<el-form-item label="主活动名称" prop="masterActivityName"
:rules="[{ required:true, message: '请填写主活动名称' }]">
<el-input type="text" v-model="formData.masterActivityName" maxlength="20"
<el-input type="text" v-model="formData.masterActivityName" maxlength="50"
placeholder="请填写主活动名称"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="分活动名称" prop="branchActivityName">
<el-input type="text" v-model="formData.branchActivityName" maxlength="20"
<el-input type="text" v-model="formData.branchActivityName" maxlength="50"
placeholder="请填写分活动名称"></el-input>
</el-form-item>
</el-col>
@@ -70,6 +70,7 @@ layout("/layouts/platform.html"){
<el-card shadow="never" class="mt10">
<table-tool label="退休人员" :app="this">
<template #func>
<el-button size="small" type="primary" @click="openImport">导入离退休人员</el-button>
<el-button size="small" type="primary" @click="openAdd">新增退休人员(系统中不存在)</el-button>
<el-button size="small" type="primary" @click="openSet">设置退休人员(系统中存在)</el-button>
<el-button size="small" type="primary" @click="backUp">备份为历史数据</el-button>
@@ -189,8 +190,74 @@ layout("/layouts/platform.html"){
<el-button type="primary" @click="doBatchJoinRetire">确定</el-button>
</span>
</el-drawer>
<el-dialog
title="导入离退休人员"
:visible.sync="importVisible"
:close-on-click-modal="false"
width="50%">
<el-timeline>
<el-timeline-item timestamp="下载模板" placement="top">
<el-card>
<el-button size="medium" type=""
@click="location.href='/platform/retiredUser/list/downloadImport'"
icon="el-icon-download">下载模板
</el-button>
</el-card>
</el-timeline-item>
<el-timeline-item timestamp="上传文件" placement="top">
<el-card>
<el-form>
<el-upload
name="file"
ref="upload"
:on-remove="(file, fileList) => {
importData.fileList = fileHandleRemove(file, fileList);
importResult={
errorCount:0,
successCount:0,
totalCount:0,
errorList:[]
}
}"
:on-change="(file, fileList) => {
importData.fileList = fileHandleChange(file, fileList,{type:['xls','xlsx']})
}"
:auto-upload="false"
:limit="1"
:file-list="importData.fileList">
<el-button size="medium" type="" icon="el-icon-upload"
style="width: 200px">选择文件
</el-button>
<div class="el-upload__tip" slot="tip" style="color: #F56C6C">
只能上传 xls/xlsx 文件
</div>
</el-upload>
</el-form>
</el-card>
</el-timeline-item>
<el-timeline-item placement="top" timestamp="导入结果">
<el-card shadow="never">
<p>总记录数:{{errorInfoData.totalCount}}</p>
<p>成功数:<span class="text-success">{{errorInfoData.successCount}}</span></p>
<p>错误数:<span class="text-danger">{{errorInfoData.errorCount}}</span></p>
<el-link @click="exportErrors" type="primary" v-if="errorInfoData.errorCount>0">下载错误记录
</el-link>
</el-card>
</el-timeline-item>
</el-timeline>
<span slot="footer" class="dialog-footer">
<el-button @click="importVisible = false" :disabled="importLoading">取 消</el-button>
<el-button type="primary" @click="doImport" :loading="importLoading">确定</el-button>
</span>
</el-dialog>
</guava>
</div>
<script src="https://cdn.staticfile.org/xlsx/0.18.5/xlsx.full.min.js"></script>
<script>
const vue = new Vue({
el: '#app',
@@ -239,8 +306,19 @@ layout("/layouts/platform.html"){
retiredGroupOption: [],
retiredPartyBranchOption: [],
userId: null
userId: null,
importVisible: false,
importLoading: false,
importData: {
fileList: [],
},
errorInfoData: {
totalCount: 0,
successCount: 0,
errorCount: 0,
errorList: 0,
},
}
},
methods: {
@@ -360,7 +438,86 @@ layout("/layouts/platform.html"){
} else {
this.$message.warning(resp.msg)
}
}
},
openImport(){
this.importData = {
fileList: [],
}
this.errorInfoData = {
totalCount: 0,
successCount: 0,
errorCount: 0,
errorList: 0,
}
this.importVisible = true;
},
doImport(){
if (this.importData.fileList.length === 0) {
this.notifyWarning("请选择文件!")
return
}
const data = new FormData();
data.append("isFlag", this.importData.isFlag)
this.importData.fileList.forEach((val) => {
data.append("file", val.raw, val.raw.name);
});
this.importLoading = true
$.ajax({
url: loc() + "/doImport",
type: "post",
data: data,
processData: false,
contentType: false,
success: (data) => {
this.importLoading = false
if (data.code === 0 && data.data === null) {
this.pageData();
this.notifySuccess("导入成功")
this.importVisible = false
} else {
this.notifyWarning("导入失败")
this.errorInfoData = data.data
}
},
error: (data) => {
this.notifyWarning("导入失败")
this.importLoading = false
}
});
},
exportErrors() {
const data = this.errorInfoData.errorList
// 创建工作簿
const workbook = XLSX.utils.book_new();
// 创建工作表
const worksheet = XLSX.utils.json_to_sheet(data);
// 将工作表添加到工作簿
XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1');
// 将工作簿转换为二进制对象
const excelBuffer = XLSX.write(workbook, {bookType: 'xlsx', type: 'array'});
// 将二进制对象转换为Blob对象
const blob = new Blob([excelBuffer], {type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'});
// 创建下载链接并设置相关属性
const url = window.URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.download = '错误记录.xlsx';
// 模拟点击下载链接
document.body.appendChild(link);
link.click();
// 清理下载链接
document.body.removeChild(link);
window.URL.revokeObjectURL(url);
},
},
async created() {
this.pageData()