This commit is contained in:
Paidax
2024-11-29 09:03:59 +08:00
commit 2ffadd89a7
3480 changed files with 879405 additions and 0 deletions
@@ -0,0 +1,190 @@
package io.v.nutz.zhgh.data.constant;
import io.v.nutz.base.annontation.SelectEnum;
import lombok.Getter;
import org.nutz.dao.util.cri.SqlExpressionGroup;
/**
* 条件运算符
*
* @author: 1V
* @date: 2021/3/1
* @since 1.0
*/
@Getter
@SelectEnum
public enum ConditionalOperational {
EQ("=", "等于(=)") {
@Override
public SqlExpressionGroup exec(SqlExpressionGroup seg, String name, Object value, MatchMethod matchMethod) throws Exception {
if (matchMethod == MatchMethod.OR) {
seg.orEquals(name, value);
} else if (matchMethod == MatchMethod.AND) {
seg.andEquals(name, value);
}
return seg;
}
}, NEQ("!=", "不等于(!=)") {
@Override
public SqlExpressionGroup exec(SqlExpressionGroup seg, String name, Object value, MatchMethod matchMethod) throws Exception {
if (matchMethod == MatchMethod.OR) {
seg.orNotEquals(name, value);
} else if (matchMethod == MatchMethod.AND) {
seg.andNotEquals(name, value);
}
return seg;
}
}, IS("IS", "是(IS,仅适用于boolean字段)") {
@Override
public SqlExpressionGroup exec(SqlExpressionGroup seg, String name, Object value, MatchMethod matchMethod) throws Exception {
if (matchMethod == MatchMethod.OR) {
seg.or(name, "is", value.equals("true"));
} else if (matchMethod == MatchMethod.AND) {
seg.and(name, "is", value.equals("true"));
}
return seg;
}
}, NOT_IS("NOT IS", "否(NOT IS,仅适用于boolean字段)") {
@Override
public SqlExpressionGroup exec(SqlExpressionGroup seg, String name, Object value, MatchMethod matchMethod) throws Exception {
if (matchMethod == MatchMethod.OR) {
seg.or(name, "is not", value.equals("true"));
} else if (matchMethod == MatchMethod.AND) {
seg.and(name, "is not", value.equals("true"));
}
return seg;
}
}, LT("<", "小于(<)") {
@Override
public SqlExpressionGroup exec(SqlExpressionGroup seg, String name, Object value, MatchMethod matchMethod) throws Exception {
if (matchMethod == MatchMethod.OR) {
seg.or(name, "<", value.toString());
} else if (matchMethod == MatchMethod.AND) {
seg.and(name, "<", value.toString());
}
return seg;
}
}, LTE("<=", "小于等于(<=)") {
@Override
public SqlExpressionGroup exec(SqlExpressionGroup seg, String name, Object value, MatchMethod matchMethod) throws Exception {
if (matchMethod == MatchMethod.OR) {
seg.or(name, "<=", value.toString());
} else if (matchMethod == MatchMethod.AND) {
seg.and(name, "<=", value.toString());
}
return seg;
}
}, GT(">", "大于(>)") {
@Override
public SqlExpressionGroup exec(SqlExpressionGroup seg, String name, Object value, MatchMethod matchMethod) throws Exception {
if (matchMethod == MatchMethod.OR) {
seg.or(name, ">", value.toString());
} else if (matchMethod == MatchMethod.AND) {
seg.and(name, ">", value.toString());
}
return seg;
}
}, GTE(">=", "大于等于(>=)") {
@Override
public SqlExpressionGroup exec(SqlExpressionGroup seg, String name, Object value, MatchMethod matchMethod) throws Exception {
if (matchMethod == MatchMethod.OR) {
//seg.orGTE(name, Long.parseLong(value.toString()));
seg.or(name, ">=", value.toString());
} else if (matchMethod == MatchMethod.AND) {
//seg.andGTE(name, Long.parseLong(value.toString()));
seg.and(name, ">=", value.toString());
}
return seg;
}
}, LEFT_LIKE("LIKE_LEFT", "以...开始(like '%s')") {
@Override
public SqlExpressionGroup exec(SqlExpressionGroup seg, String name, Object value, MatchMethod matchMethod) throws Exception {
if (matchMethod == MatchMethod.OR) {
seg.orLikeL(name, (String) value);
} else if (matchMethod == MatchMethod.AND) {
seg.andLikeL(name, (String) value);
}
return seg;
}
}, RIGHT_LIKE("LIKE_RIGHT", "以...结尾(like 's%')") {
@Override
public SqlExpressionGroup exec(SqlExpressionGroup seg, String name, Object value, MatchMethod matchMethod) throws Exception {
if (matchMethod == MatchMethod.OR) {
seg.orLikeR(name, (String) value);
} else if (matchMethod == MatchMethod.AND) {
seg.andLikeR(name, (String) value);
}
return seg;
}
}, LIKE("LIKE", "在...中(like '%s%')") {
@Override
public SqlExpressionGroup exec(SqlExpressionGroup seg, String name, Object value, MatchMethod matchMethod) throws Exception {
if (matchMethod == MatchMethod.OR) {
seg.orLike(name, (String) value);
} else if (matchMethod == MatchMethod.AND) {
seg.andLike(name, (String) value);
}
return seg;
}
}, IN("IN", "包含(in,使用英文逗号分割)") {
@Override
public SqlExpressionGroup exec(SqlExpressionGroup seg, String name, Object value, MatchMethod matchMethod) throws Exception {
String[] values = String.valueOf(value).split(",");
if (matchMethod == MatchMethod.OR) {
seg.or(name, "in", values);
// seg.orIn(name, ((String) value).split(","));
} else if (matchMethod == MatchMethod.AND) {
// seg.andIn(name, (String) value);
seg.and(name, "in", values);
}
return seg;
}
}, NOT_IN("NOT IN", "不包含(not in,使用逗号分割)") {
@Override
public SqlExpressionGroup exec(SqlExpressionGroup seg, String name, Object value, MatchMethod matchMethod) throws Exception {
String[] values = String.valueOf(value).split(",");
if (matchMethod == MatchMethod.OR) {
seg.or(name, "not in", values);
// seg.orIn(name, ((String) value).split(","));
} else if (matchMethod == MatchMethod.AND) {
// seg.andIn(name, (String) value);
seg.and(name, "not in", values);
}
return seg;
}
}, BETWEEN("BETWEEN", "之间(BETWEEN,使用逗号分割)") {
@Override
public SqlExpressionGroup exec(SqlExpressionGroup seg, String name, Object value, MatchMethod matchMethod) throws Exception {
String[] values = String.valueOf(value).split(",");
if (matchMethod == MatchMethod.OR) {
seg.or(name, "between", values);
} else if (matchMethod == MatchMethod.AND) {
seg.and(name, "between", values);
}
return seg;
}
}, NOT_BETWEEN("NOT BETWEEN", "不在之间(BETWEEN,使用逗号分割)") {
@Override
public SqlExpressionGroup exec(SqlExpressionGroup seg, String name, Object value, MatchMethod matchMethod) throws Exception {
String[] values = String.valueOf(value).split(",");
if (matchMethod == MatchMethod.OR) {
seg.or(name, "between", values);
} else if (matchMethod == MatchMethod.AND) {
seg.and(name, "between", values);
}
return seg;
}
};
private String value;
private String description;
ConditionalOperational(String value, String description) {
this.value = value;
this.description = description;
}
public abstract SqlExpressionGroup exec(SqlExpressionGroup seg, String name, Object value, MatchMethod matchMethod) throws Exception;
}
@@ -0,0 +1,549 @@
package io.v.nutz.zhgh.data.constant;
import java.util.HashMap;
import java.util.Map;
/**
* 数据常量 人员类型 民族等等
*/
public class DataConstant {
public static Map<String, String> MZ_MAP = new HashMap<String, String>() {{
put("01", "汉族");
put("02", "蒙古族");
put("03", "回族");
put("04", "藏族");
put("05", "维吾尔族");
put("06", "苗族");
put("07", "彝族");
put("08", "壮族");
put("09", "布依族");
put("10", "朝鲜族");
put("11", "满族");
put("12", "侗族");
put("13", "瑶族");
put("14", "白族");
put("15", "土家族");
put("16", "哈尼族");
put("17", "哈萨克族");
put("18", "傣族");
put("19", "黎族");
put("20", "傈僳族");
put("21", "佤族");
put("22", "畲族");
put("23", "高山族");
put("24", "拉祜族");
put("25", "水族");
put("26", "东乡族");
put("27", "纳西族");
put("28", "景颇族");
put("29", "柯尔克孜族");
put("30", "土族");
put("31", "达斡尔族");
put("32", "仫佬族");
put("33", "羌族");
put("34", "布朗族");
put("35", "撒拉族");
put("36", "毛难族");
put("37", "仡佬族");
put("38", "锡伯族");
put("39", "阿昌族");
put("40", "普米族");
put("41", "塔吉克族");
put("42", "怒族");
put("43", "乌孜别克族");
put("44", "俄罗斯族");
put("45", "鄂温克族");
put("46", "崩龙族");
put("47", "保安族");
put("48", "裕固族");
put("49", "京族");
put("50", "塔塔尔族");
put("51", "独龙族");
put("52", "鄂伦春族");
put("53", "赫哲族");
put("54", "门巴族");
put("55", "珞巴族");
put("56", "基诺族");
put("97", "其他");
put("98", "外国血统");
}};
public static Map<String, String> USER_STATE_MAP = new HashMap<String, String>() {{
put("105", "退休-转编外");
put("215", "离校未办手续");
put("0", "在职");
put("001", "在岗");
put("002", "因公出国");
put("003", "长病假");
put("004", "停薪留职");
put("005", "待岗");
put("006", "内退");
put("007", "下落不明");
put("008", "其他");
put("1", "离退休");
put("101", "离休");
put("102", "退休");
put("103", "退休-返聘");
put("104", "退职");
put("2", "离校");
put("201", "调出");
put("202", "辞职");
put("203", "博士后出站");
put("204", "博士后退站");
put("205", "合同到期不续聘");
put("206", "解聘");
put("207", "自动离职");
put("208", "开除");
put("209", "辞退");
put("210", "解除劳动合同");
put("211", "终止劳动合同");
put("212", "在职去世");
put("213", "退休去世");
put("214", "离休去世");
put("3", "报到中");
put("220", "报到终止");
}};
public static Map<String, String> JOB_MAP = new HashMap<String, String>() {{
put("420", "船舶技术人员(驾驶)");
put("422", "高级船长");
put("423", "船长(大副)");
put("424", "二副");
put("425", "三副");
put("430", "船舶技术人员(轮机)");
put("432", "高级轮机长");
put("433", "轮机长(大管轮)");
put("434", "二管轮");
put("435", "三管轮");
put("440", "船舶技术人员(电机)");
put("442", "高级电机员");
put("443", "通用电机员(一等电机员)");
put("444", "二等电机员");
put("450", "船舶技术人员(报务)");
put("452", "高级报务员");
put("453", "通用报务员");
put("454", "二等报务员");
put("455", "限用报务员");
put("460", "飞行技术人员(驾驶)");
put("462", "一级飞行员");
put("463", "二级飞行员");
put("464", "三级飞行员");
put("465", "四级飞行员");
put("470", "飞行技术人员(领航)");
put("472", "一级领航员");
put("473", "二级领航员");
put("474", "三级领航员");
put("010", "高等学校教师");
put("011", "教授");
put("012", "副教授");
put("019", "未评职称(高校教师)");
put("022", "高级讲师(中专)");
put("024", "助理讲师(中专)");
put("025", "教员(中专)");
put("030", "技工学校教师");
put("032", "高级讲师(技校)");
put("033", "讲师(技校)");
put("034", "助理讲师(技校)");
put("035", "教员(技校)");
put("040", "技工学校教师(实习指导)");
put("042", "高级实习指导教师");
put("043", "一级实习指导教师");
put("044", "二级实习指导教师");
put("045", "三级实习指导教师");
put("050", "中学教师");
put("052", "高级教师(中学)");
put("053", "一级教师(中学)");
put("054", "二级教师(中学)");
put("055", "三级教师(中学)");
put("061", "正高级教师");
put("062", "高级教师");
put("064", "二级教师");
put("065", "三级教师");
put("070", "实验技术人员");
put("072", "高级实验师");
put("073", "实验师");
put("075", "实验员");
put("080", "实验工程技术人员");
put("081", "教授级高级工程师");
put("082", "高级工程师");
put("084", "助理工程师");
put("085", "技术员");
put("091", "农业技术推广研究员(农艺)");
put("093", "农艺师");
put("094", "助理农艺师");
put("095", "农业技术员");
put("100", "农业技术人员(兽医)");
put("1000", "技术员");
put("102", "高级兽医师");
put("103", "兽医师");
put("104", "助理兽医师");
put("110", "农业技术人员(畜牧)");
put("113", "畜牧师");
put("114", "助理畜牧师");
put("120", "经济专业人员");
put("122", "高级经济师");
put("123", "经济师");
put("124", "助理经济师");
put("125", "经济员");
put("130", "会计专业人员");
put("132", "高级会计师");
put("133", "会计师");
put("134", "助理会计师");
put("135", "会计员");
put("142", "高级统计师");
put("143", "统计师");
put("145", "统计员");
put("151", "编审");
put("152", "副编审");
put("153", "编辑");
put("154", "助理编辑");
put("163", "技术编辑");
put("164", "助理技术编辑");
put("165", "技术设计员");
put("170", "出版专业人员(校对)");
put("174", "二级校对");
put("175", "三级校对");
put("181", "译审");
put("183", "翻译");
put("184", "助理翻译");
put("190", "新闻专业人员(记者)");
put("191", "高级记者");
put("192", "主任记者");
put("193", "记者");
put("A984", "助教(思政)");
put("194", "助理记者");
put("A980", "思政(南京大学)");
put("A981", "教授(思政)");
put("A982", "副教授(思政)");
put("A983", "讲师(思政)");
put("200", "新闻专业人员(编辑)");
put("201", "高级编辑");
put("202", "主任编辑");
put("693", "主检法医师");
put("694", "法医师");
put("695", "法医士");
put("972", "副译审");
put("981", "教授级高级政工师");
put("983", "政工师");
put("985", "政工员");
put("990", "高等学校教师(改革)");
put("992", "副教授(改革)");
put("995", "建设专业人员");
put("996", "正高级建筑师");
put("997", "高级建筑师");
put("999", "助理建筑师");
put("203", "编辑");
put("204", "助理编辑");
put("210", "图书、文博、档案、资料人员");
put("211", "研究馆员");
put("212", "副研究馆员");
put("213", "馆员");
put("214", "助理馆员");
put("215", "管理员");
put("220", "播音员");
put("221", "播音指导");
put("222", "主任播音员");
put("223", "一级播音员");
put("224", "二级播音员");
put("225", "三级播音员");
put("230", "卫生技术人员(医师)");
put("231", "主任医师");
put("232", "副主任医师");
put("233", "主治医师");
put("234", "医师");
put("235", "医士");
put("240", "卫生技术人员(药剂)");
put("241", "主任药师");
put("242", "副主任药师");
put("243", "主管药师");
put("244", "药师");
put("245", "药士");
put("250", "卫生技术人员(护理)");
put("251", "主任护师");
put("252", "副主任护师");
put("253", "主管护师");
put("254", "护师");
put("255", "护士");
put("260", "卫生技术人员(技师)");
put("261", "主任技师");
put("262", "副主任技师");
put("263", "主管技师");
put("264", "技师");
put("265", "技士");
put("272", "高级工艺美术师");
put("274", "助理工艺美术师");
put("275", "工艺美术员");
put("281", "一级演员");
put("282", "二级演员");
put("284", "四级演员");
put("291", "一级演奏员");
put("292", "二级演奏员");
put("294", "四级演奏员");
put("301", "一级编剧");
put("303", "三级编剧");
put("304", "四级编剧");
put("311", "一级导演");
put("312", "二级导演");
put("314", "四级导演");
put("320", "艺术人员(指挥)");
put("322", "二级指挥");
put("323", "三级指挥");
put("324", "四级指挥");
put("331", "一级作曲");
put("332", "二级作曲");
put("334", "四级作曲");
put("340", "艺术人员(美术)");
put("342", "二级美术师");
put("475", "四级领航员");
put("480", "飞行技术人员(通信)");
put("482", "一级飞行通信员");
put("483", "二级飞行通信员");
put("484", "三级飞行通信员");
put("485", "四级飞行通信员");
put("490", "飞行技术人员(机械)");
put("492", "一级飞行机械员");
put("493", "二级飞行机械员");
put("494", "三级飞行机械员");
put("495", "四级飞行机械员");
put("500", "船舶技术人员(引航)");
put("502", "高级引航员");
put("503", "一、二级引航员");
put("504", "三、四级引航员");
put("610", "高等学校研究员");
put("611", "研究员");
put("612", "副研究员");
put("613", "助理研究员");
put("614", "研究实习员");
put("620", "社会科学研究人员");
put("621", "研究员(社会科学)");
put("622", "副研究员(社会科学)");
put("623", "助理研究员(社会科学)");
put("624", "研究实习员(社会科学)");
put("630", "教育管理研究人员");
put("631", "研究员(教育管理)");
put("632", "副研究员(教育管理)");
put("633", "助理研究员(教育管理)");
put("634", "研究实习员(教育管理)");
put("640", "图书、资料专业人员");
put("641", "研究馆员(图书)");
put("642", "副研究馆员(图书)");
put("643", "馆员(图书)");
put("644", "助理馆员(图书)");
put("645", "管理员(图书)");
put("650", "文博专业人员");
put("651", "研究馆员(文博)");
put("652", "副研究馆员(文博)");
put("653", "馆员(文博)");
put("654", "助理馆员(文博)");
put("655", "管理员(文博)");
put("660", "档案专业人员");
put("661", "研究馆员(档案)");
put("662", "副研究馆员(档案)");
put("663", "馆员(档案)");
put("270", "工艺美术人员");
put("273", "工艺美术师");
put("280", "艺术人员(演员)");
put("283", "三级演员");
put("290", "艺术人员(演奏员)");
put("293", "三级演奏员");
put("350", "艺术人员(舞美设计)");
put("352", "二级舞美设计师");
put("361", "主任舞台技师");
put("364", "舞台技术员");
put("373", "一级教练");
put("380", "海关专业人员");
put("384", "助理关务监督");
put("392", "二级律师");
put("400", "公证员");
put("402", "二级公证员");
put("060", "中小学教师");
put("063", "一级教师");
put("670", "群众文化专业人员");
put("672", "副研究馆员(群众文化)");
put("675", "管理员(群众文化)");
put("682", "高级审计师");
put("692", "副主任法医师");
put("970", "江苏省翻译专业人员");
put("980", "思想政治工作人员");
put("982", "高级政工师");
put("984", "助理政工师");
put("991", "教授(改革)");
put("993", "助理教授(改革)");
put("998", "建筑师");
put("071", "教授级高级实验师");
put("074", "助理实验师");
put("013", "讲师(高校)");
put("083", "工程师");
put("090", "农业技术人员(农艺)");
put("092", "高级农艺师");
put("014", "助教(高校)");
put("101", "农业技术推广研究员(兽医)");
put("105", "兽医技术员");
put("111", "农业技术推广研究员(畜牧)");
put("112", "高级畜牧师");
put("115", "畜牧技术员");
put("121", "教授级高级经济师");
put("020", "中等专业学校教师");
put("131", "教授级高级会计师");
put("140", "统计专业人员");
put("141", "教授级高级统计师");
put("144", "助理统计师");
put("150", "出版专业人员(编审)");
put("160", "出版专业人员(技术编辑)");
put("023", "讲师(中专)");
put("173", "一级校对");
put("343", "三级美术师");
put("344", "美术员");
put("351", "一级舞美设计师");
put("353", "三级舞美设计师");
put("354", "舞美设计员");
put("360", "艺术人员(舞台技术)");
put("362", "主任舞台技师");
put("363", "舞台技师");
put("370", "体育教练");
put("371", "国家级教练");
put("372", "高级教练");
put("374", "二级教练");
put("375", "三级教练");
put("381", "高级关务监督");
put("383", "关务监督");
put("385", "监管员");
put("390", "律师");
put("391", "一级律师");
put("393", "三级律师");
put("394", "四级律师");
put("395", "律师助理");
put("401", "一级公证员");
put("664", "助理馆员(档案)");
put("665", "管理员(档案)");
put("671", "研究馆员(群众文化)");
put("673", "馆员(群众文化)");
put("674", "助理馆员(群众文化)");
put("680", "审计专业人员");
put("681", "教授级高级审计师");
put("683", "审计师");
put("180", "翻译人员");
put("300", "艺术人员(编剧)");
put("302", "二级编剧");
put("310", "艺术人员(导演)");
put("313", "三级导演");
put("321", "一级指挥");
put("330", "艺术人员(作曲)");
put("333", "三级作曲");
put("341", "一级美术师");
put("182", "副译审");
put("0", "");
put("412", "特高级教师(小学)");
put("A410", "幼儿园教师");
put("A413", "高级教师(幼儿园)");
put("A414", "一级教师(幼儿园)");
put("A415", "二级教师(幼儿园)");
put("A416", "三级教师(幼儿园)");
put("684", "助理审计师");
put("685", "审计员");
put("690", "法医专业人员");
put("691", "主任法医师");
put("403", "三级公证员");
put("404", "四级公证员");
put("405", "公证助理员");
put("410", "小学教师");
put("413", "高级教师(小学)");
put("414", "一级教师(小学)");
put("415", "二级教师(小学)");
put("416", "三级教师(小学)");
put("9999", "毓秀青年学者");
put("A010", "高等学校教师(准聘长聘)");
put("A011", "教授(长聘)");
put("A013", "副教授(准聘)");
put("A012", "副教授(长聘)");
put("A014", "助理教授(准聘)");
}};
public static Map<String, String> EDUCATION_MAP = new HashMap<String, String>() {{
put("25", "双学位毕业");
put("10", "研究生教育");
put("20", "大学本科教育");
put("30", "大学专科教育");
put("40", "中等职业教育");
put("60", "普通高级中学教育");
put("70", "初级中学教育");
put("80", "小学教育");
put("90", "其他");
put("11", "博士研究生毕业");
put("12", "博士研究生结业");
put("13", "博士研究生肄业");
put("14", "硕士研究生毕业");
put("15", "硕士研究生结业");
put("16", "硕士研究生肄业");
put("17", "研究生班毕业");
put("18", "研究生班结业");
put("19", "研究生班肄业");
put("21", "大学本科毕业");
put("22", "大学本科结业");
put("23", "大学本科肄业");
put("28", "大学普通班毕业");
put("31", "大学专科毕业");
put("32", "大学专科结业");
put("33", "大学专科肄业");
put("41", "中等专科毕业");
put("42", "中等专科结业");
put("43", "中等专科肄业");
put("44", "职业高中毕业");
put("45", "职业高中结业");
put("46", "职业高中肄业");
put("47", "技工学校毕业");
put("48", "技工学校结业");
put("49", "技工学校肄业");
put("61", "普通高中毕业");
put("62", "普通高中结业");
put("63", "普通高中肄业");
put("71", "初中毕业");
put("73", "初中肄业");
put("81", "小学毕业");
put("83", "小学肄业");
put("91", "党校函授专科");
put("92", "党校函授本科");
put("0", "无学历");
}};
public static Map<String, String> PERSON_TYPE = new HashMap<String, String>() {{
put("A01", "专任教师");
put("A02", "辅导员");
put("A03", "其他专业技术");
put("A04", "管理");
put("A05", "工勤");
put("A06", "其他");
put("B01", "专职科研");
put("B02", "博士后统招");
put("B03", "博士后在职");
put("B04", "博士后专职科研");
put("C01", "预任职员");
put("C02", "校聘人员");
put("D01", "第三方-学校全额出资");
put("D02", "第三方-学校部分出资");
put("D03", "第三方-单位自筹");
put("E01", "离休人员");
put("E02", "退休人员");
put("F01", "非全时-高层次人员");
put("F02", "非全时-专职科研");
put("F03", "非全时-兼职教师");
put("F04", "非全时-访问学者");
put("F05", "非全时-附属医院人员");
put("F06", "非全时-临时人员");
put("F07", "非全时-离校暂时保留");
put("F08", "非全时-临时经费使用");
put("D04", "第三方-单位自管");
}};
public static String getKeyByValue(Map<String, String> map, String value) {
for (Map.Entry<String, String> m : map.entrySet()) {
if (m.getValue().equals(value)) {
return m.getKey();
}
}
return "";
}
}
@@ -0,0 +1,17 @@
package io.v.nutz.zhgh.data.constant;
import cn.afterturn.easypoi.excel.annotation.Excel;
import lombok.Data;
@Data
public class JiangNanUserCode {
@Excel(name = "code")
private String code;
@Excel(name = "name")
private String name;
@Excel(name = "up")
private String up;
}
@@ -0,0 +1,21 @@
package io.v.nutz.zhgh.data.constant;
import io.v.nutz.base.annontation.SelectEnum;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 匹配方式
*
* @author: 1V
* @date: 2021/3/1
* @since 1.0
*/
@Getter
@SelectEnum
@AllArgsConstructor
public enum MatchMethod {
AND("AND(所有条件都要求匹配)"), OR("OR(条件中的任意一个匹配)");
private final String description;
}
@@ -0,0 +1,190 @@
package io.v.nutz.zhgh.data.constant;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import io.v.nutz.base.expression.Exp4;
import io.v.nutz.sys.models.Sys_unit;
import io.v.nutz.zhgh.data.model.UserSource;
import org.nutz.json.Json;
import org.nutz.lang.Lang;
import org.nutz.lang.util.NutMap;
import org.springframework.util.Assert;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 获取源数据配置
* 继承者们自己修改以下代码以达到想要效果
*
* @author 1V
* @date 2021/3/4
* @since 浙江财经
*/
public interface SourceData {
String APP_KEY = "20240919701618366869971844546564530";
String APP_SECRET = "9307335b784fd46be9f67d67ed0240747190ed28";
String APP_TOKEN_URL = "https://dct.zufe.edu.cn/open_api/authentication/get_access_token";
/**
* 获取用户数据的地址
*/
String USER_URL_TOTAL = "https://dct.zufe.edu.cn/open_api/customization/vgxjgqxjzgjbxx/full";
/**
* 获取单位的地址
*/
String UNIT_URL = "https://dct.zufe.edu.cn/open_api/customization/tgxxxyxsdwxx/full";
/**
* 断言是否成功
*
* @param jsonResult 接口返回数据
*/
private static void checkSuccess(NutMap jsonResult) {
Assert.isTrue(jsonResult.getInt("code") == 10000, jsonResult.getString("message"));
}
/**
* 接口中的数据跟SourceUser的对应关系
* <p>
* SourceUser [username,loginname]
* Result [name,code]
* <p>
* 例:{'name':['username'],'code':['loginname']}
*/
Map<String, String[]> USER_FIELD_RELATION = new HashMap() {{
put("ZGH", new String[]{"loginname"});
put("XM", new String[]{"username"});
put("XB", new String[]{"sex"});
put("CSRQ", new String[]{"birthday"});
put("SZDWDM", new String[]{"unitid"});
put("LXRQ", new String[]{"schoolTime"});
put("BZLBMC", new String[]{"personType"});
put("DQZTMC", new String[]{"userState"});
put("XZZW", new String[]{"position"});
put("LTRQ", new String[]{"retireDate"});
}};
/**
* 字段插件
*/
Map<String, Exp4> USER_FIELD_PLUGIN = new HashMap<String, Exp4>() {{
}};
/**
* 获取源用户数据
*
* @return users
*/
static List<UserSource> users() {
List<UserSource> users = new ArrayList<>();
String token = getToken();
int page = 1;
boolean hasRecords = true;
int maxPage;
while (hasRecords) {
String body = HttpUtil.get(USER_URL_TOTAL, new NutMap().addv("access_token", token).addv("page", page).addv("per_page", 1000));
NutMap map = Json.fromJson(NutMap.class, body);
checkSuccess(map);
NutMap result = map.getAs("result", NutMap.class);
maxPage = result.getInt("max_page");
List<NutMap> data = result.getAsList("data", NutMap.class);
for (NutMap row : data) {
Map entity = new HashMap(1000);
row.forEach((k, v) -> {
if (USER_FIELD_RELATION.containsKey(k)) {
Object value = v;
if (USER_FIELD_PLUGIN.containsKey(k)) {
value = USER_FIELD_PLUGIN.get(k).run(v);
}
for (String key : USER_FIELD_RELATION.get(k)) {
entity.put(key, value);
}
}
});
users.add(BeanUtil.mapToBean(entity, UserSource.class, true));
}
page++;
if (page > maxPage) {
hasRecords = false;
}
}
return users;
}
/**
* 单位对应接口字段
*/
Map<String, String[]> UNIT_FIELD_RELATION = new HashMap() {{
put("DWDM", new String[]{"id", "unitcode"});
put("DWMC", new String[]{"name"});
put("LSDWH", new String[]{"parentId"});
}};
/**
* 字段插件
*/
Map<String, Exp4> UNIT_FIELD_PLUGIN = new HashMap<String, Exp4>() {{
}};
/**
* 获取单位
*
* @return units
*/
static List<Sys_unit> units() {
String token = getToken();
List<Sys_unit> units = new ArrayList<>();
int page = 1;
String body = HttpUtil.get(UNIT_URL, new NutMap().addv("DWYXBS", "1").addv("page", page).addv("per_page", 100).addv("access_token", token));
NutMap map = Json.fromJson(NutMap.class, body);
checkSuccess(map);
NutMap result = map.getAs("result", NutMap.class);
List<NutMap> data = result.getAsList("data", NutMap.class);
for (NutMap row : data) {
Map entity = new HashMap(5);
row.forEach((k, v) -> {
if (UNIT_FIELD_RELATION.containsKey(k)) {
Object value = v;
/* if (UNIT_FIELD_PLUGIN.containsKey(k)) {
value = UNIT_FIELD_PLUGIN.get(k).run(v);
}*/
for (String key : UNIT_FIELD_RELATION.get(k)) {
entity.put(key, value);
}
}
});
units.add(BeanUtil.mapToBean(entity, Sys_unit.class, true));
}
return units;
}
static String getToken() {
String body = HttpUtil.get(APP_TOKEN_URL, new NutMap().addv("key", APP_KEY).addv("secret", APP_SECRET));
NutMap map = Json.fromJson(NutMap.class, body);
if (map.getInt("code") == 10000) {
NutMap result = map.getAs("result", NutMap.class);
String accessToken = result.getString("access_token");
return accessToken;
}
return null;
}
}
@@ -0,0 +1,37 @@
package io.v.nutz.zhgh.data.constant;
import io.v.nutz.base.annontation.SelectEnum;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 变更类型
*
* @author: 1V
* @date: 2021/2/2
* @since 1.0
*/
@Getter
@SelectEnum
@AllArgsConstructor
public enum UserChangeType {
//变更类型
UNIT_CHANGE(1, "单位异动"),
NEW(2, "新入职"),
RESIGN(3, "离校"),
// DIE(4, "去世"),
RETIREMENT(5, "离退休"),
// EXPELLED(6, "开除"),
RESTORE(7, "入会"),
WITHDRAWAL(8, "退会"),
// NONE(9, "不变"),
BASIC_CHANGE(10, "基本信息异动"),
WORK(11, "在职"),
NOT_WELFARE_LIST(12, "不在本次发放福利内"),
NEW_WELFARE_LIST(13, "添加会员到本次名单");
private int code;
private String description;
}
@@ -0,0 +1,407 @@
package io.v.nutz.zhgh.data.controller;
import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.annotation.Excel;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import io.v.nutz.base.annontation.ViReturn;
import io.v.nutz.zhgh.data.handle.DataImportPluginHandle;
import io.v.nutz.base.lang.Enum;
import io.v.nutz.base.service.AsyncService;
import io.v.nutz.base.service.ViService;
import io.v.nutz.sys.services.SysRoleService;
import io.v.nutz.sys.services.SysUserRoleService;
import io.v.nutz.sys.services.SysUserService;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.*;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.nutz.dao.Chain;
import org.nutz.dao.Cnd;
import org.nutz.dao.Sqls;
import org.nutz.dao.entity.Record;
import org.nutz.dao.sql.Sql;
import org.nutz.integration.jedis.RedisService;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.json.Json;
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.util.Assert;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 数据导入工具
*
* @author: 1V
* @date: 2021/1/18
* @since 1.0
*/
@IocBean
@Ok("json")
@At("/platform/data/import")
@Slf4j
public class DataImportController {
@At("")
@Ok("beetl:/platform/data/tool/DataImport.html")
@RequiresPermissions("sys.data.import")
public void index() {
}
@Inject
private ViService viService;
@Inject
private SysUserRoleService sysUserRoleService;
@Inject
private SysUserService sysUserService;
@Inject
private SysRoleService sysRoleService;
/**
* 插入/更新前操作
*
* @param PK 主键
* @param field 关键字段
* @param relation 列对应
* @param save true:新增 false:更新
* @param chain chain对象
*/
private void daoBefore(String tableName, Record PK, NutMap[] relation, String field, List<DataImportPluginHandle> pluginHandles, boolean save, Chain chain, NutMap row) {
/*生成主键*/
if (PK == null) {
return;
}
String column_name = PK.getString("column_name");
String column_type = PK.getString("column_type");
Object pk = null;
if (save) {
NutMap map = Arrays.stream(relation).filter(x -> x.getString("column_name").equals(column_name)).findFirst().orElse(null);
if (map == null) {
switch (column_type) {
case "int" -> pk = R.random(1000, 9999);
case "varchar(16)" -> pk = R.UU16();
case "varchar(64)" -> pk = R.UU64();
default -> pk = R.UU32();
}
chain.add(column_name, pk);
} else {
pk = row.get(map.getString("relation"));
}
} else {
Cnd cnd = Cnd.where(field, "=", row.get(field));
Record record = viService.dao().fetch(tableName, cnd);
if (record != null) {
pk = record.getString(column_name);
}
}
Assert.notNull(pk, "未找到行记录");
Map<String, Object> map = Map.of("chain", chain, "pk", pk);
/*插件*/
for (DataImportPluginHandle handle : pluginHandles) {
handle.carry(map);
}
}
/**
* 获取表的PK
*
* @param columns
* @return
*/
private Optional<Record> getPK(List<Record> columns) {
return columns.stream().filter(v -> v.getString("column_key").equals("PRI")).findFirst();
}
@Inject
private AsyncService asyncService;
/**
* 导入数据
*
* @param file xls文件
* @param tableName 表名
* @param relation 列对应
* @param method 导入方式
* @param field 关键字段
* @param plugins 插件
* @return
*/
@At
@ViReturn
@AdaptBy(type = UploadAdaptor.class, args = {"ioc:fileUpload"})
@RequiresPermissions("sys.data.import")
public Object importData(@Param("file") TempFile file, String tableName, NutMap[] relation, Integer method, String field, String[] plugins) throws IOException {
List<Record> columns = getColumns(tableName);
Record PK = getPK(columns).orElse(null);
List<NutMap> dataList = getDataForXls(file, relation);
AtomicInteger totalNum = new AtomicInteger();
AtomicInteger successNum = new AtomicInteger();
List<DataImportPluginHandle> pluginHandles = new ArrayList<>();
for (String plugin : plugins) {
pluginHandles.add(Enum.instance(DataImportPluginHandle.class, plugin));
}
pluginHandles.sort(Comparator.comparing(DataImportPluginHandle::getLocation));
List<Error> errors = new ArrayList<>();
asyncService.exe2(dataList, data -> {
try {
//因为xls里会把工号这种转成整数所以在这里强转一下
data.setv(field, data.getString(field));
Chain chain = Chain.from(data);
if (method == 1) {
Cnd cnd = Cnd.where(field, "=", data.get(field));
Record record = viService.dao().fetch(tableName, cnd);
if (record != null) {
//更新
daoBefore(tableName, PK, relation, field, pluginHandles, false, chain, data);
viService.dao().update(tableName, chain, cnd);
} else {
//新增
daoBefore(tableName, PK, relation, field, pluginHandles, true, chain, data);
viService.dao().insert(tableName, chain);
}
} else if (method == 2) {
//新增
daoBefore(tableName, PK, relation, field, pluginHandles, true, chain, data);
viService.dao().insert(tableName, chain);
} else if (method == 3) {
//更新
daoBefore(tableName, PK, relation, field, pluginHandles, false, chain, data);
viService.dao().update(tableName, chain, Cnd.where(field, "=", data.get(field)));
}
successNum.getAndIncrement();
} catch (Exception e) {
errors.add(new Error(Json.toJson(data)));
} finally {
totalNum.getAndIncrement();
}
});
String cacheKey = "";
if (!errors.isEmpty()) {
cacheKey = R.UU32();
redisService.setex(cacheKey, 60 * 60 * 5, Json.toJson(errors));
}
sysUserService.clearCache();
sysRoleService.clearCache();
return Map.of("total", totalNum.get(), "success", successNum.get(), "cacheKey", cacheKey);
}
/**
* 导出错误信息
*
* @param response
* @param cacheKey
* @throws IOException
*/
@At
@RequiresPermissions("sys.data.import")
public void exportErrors(HttpServletResponse response, String cacheKey) throws IOException {
String json = redisService.get(cacheKey);
List<Error> errors = Json.fromJsonAsList(Error.class, json);
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition", "attachment;filename=" + new String(("records.xls").getBytes("utf-8"), "ISO8859-1"));
Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams(), Error.class, errors);
workbook.write(response.getOutputStream());
}
@Inject
private RedisService redisService;
@Data
@AllArgsConstructor
@NoArgsConstructor
public static class Error {
@Excel(name = "行数据", width = 100)
private String row;
}
/**
* 从excel中获取数据
*
* @param file
* @param relation
* @return
* @throws IOException
*/
private List<NutMap> getDataForXls(TempFile file, NutMap[] relation) throws IOException {
List<NutMap> result = new ArrayList<>();
Map<Integer, String> namesMap = new HashMap<>();
//第一个sheet
Sheet sheet = WorkbookFactory.create(file.getInputStream()).getSheetAt(0);
//表头
Row namesRow = sheet.getRow(0);
//列数
int columnNum = namesRow.getPhysicalNumberOfCells();
for (int i = 0; i < columnNum; i++) {
String name = namesRow.getCell(i).getStringCellValue();
int finalI = i;
Arrays.stream(relation).filter(v -> v.getString("relation").equals(name)).findFirst().ifPresent((v) -> {
namesMap.put(finalI, v.getString("column_name"));
});
}
//物理行数
int rowNum = sheet.getPhysicalNumberOfRows();
for (int i = 1; i < rowNum; i++) {
NutMap map = NutMap.NEW();
Row row = sheet.getRow(i);
for (int j = 0; j < columnNum; j++) {
map.setv(namesMap.get(j), getCellValue(row.getCell(j)));
}
if (map.size() > 0) {
result.add(map);
}
}
return result;
}
static DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
private static Object getCellValue(Cell cell) {
if (cell == null) {
return null;
}
CellType cellType = cell.getCellType();
Object cellValue = null;
if (cellType == CellType._NONE) {
} else if (cellType == CellType.NUMERIC) {
// 数值型
if (DateUtil.isCellDateFormatted(cell)) {
// 日期类型
Date d = cell.getDateCellValue();
cellValue = dateTimeFormatter.format(LocalDateTime.ofInstant(d.toInstant(), ZoneId.systemDefault()));
} else {
double numericCellValue = cell.getNumericCellValue();
BigDecimal bdVal = new BigDecimal(numericCellValue);
if ((bdVal + ".0").equals(Double.toString(numericCellValue))) {
// 整型
cellValue = bdVal;
} else if (String.valueOf(numericCellValue).contains("E10")) {
// 科学记数法
cellValue = new BigDecimal(numericCellValue).toPlainString();
} else {
// 浮点型
cellValue = numericCellValue;
}
}
} else if (cellType == CellType.STRING) {
// 字符串型
cellValue = cell.getStringCellValue();
} else if (cellType == CellType.FORMULA) {
// 公式型
} else if (cellType == CellType.BLANK) {
// 空值
} else if (cellType == CellType.BOOLEAN) {
// 布尔型
cellValue = cell.getBooleanCellValue();
} else if (cellType == CellType.ERROR) {
// 错误
cellValue = cell.getErrorCellValue();
}
log.info("cellType={}, cellValue={}", cellType.name(), cellValue);
return cellValue;
}
/**
* @return 所有表名
*/
@At
@ViReturn
@RequiresPermissions("sys.data.import")
public Object tableNames() {
Sql sql = Sqls.create("""
SELECT
table_name,table_rows,table_comment
FROM
information_schema.TABLES
WHERE
table_schema =(SELECT DATABASE())
ORDER BY table_name
""");
return viService.list(sql);
}
/**
* @param tableName 表名
* @return 一张表的所有字段
*/
@At
@ViReturn
@RequiresPermissions("sys.data.import")
public Object columns(String tableName) {
return getColumns(tableName);
}
private List<Record> getColumns(String tableName) {
Sql sql = Sqls.create("""
SELECT
column_name,is_nullable,column_type,column_key,column_comment
FROM
information_schema.COLUMNS
WHERE
table_name = @tableName
AND table_schema = (SELECT DATABASE())
ORDER BY ordinal_position
""").setParam("tableName", tableName);
return viService.list(sql);
}
}
@@ -0,0 +1,30 @@
package io.v.nutz.zhgh.data.controller;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
/**
* 更新人员设置
*/
@At("/platform/data/part/user")
@Ok("json:full")
@IocBean
public class PartUserController {
@At("/index")
@Ok("beetl:/platform/data/part/UserPart.html")
@RequiresPermissions(value = {"data.part.user","data.part.view"},logical = Logical.OR)
public void index() {
}
@At("/view")
@Ok("beetl:/platform/data/part/UserView.html")
@RequiresPermissions(value = {"data.part.user","data.part.view"},logical = Logical.OR)
public void view() {
}
}
@@ -0,0 +1,121 @@
package io.v.nutz.zhgh.data.controller;
import io.v.nutz.base.annontation.ViReturn;
import io.v.nutz.base.dao.CndPlus;
import io.v.nutz.zhgh.data.service.SourceUserService;
import io.v.nutz.base.query.PageForm;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.nutz.dao.Cnd;
import org.nutz.dao.Sqls;
import org.nutz.dao.sql.Sql;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
import org.nutz.mvc.annotation.Param;
import org.springframework.util.StringUtils;
/**
* 源用户数据
*
* @author: 1V
* @date: 2021/2/1
* @since 1.0
*/
@At("/platform/data/user")
@Ok("json:full")
@IocBean
public class SourceUserController {
@At("")
@Ok("beetl:/platform/data/user/SourceUser.html")
@RequiresPermissions("data.user")
public void index() {
}
@Inject
private SourceUserService sourceUserService;
@At
@ViReturn
@RequiresPermissions("data.user")
public Object pageData(PageForm pageForm,
@Param(value = "unitId", required = false) String unitId,
@Param(value = "personType", required = false) String personType,
@Param(value = "userState", required = false) String userState,
@Param(value = "importDate", required = false) String importDate) {
Sql sql = Sqls.create("""
SELECT
u.pullTime,
date_format(u.pullTime,'%Y-%m-%d') importDate,
u.id,
u.unitid,
u.loginname,
u.username,
u.sex,
u.idcard,
u.birthday,
u.mobile,
u.personType,
u.userState,
un.`name` unitname,
un.unitcode
FROM
`user_source` u
LEFT JOIN sys_unit un ON u.unitid = un.id
$condition
""");
pageForm.defaultSortDesc("pullTime");
CndPlus cnd = CndPlus.create();
cnd.and(pageForm);
cnd.andEx("unitid", "=", unitId);
cnd.andEx("personType", "=", personType);
cnd.andEx("userState", "=", userState);
if(!StringUtils.isEmpty(importDate)){
cnd.and("DATE(u.pullTime)", "=", importDate);
}
cnd.desc("u.pullTime");
sql.setCondition(cnd);
return sourceUserService.list(pageForm, sql);
}
/**
* 数据中心拉取数据
*
* @return
*/
@At
@ViReturn
@RequiresPermissions("data.user")
public Object pull(@Param(value = "isIncrement",required = false) Boolean isIncrement) {
sourceUserService.pullSourceData(isIncrement);
return null;
}
@At
@ViReturn
@RequiresPermissions("data.user")
public Object delete(String[] ids) {
sourceUserService.clear(Cnd.where("id", "in", ids));
return null;
}
@At
@ViReturn
@RequiresPermissions("data.user")
public Object deleteUser(@Param("sourceTime") String[] sourceTime) {
sourceUserService.clear(Cnd.where("pullTime", "in", sourceTime));
return null;
}
}
@@ -0,0 +1,217 @@
package io.v.nutz.zhgh.data.controller;
import cn.hutool.core.bean.BeanUtil;
import cn.wizzer.framework.base.Result;
import io.v.nutz.base.annontation.ViReturn;
import io.v.nutz.base.dao.CndPlus;
import io.v.nutz.base.query.PageForm;
import io.v.nutz.base.service.AsyncService;
import io.v.nutz.base.service.ViService;
import io.v.nutz.sys.models.Sys_unit;
import io.v.nutz.sys.services.SysDqService;
import io.v.nutz.sys.services.SysGxService;
import io.v.nutz.sys.services.SysUnitClassService;
import io.v.nutz.zhgh.data.constant.SourceData;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.nutz.dao.Chain;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.log.Log;
import org.nutz.log.Logs;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@At("/platform/data/unit")
@Ok("json:full")
@IocBean
public class UpdateUnitController {
private static final Log log = Logs.get();
@Inject("Sys_unit")
private ViService<Sys_unit> sysUnitService;
@Inject
private SysUnitClassService sysUnitClassService;
@Inject
private SysDqService sysDqService;
@Inject
private SysGxService sysGxService;
@Inject
private Dao dao;
@At("")
@Ok("beetl:/platform/data/unit/UpdateUnit.html")
@RequiresPermissions("data.user.update")
public void index() {
}
/**
* 单位数据更新
*
* @return {@link Object}
*/
@At
@ViReturn
@RequiresPermissions("sys.data.unit")
public Object dataUpdate() {
List<Sys_unit> sys_units = sysUnitService.query();
List<String> list = sys_units.stream().map(Sys_unit::getId).collect(Collectors.toList());
// 从源数据中心拉取所有的单位
List<Sys_unit> units = SourceData.units();
for (Sys_unit unit : units) {
if (list.contains(unit.getId())) {
sysUnitService.updateIgnoreNull(unit);
} else {
Map<String, Object> beanMap = BeanUtil.beanToMap(unit);
String unitcode = beanMap.get("unitcode").toString();
if (unitcode.length() == 6) {
beanMap.put("unitlevel", 2);
beanMap.put("parentId", 1);
}
if (beanMap.get("id").equals("100")) {
beanMap.put("unitlevel", 1);
beanMap.put("id", 1);
beanMap.put("unitcode", 1);
}
beanMap.remove("child");
sysUnitService.insert("sys_unit", Chain.from(beanMap));
}
}
sys_units = sysUnitService.query();
sys_units.forEach(v -> {
if (sysUnitService.count(Cnd.where("parentId", "=", v.getId())) > 0) { //查询此单位是否有父级单位
v.setHasChildren(true); //设置子级菜单
sysUnitService.update(v);
}
});
return null;
}
@At
@ViReturn
@RequiresPermissions("data.user.update")
public Object pageData(String parentId, PageForm pageForm) {
CndPlus cnd = CndPlus.create();
cnd.andEx("parentId", "=", parentId);
return sysUnitService.list(pageForm, cnd);
}
@At
@ViReturn
@RequiresPermissions("data.user.update")
public Object findOne(String id) {
return sysUnitService.fetch(id);
}
@At
@ViReturn
@RequiresPermissions("data.user.update")
public Object doAdd(Sys_unit sys_unit) {
if (sysUnitService.count(Cnd.where("unitcode", "=", sys_unit.getUnitcode())) > 0) {
return Result.error("单位代码已存在");
}
sysUnitService.update(Chain.make("hasChildren", true), Cnd.where("id", "=", sys_unit.getParentId()));
sysUnitService.insert(sys_unit);
return null;
}
@At
@ViReturn
@RequiresPermissions("data.user.update")
public Object doEdit(Sys_unit sys_unit) {
if (sysUnitService.count(Cnd.where("unitcode", "=", sys_unit.getUnitcode()).and("id", "!=", sys_unit.getId())) > 0) {
return Result.error("单位代码已存在");
}
sysUnitService.update(sys_unit);
return null;
}
@At
@ViReturn
@RequiresPermissions("data.user.update")
public Object doDelete(String id) {
Sys_unit unit = sysUnitService.fetch(id);
int count = sysUnitService.count(Cnd.where("parentId", "=", unit.getParentId()).and("id", "!=", id));
sysUnitService.update(Chain.make("hasChildren", count > 0), Cnd.where("id", "=", unit.getParentId()));
delete(id);
return null;
}
private void delete(String id) {
Cnd cnd = Cnd.where("parentId", "=", id);
List<Sys_unit> units = sysUnitService.query(cnd);
for (Sys_unit unit : units) {
delete(unit.getId());
}
sysUnitService.clear(cnd);
sysUnitService.delete(id);
}
/**
* 获取树形数据
*
* @return
*/
@At
@RequiresPermissions("data.user.update")
public Object getUnitTreeData() {
try {
List list = new ArrayList();
Sys_unit school = sysUnitService.fetch("1");
school.setChild(child(school.getId()));
list.add(school);
return Result.success().addData(list);
} catch (Exception e) {
e.printStackTrace();
return Result.error("获取单位信息失败");
}
}
@Inject
private AsyncService asyncService;
private List<Sys_unit> child(String parentId) {
List<Sys_unit> units = sysUnitService.query(Cnd.where("parentId", "=", parentId));
units.forEach(unit -> {
unit.setChild(child(unit.getId()));
});
return units;
}
@At
@Ok("json")
@RequiresPermissions("data.user.update")
public Object getUnit2() {
try {
return Result.success().addData(sysUnitService.query(Cnd.where("unitlevel", "=", 2).asc("location")));
} catch (Exception e) {
return Result.error();
}
}
}
@@ -0,0 +1,226 @@
package io.v.nutz.zhgh.data.controller;
import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity;
import io.v.nutz.base.annontation.ViReturn;
import io.v.nutz.base.dao.CndPlus;
import io.v.nutz.base.utils.ViResource;
import io.v.nutz.zhgh.data.constant.UserChangeType;
import io.v.nutz.zhgh.data.model.UserHistory;
import io.v.nutz.zhgh.data.service.HistoryUserService;
import io.v.nutz.zhgh.data.service.SourceUserService;
import io.v.nutz.base.query.PageForm;
import io.v.nutz.base.utils.ViTool;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.nutz.dao.Cnd;
import org.nutz.dao.Sqls;
import org.nutz.dao.sql.Sql;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Strings;
import org.nutz.lang.util.NutMap;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
import org.nutz.mvc.annotation.Param;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
/**
* 更新用户数据
*
* @author: 1V
* @date: 2021/2/2
* @since 1.0
*/
@At("/platform/data/user/update")
@Ok("json:full")
@IocBean
public class UpdateUserController {
@At("")
@Ok("beetl:/platform/data/user/UpdateUser.html")
@RequiresPermissions("data.user.update")
public void index() {
}
@Inject
private HistoryUserService historyUserService;
@Inject
private SourceUserService sourceUserService;
@At
@ViReturn
@RequiresPermissions("data.user.update")
public Object pageData(PageForm pageForm,
@Param(value = "unitId", required = false) String unitId,
@Param(value = "personType", required = false) String personType,
@Param(value = "userState", required = false) String userState,
@Param(value = "changeDate", required = false) String changeDate,
@Param(value = "changeType", required = false) String changeType) {
Sql sql = Sqls.create("""
SELECT
u.*,his.id as hisId,his.changeType,his.changeTypes,his.changeTime,IF(his.id is null,FALSE,TRUE) hasHis,TRUE as flag
FROM
`user` u
LEFT JOIN user_history_latest his ON his.loginname = u.loginname
$condition
""");
pageForm.defaultSortDesc("his.changeTime");
CndPlus cnd = CndPlus.create();
cnd.and(pageForm);
cnd.andEx("u.unitid", "=", unitId);
cnd.andEx("u.personType", "=", personType);
cnd.andEx("u.userState", "=", userState);
cnd.andEx("Date(his.changeTime)", "=", changeDate);
cnd.andEx("his.changeType", "=", changeType);
sql.setCondition(cnd);
return historyUserService.list(pageForm, sql);
}
/**
* 获取最近几次的pull时间
* 用于更新用户表
*
* @return
*/
@At
@ViReturn
@RequiresPermissions("data.user.update")
public Object latelyUpdateTimes() {
Sql sql = Sqls.create("""
SELECT
pullTime pullTime,
count( 1 ) num
FROM
`user_source`
WHERE
pullTime IS NOT NULL
GROUP BY
pullTime
ORDER BY
pullTime DESC
LIMIT 5
""");
return historyUserService.listMap(sql);
}
@At
@ViReturn
@RequiresPermissions("data.user.update")
public Object historyUsers(String loginname) {
return historyUserService.historyUsers(loginname);
}
@At
@ViReturn
@RequiresPermissions("data.user.update")
public Object update(String sourceTime, String sourceType,
@Param(value = "columnNames", required = false) String[] columnNames,
@Param(value = "isUpSet", required = false) String isUpSet,
@Param(value = "partGroupId",required = false)String partGroupId,
@Param(value = "isInvert",required = false) boolean isInvert) {
sourceUserService.updateSysUser(sourceTime, sourceType, columnNames, isUpSet,partGroupId,isInvert);
return null;
}
@At
@ViReturn
public Object clearHistory() {
historyUserService.clear();
return null;
}
@At
@Ok("void")
public void exportChangePeo(@Param(value = "searchName",required = false)String searchName,
@Param(value = "searchKeyword",required = false)String searchKeyword,
@Param(value = "unitId", required = false) String unitId,
@Param(value = "personType", required = false) String personType,
@Param(value = "userState", required = false) String userState,
@Param(value = "changeDate", required = false) String changeDate,
@Param(value = "changeType", required = false) String changeType,
HttpServletResponse response) {
Sql sql = Sqls.create("""
SELECT
u.*,his.changeType,his.changeTime,IF(his.id is null,FALSE,TRUE) hasHis,TRUE as flag
FROM
`user` u
LEFT JOIN user_history_latest his ON his.loginname = u.loginname
$condition
""");
CndPlus cnd = CndPlus.create();
if (Strings.isNotBlank(searchName) && Strings.isNotBlank(searchKeyword)) {
cnd.and(Cnd.likeEX(searchName, searchKeyword));
}
cnd.andEX("u.unitid", "=", unitId);
cnd.andEX("u.personType", "=", personType);
cnd.andEX("u.userState", "=", userState);
cnd.andEX("Date(his.changeTime)", "=", changeDate);
cnd.andEX("his.changeType", "=", changeType);
cnd.and(Cnd.exps("his.changeType", "is not", null));
// cnd.and(Cnd.exps("his.changeType", "is not", null).or("his.changeType", "!=", UserChangeType.NONE.getCode()));
cnd.desc("his.changeTime");
sql.setCondition(cnd);
List<NutMap> userChangeList = historyUserService.listMap(sql);
List<NutMap> list = ViResource.selectEnums.get("UserChangeType");
userChangeList.forEach(v->{
NutMap userHis = historyUserService.historyUsers(v.getString("loginname")).stream().findFirst().orElse(null);
if (userHis != null){
if (!v.getString("unitname").equals(userHis.getString("unitname"))){
v.setv("newUnit",userHis.getString("unitname"));
}
v.setv("changeDate",userHis.getString("changeDate"));
}
List<NutMap> collect = list.stream().filter(i -> i.getString("code").equals(v.getString("changeType"))).collect(Collectors.toList());
NutMap nutMap = collect.stream().findFirst().orElse(null);
if (nutMap != null){
v.setv("changeType",nutMap.getString("description"));
}
});
List<ExcelExportEntity> entities = new ArrayList<>();
entities.add(new ExcelExportEntity("工号","loginname",20));
entities.add(new ExcelExportEntity("姓名","username",20));
entities.add(new ExcelExportEntity("联系电话","mobile",20));
entities.add(new ExcelExportEntity("身份证","idcard",50));
entities.add(new ExcelExportEntity("在职状态","userState",20));
entities.add(new ExcelExportEntity("异动类型","changeType",20));
entities.add(new ExcelExportEntity("单位","unitname",50));
entities.add(new ExcelExportEntity("新单位","newUnit",50));
entities.add(new ExcelExportEntity("异动时间","changeDate",20));
try {
ViTool.excelResponse(response, "人员异动名单.xls");
Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams(), entities, userChangeList);
workbook.write(response.getOutputStream());
} catch (Exception e) {
e.printStackTrace();
}
}
public Object findChangeInfo(String loginName){
List<UserHistory> list = historyUserService.query(Cnd.where("loginname", "=", loginName));
return null;
}
}
@@ -0,0 +1,60 @@
package io.v.nutz.zhgh.data.handle;
import io.v.nutz.base.annontation.SelectEnum;
import io.v.nutz.zhgh.member.UserMode;
import lombok.Getter;
import org.apache.shiro.crypto.hash.Sha256Hash;
import org.apache.shiro.util.ByteSource;
import org.nutz.dao.Chain;
import org.nutz.lang.random.R;
import java.util.Map;
/**
* 数据导入插件
*
* @author: 1V
* @date: 2021/2/1
* @since 1.0
*/
@Getter
@SelectEnum
public enum DataImportPluginHandle {
USER_INIT(1, "用户数据初始化") {
@Override
public void carry(Map map) {
Chain chain = (Chain) map.get("chain");
Object pk = map.get("pk");
String salt = R.UU32();
chain.add("salt", salt);
chain.add("password", new Sha256Hash("dd3s@#2022", ByteSource.Util.bytes(salt), 1024).toHex());
chain.add("loginPjax", true);
chain.add("menuTheme", "left");
UserMode.addPublicRole(pk.toString());
}
},
MEMBER_INIT(2, "将用户设置为会员") {
@Override
public void carry(Map map) {
Chain chain = (Chain) map.get("chain");
chain.add("member", 1);
UserMode.addMemberRole(map.get("pk").toString());
}
};
/**
* 排序用
*/
private int location;
private String description;
DataImportPluginHandle(int location, String description) {
this.location = location;
this.description = description;
}
public abstract void carry(Map map);
}
@@ -0,0 +1,48 @@
package io.v.nutz.zhgh.data.model;
import io.v.nutz.zhgh.data.constant.ConditionalOperational;
import lombok.Data;
import lombok.experimental.Accessors;
import org.nutz.dao.entity.annotation.*;
import org.nutz.dao.interceptor.annotation.PrevInsert;
/**
* 匹配条件
*
* @author: 1V
* @date: 2021/3/1
* @since 1.0
*/
@Data
@Accessors(chain = true)
@Table("match_condition")
public class MatchCondition {
@Name
@Column
@Comment("ID")
@PrevInsert(uu32 = true)
@ColDefine(type = ColType.VARCHAR, width = 32)
private String id;
@Column
@Comment("结构id")
@ColDefine(type = ColType.VARCHAR, width = 32)
private String structureId;
@Column
@Comment("字段")
@ColDefine(type = ColType.VARCHAR, width = 50)
private String field;
@Column
@Comment("操作")
@ColDefine(type = ColType.VARCHAR, width = 50)
private ConditionalOperational operational;
@Column
@Comment("")
@ColDefine(type = ColType.VARCHAR, width = 255)
private String value;
}
@@ -0,0 +1,58 @@
package io.v.nutz.zhgh.data.model;
import io.v.nutz.zhgh.data.constant.MatchMethod;
import lombok.Data;
import lombok.experimental.Accessors;
import org.nutz.dao.Cnd;
import org.nutz.dao.entity.annotation.*;
import org.nutz.dao.interceptor.annotation.PrevInsert;
import org.nutz.dao.util.cri.Exps;
import org.nutz.dao.util.cri.SqlExpression;
import java.util.List;
/**
* 条件构造
*
* @author: 1V
* @date: 2021/3/1
* @since 1.0
*/
@Data
@Accessors(chain = true)
@Table("match_condition_structure")
public class MatchConditionStructure {
@Name
@Column
@Comment("ID")
@PrevInsert(uu32 = true)
@ColDefine(type = ColType.VARCHAR, width = 32)
private String id;
@Column
@Comment("匹配方法")
@ColDefine(type = ColType.VARCHAR, width = 10)
private MatchMethod method;
@Many(field = "structureId")
private List<MatchCondition> conditions;
public void join(Cnd cnd) {
if (conditions == null) {
return;
}
for (MatchCondition condition : conditions) {
SqlExpression sqlExpression = Exps.create(condition.getField(), condition.getOperational().getValue(), condition.getValue());
switch (method) {
case AND -> {
cnd.and(sqlExpression);
}
case OR -> {
cnd.or(sqlExpression);
}
}
}
}
}
@@ -0,0 +1,74 @@
package io.v.nutz.zhgh.data.model;
import io.v.nutz.zhgh.data.constant.UserChangeType;
import io.v.nutz.sys.models.Sys_user;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import org.nutz.dao.entity.annotation.*;
import org.nutz.dao.interceptor.annotation.PrevInsert;
import java.util.Date;
import java.util.List;
/**
* 用户历史信息表
*
* @author: 1V
* @date: 2021/2/1
* @since 1.0
*/
@Table("user_history")
@TableIndexes({
@Index(name = "INDEX_HISTORY_USER_LOGINNAMAE", fields = {"loginname"}, unique = false),
@Index(name = "INDEX_HISTORY_USER_UNIT", fields = {"unitid"}, unique = false),
@Index(name = "INDEX_HISTORY_USER_UNION", fields = {"unionid"}, unique = false),
})
@Data
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = true)
public class UserHistory extends Sys_user {
@Name
@Column
@Comment("ID")
@PrevInsert(uu32 = true)
@ColDefine(type = ColType.VARCHAR, width = 32)
private String id;
@Column
@Comment("更新时间")
private Date changeTime;
/**
* @see UserChangeType
*/
@Column
@Comment("变更类型")
private int changeType;
@Column
@Comment("变更类型(多种)")
private List<Integer> changeTypes;
@Column
@Comment("变更来源")
private Integer changeOrigin;
@Column
@Comment("变更人")
private String changeOperator;
@Column
@ColDefine(type = ColType.VARCHAR, width = 100)
@Comment("变更原因")
private String changeReason;
@Column
@Comment("会员变更表记录id")
private String memberChangeRecordId;
@Column
@ColDefine(type = ColType.VARCHAR, width = 32)
@Comment("上一次历史记录id")
private String lastHistoryId;
}
@@ -0,0 +1,31 @@
package io.v.nutz.zhgh.data.model;
import io.v.nutz.sys.models.Sys_user;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import org.nutz.dao.entity.annotation.*;
import java.util.Date;
/**
* 源用户数据
*
* @author: 1V
* @date: 2021/2/1
* @since 1.0
*/
@Table("user_source")
@TableIndexes({
@Index(name = "INDEX_USER_SOURCE_LOGINNAMAE", fields = {"loginname"}, unique = false),
@Index(name = "INDEX_USER_SOURCE_UNIT", fields = {"unitid"}, unique = false),
@Index(name = "INDEX_USER_SOURCE_UNION", fields = {"unionid"}, unique = false),
})
@Data
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = true)
public class UserSource extends Sys_user {
@Column
@Comment("导入时间")
private Date pullTime;
}
@@ -0,0 +1,24 @@
package io.v.nutz.zhgh.data.service;
import io.v.nutz.zhgh.data.model.UserHistory;
import io.v.nutz.base.service.ViService;
import org.nutz.lang.util.NutMap;
import java.util.List;
/**
* Todo
*
* @author: 1V
* @date: 2021/2/1
* @since 1.0
*/
public interface HistoryUserService extends ViService<UserHistory> {
/**
* 获取该工号的所有历史上记录
*
* @param loginname
* @return
*/
List<NutMap> historyUsers(String loginname);
}
@@ -0,0 +1,21 @@
package io.v.nutz.zhgh.data.service;
import io.v.nutz.zhgh.data.model.MatchConditionStructure;
import io.v.nutz.base.service.ViService;
/**
* Todo
*
* @author: 1V
* @date: 2021/2/1
* @since 1.0
*/
public interface MatchConditionStructureService extends ViService<MatchConditionStructure> {
/**
* 保存
* @param conditionStructure
* @return
*/
MatchConditionStructure save(MatchConditionStructure conditionStructure);
}
@@ -0,0 +1,32 @@
package io.v.nutz.zhgh.data.service;
import io.v.nutz.zhgh.data.model.UserSource;
import io.v.nutz.base.service.ViService;
/**
* Todo
*
* @author: 1V
* @date: 2021/2/1
* @since 1.0
*/
public interface SourceUserService extends ViService<UserSource> {
/**
* 从数据中心获取数据
*
* @return 源数据
*/
void pullSourceData(Boolean isIncrement);
/**
* 更新系统用户
*
* @param pullTime
*/
void updateSysUser(String pullTime, String sourceType,String[] columnNames,String isUpSet,String partGroupId,boolean isInvert);
/**
* 每日定时更新
*/
void dailyScheduledUpdates();
}
@@ -0,0 +1,88 @@
package io.v.nutz.zhgh.data.service.impl;
import io.v.nutz.zhgh.data.model.UserHistory;
import io.v.nutz.zhgh.data.service.HistoryUserService;
import io.v.nutz.base.service.AsyncService;
import io.v.nutz.base.service.impl.ViServiceImpl;
import org.nutz.dao.Dao;
import org.nutz.dao.Sqls;
import org.nutz.dao.sql.Sql;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.util.NutMap;
import org.nutz.plugins.wkcache.annotation.CacheDefaults;
import java.util.List;
/**
* @author 1V
*/
@IocBean(args = {"refer:dao"})
@CacheDefaults(cacheName = "user_history")
public class HistoryUserServiceImpl extends ViServiceImpl<UserHistory> implements HistoryUserService {
public HistoryUserServiceImpl(Dao dao) {
super(dao);
}
@Inject
private AsyncService asyncService;
@Override
public List<NutMap> historyUsers(String loginname) {
Sql sql = Sqls.create("""
SELECT
u.changeTime,
u.changeType,
date_format( u.changeTime, '%Y-%m-%d' ) changeDate,
`u`.`id` AS `id`,
`u`.`loginname` AS `loginname`,
`u`.`username` AS `username`,
`u`.`avatar` AS `avatar`,
`u`.`email` AS `email`,
`u`.`mobile` AS `mobile`,
`u`.`birthday` AS `birthday`,
`u`.`unitid` AS `unitid`,
`u`.`sex` AS `sex`,
`u`.`idcard` AS `idcard`,
`u`.`hobby` AS `hobby`,
`u`.`qqnum` AS `qqnum`,
`u`.`bank_number` AS `bankNumber`,
`u`.`member` AS `member`,
`u`.`welfareMember` AS `welfareMember`,
`u`.`birthPlace` AS `birthPlace`,
`u`.`marriage` AS `marriage`,
`u`.`preparedBy` AS `preparedBy`,
`u`.`education` AS `education`,
`u`.`hometown` AS `hometown`,
`u`.`wage` AS `wage`,
`u`.`nation` AS `nation`,
`u`.`political` AS `political`,
`u`.`position` AS `position`,
`u`.`jobTitle` AS `jobTitle`,
`u`.`userState` AS `userState`,
`u`.`family` AS `family`,
`u`.`vita` AS `vita`,
`u`.`personType` AS `personType`,
`u`.`memberOrigin` AS `memberOrigin`,
`unit`.`name` AS `unitname`,
`unit`.`unitcode` AS `unitcode`,
`unit`.`unionid` AS `unionid`,
`un`.`unionname` AS `unionname`,
`un`.`unioncode` AS `unioncode`,
`u`.`dqid` AS `campusId`,
`campus`.`dq_name` AS `campusName`\s
FROM
`user_history` `u`
LEFT JOIN `sys_unit` `unit` ON `u`.`unitid` = `unit`.`id`
LEFT JOIN `sys_union` `un` ON `unit`.`unionid` = `un`.`id`
LEFT JOIN `sys_dq` `campus` ON `campus`.`dq_id` = `u`.`dqid`
WHERE
u.loginname = @loginname\s
ORDER BY
u.changeTime DESC
""").setParam("loginname", loginname);
return listMap(sql);
}
}
@@ -0,0 +1,51 @@
package io.v.nutz.zhgh.data.service.impl;
import io.v.nutz.zhgh.data.model.MatchCondition;
import io.v.nutz.zhgh.data.model.MatchConditionStructure;
import io.v.nutz.zhgh.data.service.MatchConditionStructureService;
import io.v.nutz.base.service.impl.ViServiceImpl;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Strings;
import org.nutz.plugins.wkcache.annotation.CacheDefaults;
import org.springframework.util.Assert;
import java.util.List;
import java.util.stream.Collectors;
/**
* @author 1V
*/
@IocBean(args = {"refer:dao"})
@CacheDefaults(cacheName = "match_condition_structure")
public class MatchConditionStructureServiceImpl extends ViServiceImpl<MatchConditionStructure> implements MatchConditionStructureService {
public MatchConditionStructureServiceImpl(Dao dao) {
super(dao);
}
@Override
public MatchConditionStructure save(MatchConditionStructure conditionStructure) {
if (Strings.isNotBlank(conditionStructure.getId())) {
Assert.notNull(conditionStructure.getConditions(), "conditions is empty");
List<String> ids = conditionStructure.getConditions().stream().map(MatchCondition::getId).collect(Collectors.toList());
dao().clear(MatchCondition.class, Cnd.where("structureId", "=", conditionStructure.getId()).and("id", "not in", ids.toArray(new String[ids.size()])));
MatchConditionStructure finalConditionStructure = conditionStructure;
List<MatchCondition> conditionList = conditionStructure.getConditions().stream().filter(v -> {
v.setStructureId(finalConditionStructure.getId());
return Strings.isBlank(v.getId());
}).collect(Collectors.toList());
dao().insert(conditionList);
conditionStructure = updateWith(conditionStructure, "conditions");
} else {
Assert.notNull(conditionStructure.getConditions(), "conditions is empty");
conditionStructure = insertWith(conditionStructure, "conditions");
}
return conditionStructure;
}
}
@@ -0,0 +1,358 @@
package io.v.nutz.zhgh.data.service.impl;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import io.v.nutz.base.utils.Roles;
import io.v.nutz.sys.models.Sys_user_role;
import io.v.nutz.sys.services.SysUserRoleService;
import io.v.nutz.web.commons.utils.ShiroUtil;
import io.v.nutz.zhgh.data.constant.SourceData;
import io.v.nutz.zhgh.data.constant.UserChangeType;
import io.v.nutz.zhgh.data.model.UserHistory;
import io.v.nutz.zhgh.data.model.UserSource;
import io.v.nutz.zhgh.data.service.HistoryUserService;
import io.v.nutz.zhgh.data.service.SourceUserService;
import io.v.nutz.base.lang.Enum;
import io.v.nutz.zhgh.member.UserMode;
import io.v.nutz.base.service.AsyncService;
import io.v.nutz.base.service.impl.ViServiceImpl;
import io.v.nutz.sys.models.Sys_user;
import io.v.nutz.sys.services.SysRoleService;
import io.v.nutz.sys.services.SysUserService;
import io.v.nutz.web.commons.controller.userpartupdate.models.UserPartUp;
import io.v.nutz.web.commons.controller.userpartupdate.service.UserPatUpService;
import io.v.nutz.zhgh.member.constant.MemberChangeOrigin;
import lombok.extern.slf4j.Slf4j;
import org.nutz.aop.interceptor.ioc.TransAop;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.dao.FieldFilter;
import org.nutz.dao.Sqls;
import org.nutz.dao.entity.Record;
import org.nutz.dao.sql.Sql;
import org.nutz.dao.util.Daos;
import org.nutz.ioc.aop.Aop;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Lang;
import org.nutz.lang.Strings;
import org.nutz.lang.random.R;
import org.nutz.lang.util.NutMap;
import org.nutz.plugins.wkcache.annotation.CacheDefaults;
import org.springframework.beans.BeanUtils;
import org.springframework.util.StringUtils;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
/**
* @author 1V
*/
@IocBean(args = {"refer:dao"})
@CacheDefaults(cacheName = "user_source")
@Slf4j
public class SourceUserServiceImpl extends ViServiceImpl<UserSource> implements SourceUserService {
public SourceUserServiceImpl(Dao dao) {
super(dao);
}
@Inject
private AsyncService asyncService;
@Inject
private SysUserService sysUserService;
@Inject
private HistoryUserService historyUserService;
@Inject
private UserPatUpService userPatUpService;
@Inject
private SysRoleService sysRoleService;
@Inject
private SysUserRoleService sysUserRoleService;
@Override
@Aop(TransAop.READ_COMMITTED)
public void pullSourceData(Boolean isIncrement) {
Date now = new Date();
List<UserSource> users = SourceData.users();
/* List<UserSource> userSourceList = users.stream().filter(v -> !v.getUserState().equals("离校")).collect(Collectors.toList());
//离退休劳模,要更新到系统
List<String> userPartUpLoginNameList = userPatUpService.query(Cnd.where("groupId", "=", 2)).stream().map(UserPartUp::getLoginname).collect(Collectors.toList());
//离退休超过两年
List<UserSource> retireUser = userSourceList.stream().filter(v -> v.getRetireDate() != null && DateUtil.betweenYear(v.getRetireDate(), DateUtil.date(), false) > 2L && !userPartUpLoginNameList.contains(v.getLoginname())).collect(Collectors.toList());
users = userSourceList.stream().filter(v -> !retireUser.contains(v)).collect(Collectors.toList());*/
asyncService.exe2(users, (user) -> {
user.setPullTime(now);
UserMode.initUser(user);
});
dao().insert(users);
}
@Override
@Aop(TransAop.READ_COMMITTED)
public void updateSysUser(String pullTime, String sourceType, String[] columnNames, String isUpSet, String partGroupId, boolean isInvert) {
try {
List<Sys_user> users = sysUserService.query(Cnd.where("loginname", "is not", null));
Map<String, Sys_user> userMap = users.stream().collect(Collectors.toMap(sys_user -> sys_user.getLoginname().toLowerCase(), sys_user -> sys_user));
List<UserSource> sources = new ArrayList<>();
List<UserHistory> histories = new ArrayList<>();
Map<String, String> userPartMap = new HashMap<>();
if (Strings.isNotBlank(partGroupId)) {
//如果为true,更新组别之外人员
Sql sql = Sqls.create("select u.loginname from user_part up left join `user` u on u.id=up.userId where up.groupId = @groupId").setParam("groupId", partGroupId);
List<String> loginNameList = userPatUpService.listMap(sql).stream().map(o -> o.getString("loginname")).collect(Collectors.toList());
if (isInvert) {
sources = query(Cnd.where("pullTime", "=", pullTime).and("loginname", "not in", loginNameList).groupBy("loginname"));
userPartMap = sources.stream().collect(Collectors.toMap(Sys_user::getLoginname, Sys_user::getLoginname));
} else {
userPartMap = userPatUpService.query(Cnd.where("groupId", "=", partGroupId)).stream().collect(Collectors.toMap(UserPartUp::getLoginname, UserPartUp::getLoginname));
sources = query(Cnd.where("pullTime", "=", pullTime).and("loginname", "in", loginNameList).groupBy("loginname"));
}
} else {
sources = query(Cnd.where("pullTime", "=", pullTime).groupBy("loginname"));
}
AtomicReference<Dao> filterColumnDao = new AtomicReference<>(dao());
//全部更新时,要修改的用户表
List<Sys_user> needDoUpdateList = new ArrayList<>();
//新增的用户
List<Sys_user> needInitUserList = new ArrayList<>();
//添加角色的用户
List<Sys_user_role> userRoles = new ArrayList<>();
// 创建一个固定大小的线程池 可以根据服务器性能调整线程池大小
int numberOfThreads = Runtime.getRuntime().availableProcessors() * 2;
List<CompletableFuture<Void>> futures = new ArrayList<>();
// 每批处理的数据量,可以根据实际情况调整
int batchSize = 200;
for (int i = 0; i < sources.size(); i += batchSize) {
final int end = Math.min(i + batchSize, sources.size());
List<UserSource> batch = sources.subList(i, end);
Map<String, String> finalUserPartMap = userPartMap;
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
for (UserSource source : batch) {
//不更新会员和福利会员字段
source.setMember(null);
source.setWelfareMember(null);
Sys_user user = userMap.get(source.getLoginname().toLowerCase());
Sys_user u = new Sys_user();
BeanUtils.copyProperties(source, u);
switch (sourceType) {
case "all" -> {
//复制属性到一个新的user对象
u.setId(user == null ? source.getId() : user.getId());
if (user != null) {
needDoUpdateList.add(u);
}
}
case "add" -> {
u.setId(source.getId());
}
case "part" -> {
u.setId(user == null ? source.getId() : user.getId());
if (columnNames != null && columnNames.length > 0) {
String lockedColumn = String.join("|", columnNames);
FieldFilter fieldFilter = FieldFilter.create(Sys_user.class, null, "^" + lockedColumn + "$", true);
filterColumnDao.set(Daos.ext(dao(), fieldFilter));
}
if (Strings.isNotBlank(finalUserPartMap.get(u.getLoginname())) && user != null) {
needDoUpdateList.add(u);
}
}
}
List<UserChangeType> changeTypes = getChangeTypes(source, user);
if (changeTypes.contains(UserChangeType.NEW)) {
user = UserMode.initUser(u);
needInitUserList.add(user);
Sys_user_role userRole = new Sys_user_role();
userRole.setUserId(user.getId());
userRole.setRoleId(Roles.PUBLIC);
userRoles.add(userRole);
histories.add(createUserHistory(user, changeTypes));
} else if (changeTypes.size() > 0) {
histories.add(createUserHistory(user, changeTypes));
}
}
}, Executors.newFixedThreadPool(numberOfThreads));
futures.add(future);
}
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
//如果有新用户,增加到用户表同时增加角色
if (Lang.isNotEmpty(needInitUserList)) {
sysUserService.fastInsert(needInitUserList);
List<String> userIdList = userRoles.stream().map(Sys_user_role::getUserId).collect(Collectors.toList());
sysUserRoleService.dao().clear(Sys_user_role.class, Cnd.where("userId", "in", userIdList));
sysUserRoleService.insert(userRoles);
}
// Collection<String[]> updateColumns = SourceData.USER_FIELD_RELATION.values();
if ("part".equals(sourceType)) {
massUpdatesAsync(needDoUpdateList, true, filterColumnDao);
} else {
massUpdatesAsync(needDoUpdateList, false, null);
}
//历史记录表插入数据
historyUserService.dao().fastInsert(histories);
//人员状态及在职状态更新
userPatUpService.renewUserState();
//清除缓存
// sysUserService.clearCache();
// sysRoleService.clearCache();
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
@Aop(TransAop.READ_COMMITTED)
public void dailyScheduledUpdates() {
pullSourceData(true);
Date pullTime = (Date) dao().func2(UserSource.class, "max", "pullTime");
updateSysUser(DateUtil.formatDateTime(pullTime), "add",null,null,null,false);
DateTime agoWeekDate = DateUtil.offsetWeek(new Date(), -1);
String formatAgoWeekDate = DateUtil.format(agoWeekDate, "yyyy-MM-dd");
dao().clear(UserSource.class, Cnd.where("DATE(pullTime)", "<", formatAgoWeekDate));
}
private List<UserChangeType> getChangeTypes(Sys_user source, Sys_user user) {
List<UserChangeType> userChangeTypes = new ArrayList<>();
if (user == null) {
userChangeTypes.add(UserChangeType.NEW);
return userChangeTypes;
}
if (!StringUtils.isEmpty(source.getUnitid()) && !source.getUnitid().equals(user.getUnitid())) {
userChangeTypes.add(UserChangeType.UNIT_CHANGE);
}
if (!StringUtils.isEmpty(user.getUserState()) && StrUtil.isNotEmpty(source.getUserState()) && !source.getUserState().equals(user.getUserState())) {
for (UserChangeType value : UserChangeType.values()) {
if (value.getDescription().equals(source.getUserState())) {
userChangeTypes.add(value);
}
}
}
List<String> columns = List.of("nation", "birthday", "personType", "political", "schoolTime", "jobTitle", "education", "academicDegree", "position", "leaveSchoolDate", "retireDate");
for (String column : columns) {
NutMap userSourceMap = Lang.obj2nutmap(source);
NutMap userMap = Lang.obj2nutmap(user);
String sourceValue = userSourceMap.getString(column, "");
String value = userMap.getString(column, "");
if (!sourceValue.equals(value) && StrUtil.isNotBlank(sourceValue)) {
userChangeTypes.add(UserChangeType.BASIC_CHANGE);
break;
}
}
return userChangeTypes;
}
/**
* 生成一条用户历史记录
*
* @param user
* @param changeTypes
* @return
*/
private UserHistory createUserHistory(Sys_user user, List<UserChangeType> changeTypes) {
//除仅更新新增人员外的方式都需要往历史记录表插数据
UserHistory history = new UserHistory();
history.setId(R.UU32());
BeanUtils.copyProperties(user, history);
history.setChangeTime(new Date());
history.setChangeTypes(changeTypes.stream().map(UserChangeType::getCode).collect(Collectors.toList()));
history.setChangeOperator(StrUtil.blankToDefault((String) ShiroUtil.getPrincipalProperty("username"), "系统"));
history.setChangeOrigin(MemberChangeOrigin.SYSTEM.getCode());
history.setChangeReason("数据自动更新");
//找出上一次更新的记录
Sql lastHistorySql = Sqls.fetchString("select id from user_history where loginname = @loginname order by changeTime");
lastHistorySql.setParam("loginname",user.getLoginname());
dao().execute(lastHistorySql);
String lastHistoryId = lastHistorySql.getString();
history.setLastHistoryId(lastHistoryId);
return history;
}
/**
* 数据大批量更新
* @param needDoUpdateList 需要更新的数据
* @param isPart 是否部分更新
* @param filterColumnDao 部分更新传递(部分更新存在过滤字段)
*/
private void massUpdatesAsync(List<Sys_user> needDoUpdateList, Boolean isPart, AtomicReference<Dao> filterColumnDao) {
// 根据服务器性能和任务特性动态确定线程池大小;通常,线程池大小为CPU核心数的2倍
int numberOfThreads = Runtime.getRuntime().availableProcessors() * 2;
ExecutorService executorService = Executors.newFixedThreadPool(numberOfThreads);
ExecutorCompletionService<Void> ecs = new ExecutorCompletionService<>(executorService);
// 每批处理的数据量
int batchSize = 100;
try {
// 将sources分成若干批
for (int i = 0; i < needDoUpdateList.size(); i += batchSize) {
final int end = Math.min(i + batchSize, needDoUpdateList.size());
List<Sys_user> batch = needDoUpdateList.subList(i, end);
// 提交任务给线程池执行
ecs.submit(() -> {
Dao daoToUse = isPart ? filterColumnDao.get() : dao();
// 执行数据库更新操作
synchronized (daoToUse) {
daoToUse.updateIgnoreNull(batch);
}
return null; // CompletionService需要一个返回值,这里返回null
});
}
// 等待所有任务完成
for (int i = 0; i < needDoUpdateList.size(); i += batchSize) {
try {
Future<Void> future = ecs.take();
future.get(); // 等待任务完成
} catch (InterruptedException | ExecutionException e) {
Thread.currentThread().interrupt(); // 恢复中断状态
throw new RuntimeException(e);
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// 关闭线程池
executorService.shutdown();
try {
// 设置合理的超时时间,防止无限期阻塞
if (!executorService.awaitTermination(10, TimeUnit.SECONDS)) {
executorService.shutdownNow(); // 如果超时,强制关闭
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // 恢复中断状态
}
}
}
}