Ver código fonte

闵教院修改提交

pruple_boy 2 anos atrás
pai
commit
15481617de

+ 54 - 0
mjava-minjiaoyuan/pom.xml

@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>java-mcli</artifactId>
+        <groupId>com.malk</groupId>
+        <version>1.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>mjava-minjiaoyuan</artifactId>
+    <description>闵教院教师梯队管理, 骨干系列评选</description>
+
+    <properties>
+        <maven.compiler.source>8</maven.compiler.source>
+        <maven.compiler.target>8</maven.compiler.target>
+    </properties>
+
+    <dependencies>
+        <!-- 核心模块-->
+        <dependency>
+            <groupId>com.malk</groupId>
+            <artifactId>mjava</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <version>2.1.1.RELEASE</version>
+                <configuration>
+                    <includeSystemScope>true</includeSystemScope>
+                    <!-- 如果没有该配置,devtools不会生效: 打包时关闭 -->
+                    <fork>false</fork>
+                    <!-- 避免中文乱码 -->
+                    <jvmArguments>-Dfile.encoding=UTF-8</jvmArguments>
+                </configuration>
+                <!-- 允许生成可运行jar -->
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>repackage</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+        <finalName>${project.artifactId}</finalName>
+    </build>
+</project>

+ 32 - 0
mjava-minjiaoyuan/src/main/java/com/malk/minjiaoyuan/Boot.java

@@ -0,0 +1,32 @@
+package com.malk.minjiaoyuan;
+
+import com.querydsl.jpa.impl.JPAQueryFactory;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
+
+import javax.persistence.EntityManager;
+
+/**
+ * corp项目: 扫描公共模块
+ * -
+ * 若是无需数据库模块, 配置无效地址也可启动, 引入mjava不支持直接 @SpringBootApplication(exclude = DataSourceAutoConfiguration.class) 配置
+ * 需要配置 jpa.hibernate.ddl-auto 为 none. 标识对表没有任何操作. 若不设置为 non, flyway.enabled 配置会无效, 在没有数库连接情况下程序无法启动
+ */
+@EnableJpaAuditing
+@SpringBootApplication(scanBasePackages = {"com.malk"})
+public class Boot {
+
+    public static void main(String... args) {
+        SpringApplication.run(Boot.class, args);
+    }
+
+    /**
+     * 让Spring管理JPAQueryFactory [不使用Qualifier详见mjava-Boot]
+     */
+    @Bean
+    public JPAQueryFactory jpaQueryFactory(EntityManager entityManager) {
+        return new JPAQueryFactory(entityManager);
+    }
+}

+ 98 - 0
mjava-minjiaoyuan/src/main/java/com/malk/minjiaoyuan/controller/InviteControl.java

@@ -0,0 +1,98 @@
+package com.malk.minjiaoyuan.controller;
+
+import com.alibaba.fastjson.JSON;
+import com.malk.Util.UtilMap;
+import com.malk.minjiaoyuan.service.MJYService;
+import com.malk.server.aliwork.YDConf;
+import com.malk.server.aliwork.YDParam;
+import com.malk.server.common.McException;
+import com.malk.server.common.McR;
+import com.malk.server.dingtalk.DDR_New;
+import com.malk.service.aliwork.YDClient;
+import com.malk.service.dingtalk.DDClient;
+import com.malk.service.dingtalk.DDClient_Contacts;
+import lombok.SneakyThrows;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+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 java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 错误抛出与拦截详见CatchException
+ */
+@Slf4j
+@RestController
+@RequestMapping("/minjiaoyuan")
+public class InviteControl {
+
+
+    @Autowired
+    private YDClient ydClient;
+
+    @Autowired
+    private DDClient ddClient;
+
+    @Autowired
+    private DDClient_Contacts ddClient_contacts;
+
+    @Autowired
+    private MJYService mjyService;
+
+    /**
+     * 同步学校 & 钉钉通讯录
+     */
+    @SneakyThrows
+    @PostMapping("sync/department")
+    McR department() {
+        log.info("同步学校 & 钉钉通讯录");
+        List<Map> deptList = ddClient_contacts.getDepartmentDetail_all(ddClient.getAccessToken());
+        for (Map dept : deptList) {
+            YDParam ydParam = YDParam.builder()
+                    .formUuid("FORM-AC666081555ANZAZ6D4IVCQLY5Y12P4ZSRTGLUE")
+                    .searchFieldJson(JSON.toJSONString(UtilMap.map("selectField_lgf41nj4", dept.get("name"))))
+                    .pageSize(1)
+                    .build();
+            DDR_New ddr_new = ydClient.queryData(ydParam, YDConf.FORM_QUERY.retrieve_search_form);
+            if (ddr_new.getTotalCount() == 0) {
+                continue;
+            }
+            Map formData = ((List<Map>) ddr_new.getData()).get(0);
+            if (StringUtils.isNotBlank(String.valueOf(((Map) formData.get("formData")).get("textField_lhldcchn")))) {
+                continue;
+            }
+            Thread.sleep(100); // 避免限流
+            ydParam.setFormInstanceId(formData.get("formInstanceId").toString());
+            ydParam.setUpdateFormDataJson(JSON.toJSONString(UtilMap.map("textField_lhldcchn", dept.get("dept_id"))));
+            ydClient.operateData(ydParam, YDConf.FORM_OPERATION.update);
+        }
+        return McR.success();
+    }
+
+    /**
+     * 创建人员: 邀请到架构 [配置提交校验, 无需更新宜搭单据]
+     */
+    @PostMapping("invite/user")
+    McR createUser(@RequestBody Map data) {
+        log.info("创建员工, {}", data);
+        McException.assertParamException_Null(data, "userId", "name", "mobile", "deptId");
+        Map bodyInfo = UtilMap.map("userid", data.get("userId"));
+        ddClient_contacts.createUser(ddClient.getAccessToken(), String.valueOf(data.get("name")), String.valueOf(data.get("mobile")), Arrays.asList(String.valueOf(data.get("deptId"))), bodyInfo);
+        return McR.success();
+    }
+
+    /**
+     * 同步教师档案 [已邀请], 定时同步后更新为已同步
+     */
+    @PostMapping("sync/teacher")
+    McR syncTeacherStatus() {
+        mjyService.syncTeacherStatus();
+        return McR.success();
+    }
+}

+ 518 - 0
mjava-minjiaoyuan/src/main/java/com/malk/minjiaoyuan/controller/MJYController.java

@@ -0,0 +1,518 @@
+package com.malk.minjiaoyuan.controller;
+
+import com.alibaba.fastjson.JSON;
+import com.malk.Util.UtilList;
+import com.malk.Util.UtilMap;
+import com.malk.Util.UtilServlet;
+import com.malk.Util.UtilString;
+import com.malk.minjiaoyuan.service.MJYService;
+import com.malk.server.aliwork.YDConf;
+import com.malk.server.aliwork.YDParam;
+import com.malk.server.common.McException;
+import com.malk.server.common.McR;
+import com.malk.service.aliwork.YDClient;
+import com.malk.service.aliwork.YDService;
+import lombok.Synchronized;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+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 javax.servlet.http.HttpServletRequest;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * 错误抛出与拦截详见CatchException
+ */
+@Slf4j
+@RestController
+@RequestMapping("/minjiaoyuan")
+public class MJYController {
+
+    @Autowired
+    private YDConf ydConf;
+
+    @Autowired
+    private YDClient ydClient;
+
+    @Autowired
+    private MJYService mjyService;
+
+    /**
+     * 同步名额数据
+     */
+    @Synchronized
+    @PostMapping("sync/quota")
+    McR quotaSync(@RequestBody Map<String, String> data) {
+
+        log.info("###### 同步名额数据 #####");
+
+        // 参数合法校验
+        McException.assertParamException_Null(data, "period");
+        String period = data.get("period");
+
+        // 是否重新计算
+        YDParam ydParam = YDParam.builder()
+                .formUuid("FORM-AC666081555ANZAZ6D4IVCQLY5Y12P4ZSRTGLLE")
+                .pageSize(1)
+                .searchCondition(JSON.toJSONString(UtilMap.map("selectField_lggd61a7", period)))
+                .build();
+        long totalCount = ydClient.queryData(ydParam, YDConf.FORM_QUERY.retrieve_list).getTotalCount();
+        McException.assertAccessException(totalCount > 0, period + "名额已计算, 若需重置请删除后台数据后重试");
+
+        // 查询教师档案
+        ydParam.setSearchCondition(null);
+        ydParam.setFormUuid("FORM-AC666081555ANZAZ6D4IVCQLY5Y12P4ZSRTGLAE");
+        List<Map> teacherList = mjyService.queryAllBySync(ydParam);
+        log.info("教师档案数据, {}", teacherList.size());
+
+        // 学校档案去重
+        List<Map> schoolList = new ArrayList<>();
+        for (Map teacher : teacherList) {
+            Map formData = (Map) teacher.get("formData");
+            // 条件: 学校全称
+            Optional matchData = schoolList.stream().filter(school -> formData.get("textField_lgeyihed").equals(school.get("textField_lgezb8r7"))).findAny();
+            Map schoolMap;
+            if (!matchData.isPresent()) {
+                schoolMap = UtilMap.map("selectField_lggd61a7, radioField_lgf7zdi5", period, "未开始");
+                schoolMap.put("textField_lgezb8r7", formData.get("textField_lgeyihed")); // 学校全称
+                schoolMap.put("textField_lggdp94o", formData.get("textField_lgeyihe8")); // 学校简称
+                schoolMap.put("selectField_lggdghio", formData.get("selectField_lggdghio")); // 所属学段
+                schoolMap.put("numberField_lgf2au4s", 0); // 在编在岗人数
+                schoolList.add(schoolMap);
+            } else {
+                schoolMap = (Map) matchData.get();
+            }
+            // prd: 档案教师计算比例都是在编在岗
+            if (formData.get("radioField_lgezgr8l").equals("是")) {
+                schoolMap.put("numberField_lgf2au4s", (int) schoolMap.get("numberField_lgf2au4s") + 1);
+            }
+            log.debug("教师档案处理, {}", formData);
+        }
+        log.info("学校档案数据, {}, {}", schoolList.size(), schoolList);
+
+        // 学校名额计算
+        for (Map schoolData : schoolList) {
+            String schoolName = String.valueOf(schoolData.get("textField_lgezb8r7"));
+            int numZBZG = Integer.valueOf(String.valueOf(schoolData.get("numberField_lgf2au4s")));
+            // 骨干系列: prd 骨干比例拆分比例分项计算, 合计数不一定匹配, 因此不计算骨干系列名额
+            int ratioGDXT = mjyService.getSchoolRatio(schoolName, "骨干系列");
+            schoolData.put("numberField_lgf2au4t", ratioGDXT);
+            // 学科带头人和骨干教师
+            int ratioXDGG = mjyService.getSchoolRatio(schoolName, "学科带头人和骨干教师");
+            schoolData.put("numberField_lgf2au51", ratioXDGG);
+            schoolData.put("numberField_lgf2au52", Math.round(numZBZG * ratioXDGG / 100));
+            // 骨干后备
+            int numGGHB = Math.round(numZBZG * (ratioGDXT - ratioXDGG) / 100);
+            schoolData.put("numberField_lghpgjyk", ratioGDXT - ratioXDGG);
+            schoolData.put("numberField_lgf2au4z", numGGHB);
+            // 写入学校档案
+            log.info("学校名额计算, {}", schoolData);
+            ydParam.setFormDataJson(JSON.toJSONString(schoolData));
+            ydParam.setFormUuid("FORM-AC666081555ANZAZ6D4IVCQLY5Y12P4ZSRTGLLE");
+            ydClient.operateData(ydParam, YDConf.FORM_OPERATION.create);
+        }
+        return McR.success(mjyService.matchQuery(schoolList));
+    }
+
+    /**
+     * 查询学校名额
+     */
+    @PostMapping("query/quota")
+    McR quotaQuery(@RequestBody Map<String, String> data) {
+        McException.assertParamException_Null(data, "period");
+        String period = data.get("period");
+        YDParam ydParam = YDParam.builder()
+                .formUuid("FORM-AC666081555ANZAZ6D4IVCQLY5Y12P4ZSRTGLLE")
+                .searchCondition(JSON.toJSONString(UtilMap.map("selectField_lggd61a7", period)))
+                .build();
+        List<Map> schoolList = mjyService.queryAllBySync(ydParam);
+        log.info("学校名额数据, {}", schoolList.size());
+        List list = schoolList.stream().map(item -> (Map) item.get("formData")).collect(Collectors.toList());
+        return McR.success(mjyService.matchQuery(list));
+    }
+
+    /**
+     * 推送学校名额确认
+     */
+    @PostMapping("confirm/quota")
+    McR quotaConfirm(HttpServletRequest request) {
+        Map data = UtilServlet.getParamMap(request);
+        McException.assertParamException_Null(data, "formInstanceId");
+        YDParam ydParam = YDParam.builder()
+                .formInstanceId(String.valueOf(data.get("formInstanceId")))
+                .build();
+        Map formData = ydClient.queryData(ydParam, YDConf.FORM_QUERY.retrieve_id).getFormData();
+        List<Map> details = (List<Map>) formData.get("tableField_lgf41nj3");
+        // 创建学校确认流程: src - cur, 发起流程 - 学校确认; 明细内: 全称, 简称, 在编在岗, 学带 + 骨干教师, 后备, 学校负责人
+        Map<String, String> keyMap = UtilMap.map("selectField_lgf41nj4, selectField_lgi7oaqo, numberField_lgf2au4s, numberField_lgi7oaqq, numberField_lgi7oaqr, employeeField_lgf7ky0h",
+                "selectField_lgf41nj4, selectField_lgi7oaqo, numberField_lgf2au4s, numberField_lgi7oaqq, numberField_lgi7oaqr, employeeField_lgf7m9s4");
+        for (Map detail : details) {
+            // 主表读取: 届别, 提交人
+            Map formJson = UtilMap.map("selectField_lggd61a7, employeeField_lgf7ky0i", formData.get("selectField_lggd61a7"), formData.get("employeeField_lgf6dzrv_id"));
+            for (String key : keyMap.keySet()) {
+                if (key.contains("employeeField_")) {
+                    formJson.put(key, detail.get(keyMap.get(key) + "_id"));
+                } else {
+                    formJson.put(key, detail.get(keyMap.get(key)));
+                }
+            }
+            log.info("名额确认记录, {}, {}", formJson, detail);
+            ydParam.setFormDataJson(JSON.toJSONString(formJson));
+            ydParam.setFormUuid("FORM-AC666081555ANZAZ6D4IVCQLY5Y12P4ZSRTGLYD");
+            ydParam.setProcessCode("TPROC--G2666871DH3AGJ52BWGGY62N9HGV39Y1TRTGLL6");
+            ydClient.operateData(ydParam, YDConf.FORM_OPERATION.start);
+        }
+        return McR.success();
+    }
+
+    /**
+     * 汇总学校复核数据
+     */
+    @Synchronized
+    @PostMapping("approve/quota")
+    McR quotaApprove(HttpServletRequest request) {
+        Map data = UtilServlet.getParamMap(request);
+        McException.assertParamException_Null(data, "formInstanceId");
+        log.info("学校汇总, {}", data);
+
+        // 查询教师申请数据
+        YDParam ydParam = YDParam.builder()
+                .formInstanceId(String.valueOf(data.get("formInstanceId")))
+                .build();
+        Map teacherData = ydClient.queryData(ydParam, YDConf.FORM_QUERY.retrieve_id).getFormData();
+
+        // 匹配学校汇总数据: 届别 + 学校全称
+        Map formData = UtilMap.map("selectField_lggd61a7, selectField_lgf41nj4", teacherData.get("selectField_lgs5yclt"), teacherData.get("textField_lgf4ppaw"));
+        ydParam.setFormUuid("FORM-AC666081555ANZAZ6D4IVCQLY5Y12P4ZSRTGLWD");
+        ydParam.setSearchCondition(JSON.toJSONString(formData));
+        List<Map> schoolApprove = (List<Map>) ydClient.queryData(ydParam, YDConf.FORM_QUERY.retrieve_list_all).getData();
+
+        // 组装评审明细数据: 关联评选记录, 教师进修编号, 教师成员, 手机号, 评选类型, 行政职务
+        formData.put("selectField_lgi7oaqo", teacherData.get("textField_lgib58q3")); // 学校简称
+        formData.put("employeeField_lgf7ky0h", teacherData.get("employeeField_lgf7ky0h_id")); // 学校负责人
+        formData.put("radioField_lggd61a8", "进行中"); // 届别评选状态
+        List<Map> details = new ArrayList<>();
+        if (UtilList.isNotEmpty(schoolApprove)) {
+            Map recordData = schoolApprove.get(0);
+            details = mjyService.getCollectData(String.valueOf(recordData.get("formInstanceId"))); // 全量申请数据
+            // 成员组件 && 关联表单数据处理
+            details.forEach(item -> {
+                item.put("employeeField_lgialujd", item.get("employeeField_lgialujd_id"));
+                item.put("associationFormField_lgiacs47", JSON.parse(String.valueOf(item.get("associationFormField_lgiacs47_id"))));
+            });
+            ydParam.setFormInstanceId(String.valueOf(recordData.get("formInstanceId")));
+        }
+        Map detail = UtilMap.map("textField_lgialujb, employeeField_lgialujd, numberField_lgeyihee, selectField_lgf4ppa6, textField_lgt9sb8f, textField_lhxaovhb", teacherData.get("textField_lgf4ppax"), teacherData.get("employeeField_lgf4ppa7_id"), teacherData.get("numberField_lgeyihee"), teacherData.get("selectField_lgf4ppa6"), teacherData.get("textField_lgt9sb8f"), teacherData.get("serialNumberField_lhxa769r"));
+        detail.put("associationFormField_lgiacs47", Arrays.asList(UtilMap.map("appType, formUuid, instanceId, title, formType, subTitle", ydConf.getAppType(), "FORM-AC666081555ANZAZ6D4IVCQLY5Y12P4ZSRTGLVD", data.get("formInstanceId"), teacherData.get("textField_lgs8ej3g"), "receipt", teacherData.get("textField_lgf4ppax"))));
+        details.add(detail);
+        // prd 按照评选类型, 排序: 学带, 骨干, 特色, 后备
+        Map sortRule = UtilMap.map("学科带头人, 骨干教师, 骨干后备, 特色骨干", 1, 2, 3, 4);
+        details.forEach(item -> item.put("sort", sortRule.get(item.get("selectField_lgf4ppa6"))));
+        Collections.sort(details, Comparator.comparingInt(o -> Integer.parseInt(String.valueOf(o.get("sort")))));
+        formData.put("tableField_lgiacs44", details);
+        log.info("学校汇总记录, {}", JSON.toJSONString(formData));
+        ydParam.setFormDataJson(JSON.toJSONString(formData));
+        ydParam.setFormUuid("FORM-AC666081555ANZAZ6D4IVCQLY5Y12P4ZSRTGLWD");
+        ydParam.setProcessCode("TPROC--G2666871DH3AGJ52BWGGY62N9HGV39Y1TRTGLN6");
+        if (UtilList.isNotEmpty(schoolApprove)) {
+            ydParam.setUpdateFormDataJson(ydParam.getFormDataJson());
+            ydClient.operateData(ydParam, YDConf.FORM_OPERATION.update);
+            return McR.success();
+        }
+        ydClient.operateData(ydParam, YDConf.FORM_OPERATION.start);
+
+        return McR.success();
+    }
+
+    @Autowired
+    private YDService ydService;
+
+    /**
+     * 学校申报区里, 名额校验
+     */
+    @PostMapping("validate/quota")
+    McR quotaValidate(HttpServletRequest request) {
+        Map data = UtilServlet.getParamMap(request);
+        McException.assertParamException_Null(data, "formInstanceId");
+        log.info("名额校验, {}", data);
+
+        List usersZRMD = mjyService.getDirectList(); // 直入名单
+        // 学校申报数据
+        YDParam ydParam = YDParam.builder()
+                .formInstanceId(String.valueOf(data.get("formInstanceId")))
+                .build();
+        Map approveData = ydClient.queryData(ydParam, YDConf.FORM_QUERY.retrieve_id).getFormData();
+        List<Map> details = mjyService.getCollectData(String.valueOf(data.get("formInstanceId"))); // 全量教师申请数量
+
+        // 匹配通过数据 & 未在直入名单 [进修编号]
+        List arrStatus = (List) JSON.parse(String.valueOf(data.get("details_status")));
+        List arrType = (List) JSON.parse(String.valueOf(data.get("details_type")));
+        List arrPeerRatio = (List) JSON.parse(String.valueOf(data.get("details_peer_ratio")));
+        List arrSort = (List) JSON.parse(String.valueOf(data.get("details_sort")));
+        List<Map> approveList = new ArrayList();
+        int appXKDTR = 0, appGGJS = 0, appGGHB = 0, appTSGG = 0, appZRMD = 0;
+        for (int i = 0; i < arrStatus.size(); i++) {
+            // prd 直入名单通过人员匹配, 不占用名额, 教师信息报区里
+            if (usersZRMD.contains(details.get(i).get("textField_lgialujb"))) {
+                details.get(i).put("isDirect", "直入名单");
+                approveList.add(details.get(i));
+                appZRMD++;
+                log.info("直入名单, {}", details.get(i));
+            } else if (arrStatus.get(i).equals("通过")) {
+                if (arrType.get(i).equals("学科带头人")) appXKDTR += 1;
+                if (arrType.get(i).equals("骨干教师")) appGGJS += 1;
+                if (arrType.get(i).equals("骨干后备")) appGGHB += 1;
+                if (arrType.get(i).equals("特色骨干")) appTSGG += 1;
+                approveList.add(details.get(i));
+            }
+            // 存储前台填写数据
+            details.get(i).put("textField_lgst1j31", arrPeerRatio.get(i));
+            details.get(i).put("numberField_lh8monwb", arrSort.get(i));
+            details.get(i).put("radioField_lgialujc", arrStatus.get(i));
+        }
+        log.info("申报数量, appXKDTR = {}, appGGJS = {}, appGGHB = {}, appTSGG = {}, appZRMD = {}", appXKDTR, appGGJS, appGGHB, appTSGG, appZRMD);
+
+        // 学校名额信息: 届别 + 学校全称
+        ydParam.setFormInstanceId(null);
+        ydParam.setFormUuid("FORM-AC666081555ANZAZ6D4IVCQLY5Y12P4ZSRTGLLE");
+        ydParam.setSearchCondition(JSON.toJSONString(UtilMap.map("selectField_lggd61a7, textField_lgezb8r7", approveData.get("selectField_lggd61a7"), approveData.get("selectField_lgf41nj4"))));
+        ydParam.setPageSize(1);
+        ydParam.setPageSize(Integer.valueOf(10));
+        // 学校查询输入框, 模糊会有重复情况, 兼容处理
+        List<Map> formList = (List<Map>) ydClient.queryData(ydParam, YDConf.FORM_QUERY.retrieve_list).getData();
+        if (formList.size() > 1) {
+            formList = formList.stream().filter(item -> ((Map) item.get("formData")).get("textField_lgezb8r7").equals(approveData.get("selectField_lgf41nj4"))).collect(Collectors.toList());
+        }
+        Map schoolData = (Map) (formList.get(0)).get("formData");
+
+        int numXDGG = Integer.valueOf(String.valueOf(schoolData.get("numberField_lgf2au52")));
+        int numGGHB = Integer.valueOf(String.valueOf(schoolData.get("numberField_lgf2au4z")));
+        // 学带 + 骨干教师名额校验
+        McException.assertAccessException((appXKDTR + appGGJS) > numXDGG, "申报名额校验未通过,请核查!");
+        // 名额降级逻辑,骨干后备可以占骨干教师 + 学带名额 [prd 申报名额未用完或超标均不能上报]
+        McException.assertAccessException((appGGHB + appXKDTR + appGGJS) != (numGGHB + numXDGG), "申报名额校验未通过,请核查!");
+
+        // 更新申报信息: 进修编号, 评选类型, 同职比, 手机号 [排序]
+        Map updateJson = UtilMap.map("numberField_lgstol7i, numberField_lgstol7k, numberField_lgstol7j, numberField_lgstol7l", appXKDTR, appGGJS, appGGHB, appTSGG);
+        List<Map> appDetails = approveList.stream().map(item -> {
+            Map row = UtilMap.map("textField_lgst1j33, selectField_lgst1j35, textField_lgst1j3g, numberField_lgst1j37", item.get("textField_lgialujb"), item.get("selectField_lgf4ppa6"), item.get("textField_lgst1j31"), item.get("numberField_lgeyihee"));
+            row.put("textField_lgt59zeb", item.get("isDirect"));
+            row.put("employeeField_lgst1j34", item.get("employeeField_lgialujd_id"));
+            row.put("numberField_lh8monwb", item.get("numberField_lh8monwb")); // 未排序过前顺序
+            row.put("associationFormField_lgst1j32", JSON.parse(String.valueOf(item.get("associationFormField_lgiacs47_id"))));
+            return row;
+        }).collect(Collectors.toList());
+        Collections.sort(appDetails, Comparator.comparingInt(o -> Integer.parseInt(String.valueOf(o.get("numberField_lh8monwb")))));
+        // 后置排序, 避免影响到客户填入数据 [先储存再排序]
+        details.forEach(item -> {
+            item.put("employeeField_lgialujd", item.get("employeeField_lgialujd_id"));
+            item.put("associationFormField_lgiacs47", JSON.parse(String.valueOf(item.get("associationFormField_lgiacs47_id"))));
+        });
+        Collections.sort(details, Comparator.comparingInt(o -> Integer.parseInt(String.valueOf(o.get("numberField_lh8monwb")))));
+        updateJson.put("tableField_lgst1j3e", appDetails);
+        updateJson.put("tableField_lgiacs44", details); // 更新学校排序
+        ydParam.setFormInstanceId(String.valueOf(data.get("formInstanceId")));
+        ydParam.setUpdateFormDataJson(JSON.toJSONString(updateJson));
+        // 操作数据 [异步] - 审批通过立即更新, 会无效
+        ydService.operateData(ydParam, YDConf.FORM_OPERATION.update);
+        log.info("更新申报信息, {}", appDetails);
+
+        return McR.success();
+    }
+
+    // 宜搭审批页面弱校验提示框会被覆盖, 或另一个校验冲销. 添加记录, 第二次请求放行
+    private Map checkMap = new HashMap();
+
+    /**
+     * 学校申报区里, 学校中层或校级副职干部, 弱校验
+     */
+    @PostMapping("check/quota")
+    McR quotaCheck(HttpServletRequest request) {
+        Map data = UtilServlet.getParamMap(request);
+        McException.assertParamException_Null(data, "formInstanceId");
+        log.info("名额验证, {}", data);
+
+        List usersZRMD = mjyService.getDirectList(); // 直入名单
+        // 学校申报数据
+        YDParam ydParam = YDParam.builder()
+                .formInstanceId(String.valueOf(data.get("formInstanceId")))
+                .build();
+        Map approveData = ydClient.queryData(ydParam, YDConf.FORM_QUERY.retrieve_id).getFormData();
+        List<Map> details = (List<Map>) approveData.get("tableField_lgiacs44");
+        // 匹配通过数据 & 未在直入名单 [进修编号]
+        List arrStatus = (List) JSON.parse(String.valueOf(data.get("details_status")));
+        List arrType = (List) JSON.parse(String.valueOf(data.get("details_type")));
+        List<Map> approveList = new ArrayList();
+        int appGGHB = 0;
+        for (int i = 0; i < arrStatus.size(); i++) {
+            // prd 直入名单通过人员匹配, 不占用名额, 教师信息报区里
+            if (usersZRMD.contains(details.get(i).get("textField_lgialujb"))) {
+                approveList.add(details.get(i));
+                details.get(i).put("isDirect", "直入名单");
+                log.info("直入名单, {}", details.get(i));
+            } else if (arrStatus.get(i).equals("通过")) {
+                approveList.add(details.get(i));
+                if (arrType.get(i).equals("骨干后备")) appGGHB += 1;
+            }
+        }
+        float numZCXF = approveList.stream().filter(item -> Arrays.asList("学校副职", "中层副职", "中层正职").contains(item.get("textField_lgt9sb8f"))).collect(Collectors.toList()).size();
+        log.info("学校中层或校级副职干部, 弱校验, appGGHB = {}, nunZCXF = {}", appGGHB, numZCXF);
+
+        // 学校名额信息: 届别 + 学校全称
+        ydParam.setFormInstanceId(null);
+        ydParam.setFormUuid("FORM-AC666081555ANZAZ6D4IVCQLY5Y12P4ZSRTGLLE");
+        ydParam.setSearchCondition(JSON.toJSONString(UtilMap.map("selectField_lggd61a7, textField_lgezb8r7", approveData.get("selectField_lggd61a7"), approveData.get("selectField_lgf41nj4"))));
+        ydParam.setPageSize(1);
+        Map schoolData = (Map) ((List<Map>) ydClient.queryData(ydParam, YDConf.FORM_QUERY.retrieve_list).getData()).get(0).get("formData");
+        // prd 学校中层或校级副职干部,每周兼课时数需达到教育局规定课时量,比例不超过学校申报骨干后备教师人选的20%。(学校教师人在编在岗数不满30人,比例不超过学校申报骨干后备教师人选的25%)
+        float numZBZG = Integer.valueOf(String.valueOf(schoolData.get("numberField_lgf2au4s")));
+        int ratio = numZBZG >= 30 ? 25 : 20;
+        log.info("学校中层或校级副职干部, 弱校验, check = {}, ratio = {}", appGGHB / numZBZG, ratio / 100F);
+        if (!checkMap.containsKey(data.get("formInstanceId"))) {
+            checkMap.put(data.get("formInstanceId"), true);
+            McException.assertAccessException((appGGHB / numZBZG) > (ratio / 100F), "学校中层或校级副职干部, 占比骨干后备超标准");
+        }
+        return McR.success();
+    }
+
+    /**
+     * 是否直入名单
+     */
+    @PostMapping("direct/quota")
+    McR directQuota(@RequestBody Map data) {
+        log.info("是否直入名单", data);
+        McException.assertParamException_Null(data, "code");
+        List usersZRMD = mjyService.getDirectList(); // 直入名单
+        return McR.success(UtilMap.map("isDirect", usersZRMD.contains(data.get("code"))));
+    }
+
+    /**
+     * 退回卡片通知
+     * 被学校退回:某某老师,您的骨干系列评选材料已被学校退回。
+     * 被区级退回:某某老师,您的骨干系列评选材料已被区级退回;某某学校,您校某某老师的评选资料已被区级退回。
+     */
+    @PostMapping("notice/sendback")
+    McR sendBackNotice(HttpServletRequest request) {
+        Map data = UtilServlet.getParamMap(request);
+        log.info("退回卡片通知, {}", data);
+        McException.assertParamException_Null(data, "teachers, administrator, results, associations, createUserId, schoolName");
+        List<String> teachers = (List<String>) JSON.parse(String.valueOf(data.get("teachers")));
+        List<String> associations = (List<String>) JSON.parse(String.valueOf(data.get("associations")));
+        List<String> results = (List<String>) JSON.parse(String.valueOf(data.get("results")));
+        String createUserId = String.valueOf(data.get("createUserId"));
+        String schoolName = String.valueOf(data.get("schoolName"));
+        for (int i = 0; i < results.size(); i++) {
+            String status = results.get(i);
+            if (!Arrays.asList("不通过", "退回").contains(status)) {
+                continue;
+            }
+            List<Map> associationForm = (List<Map>) JSON.parse(associations.get(i));
+            String notice = associationForm.get(0).get("title") + "老师[" + associationForm.get(0).get("subTitle") + "]";
+            Map formData = UtilMap.map("employeeField_lhgj6tc7, employeeField_lhgj6tc9, associationFormField_lgiacs47", JSON.parse(teachers.get(i)), data.get("administrator"), associationForm);
+            if ("不通过".equals(status)) {
+                notice += ", 您好: \n您的骨干系列评选材料已被学校退回。";
+            }
+            if ("退回".equals(status)) {
+                notice += ", 您好: \n您的骨干系列评选材料已被区级退回。";
+                // 通知学校
+                String new_notice = schoolName + ", 管理员您好: \n您校" + associationForm.get(0).get("title") + "老师[" + associationForm.get(0).get("subTitle") + "]";
+                new_notice += "的评选资料已被区级退回。";
+                formData.put("textareaField_lhgj6tcu", new_notice);
+                mjyService.triggerNotice("FORM-NC966W81139A3Y5QEEXT5AZ6BU7M3TB0C9LHLO", createUserId, formData);
+            }
+            // 通知老师
+            formData.put("textareaField_lhgj6tcu", notice);
+            mjyService.triggerNotice("FORM-NT766881D48AF5W78VL7L6VLZTAJ2TOE6JGHL92", createUserId, formData);
+        }
+        return McR.success();
+    }
+
+    /**
+     * 评选信息变更
+     */
+    @PostMapping("update/details")
+    McR updateDetails(HttpServletRequest request) {
+        Map data = UtilServlet.getParamMap(request);
+        McException.assertParamException_Null(data, "formInstanceId");
+        log.info("信息变更, {}", data);
+
+        YDParam ydParam = YDParam.builder()
+                .formInstanceId(String.valueOf(data.get("formInstanceId")))
+                .build();
+        Map formData = ydClient.queryData(ydParam, YDConf.FORM_QUERY.retrieve_id).getFormData();
+        List<Map> details = (List<Map>) formData.get("tableField_lgs5ycm5");
+
+        List<Map> association = (List<Map>) JSON.parse(String.valueOf(data.get("associationComp")));
+        ydParam.setFormInstanceId(String.valueOf(association.get(0).get("instanceId")));
+        ydParam.setUpdateFormDataJson(JSON.toJSONString(UtilMap.map("tableField_lgs5ycm5", details)));
+        ydClient.operateData(ydParam, YDConf.FORM_OPERATION.update);
+        return McR.success();
+    }
+
+    /**
+     * 学校管理员撤回
+     */
+    @Synchronized
+    @PostMapping({"cancel/quota"})
+    McR cancelQuota(@RequestBody Map data) {
+        log.info("学校管理员撤回, {}", data);
+        McException.assertParamException_Null(data, "serialNumber, teacherCode, schoolShort, period, formInstId");
+        YDParam ydParam = YDParam.builder()
+                .formUuid("FORM-AC666081555ANZAZ6D4IVCQLY5Y12P4ZSRTGL7E")
+                .searchFieldJson(JSON.toJSONString(UtilMap.map("textField_lftczqr5", data.get("teacherCode"))))
+                .pageSize(1)
+                .build();
+        Map dataForm = ((List<Map>) ydClient.queryData(ydParam, YDConf.FORM_QUERY.retrieve_search_form).getData()).get(0);
+        Map formData = (Map) dataForm.get("formData");
+        // 校验, 修改教师档案
+        String result = String.valueOf(formData.get("radioField_lgfawf83"));
+        McException.assertAccessException((!result.equals("内通过") && !result.equals("内拒绝")), "当前结果为" + (UtilString.isBlankCompatNull(result) ? "未开始" : result) + ", 不支持撤销!");
+        ydParam.setFormInstanceId(dataForm.get("formInstanceId").toString());
+        ydParam.setUpdateFormDataJson(JSON.toJSONString(UtilMap.map("radioField_lgfawf83", "")));
+        ydClient.operateData(ydParam, YDConf.FORM_OPERATION.update);
+        // 修改教师档案
+        ydParam.setFormInstanceId("");
+        ydParam.setFormUuid("FORM-AC666081555ANZAZ6D4IVCQLY5Y12P4ZSRTGLAE");
+        ydParam.setSearchFieldJson(JSON.toJSONString(UtilMap.map("textField_lftczqr5", data.get("teacherCode"))));
+        dataForm = ((List<Map>) ydClient.queryData(ydParam, YDConf.FORM_QUERY.retrieve_search_form).getData()).get(0);
+        ydParam.setFormInstanceId(dataForm.get("formInstanceId").toString());
+        ydParam.setUpdateFormDataJson(JSON.toJSONString(UtilMap.map("radioField_lhlbdk4w", "")));
+        ydClient.operateData(ydParam, YDConf.FORM_OPERATION.update);
+        // 修改评选报名
+        ydParam.setFormInstanceId(data.get("formInstId").toString());
+        ydParam.setUpdateFormDataJson(JSON.toJSONString(UtilMap.map("textField_li0f7sah", "")));
+        ydClient.operateData(ydParam, YDConf.FORM_OPERATION.update);
+        ydParam.setFormInstanceId("");
+        // 删除评选汇总
+        ydParam.setFormUuid("FORM-AC666081555ANZAZ6D4IVCQLY5Y12P4ZSRTGLWD");
+        ydParam.setSearchFieldJson(JSON.toJSONString(UtilMap.map("selectField_lgi7oaqo, selectField_lggd61a7", new Object[]{data.get("schoolShort"), data.get("period")})));
+        String processInstanceId = ((List<String>) ydClient.queryData(ydParam, YDConf.FORM_QUERY.retrieve_search_process_id).getData()).get(0);
+        List<Map> details = mjyService.getCollectData(processInstanceId);
+        Optional optional = details.stream().filter(item -> item.get("textField_lhxaovhb").equals(data.get("serialNumber"))).findAny();
+        if (optional.isPresent()) {
+            details.remove(optional.get());
+            ydParam.setFormInstanceId(processInstanceId);
+            // 宜搭BUG: 若仅剩一条, 明细不支持删除, 只能删除主表
+            if (details.isEmpty()) {
+                ydClient.operateData(ydParam, YDConf.FORM_OPERATION.delete);
+            } else {
+                details.forEach(item -> {
+                    item.put("employeeField_lgialujd", item.get("employeeField_lgialujd_id"));
+                    item.put("associationFormField_lgiacs47", JSON.parse(String.valueOf(item.get("associationFormField_lgiacs47_id"))));
+                });
+                ydParam.setUpdateFormDataJson(JSON.toJSONString(UtilMap.map("tableField_lgiacs44", details)));
+                ydClient.operateData(ydParam, YDConf.FORM_OPERATION.update);
+            }
+            String notice = data.get("teacherName") + "老师[" + data.get("teacherCode") + "]";
+            notice = notice + ", 您好: \n您的评选材料经过学校审核被撤销, 请按照要求重新提交评选材料。";
+            dataForm = UtilMap.map("employeeField_lhgj6tc7, textField_lhlj3dgb, textareaField_lhgj6tcu", Arrays.asList(data.get("teacherCode")), data.get("teacherCode"), notice);
+            mjyService.triggerNotice("FORM-F8666NB1MRZA2CT097OAE65SOFSV27SERG0ILB", String.valueOf(data.get("teacherCode")), dataForm);
+            log.info("撤销成功, {}", optional.get());
+        }
+        return McR.success(details);
+    }
+}

+ 60 - 0
mjava-minjiaoyuan/src/main/java/com/malk/minjiaoyuan/controller/TestControl.java

@@ -0,0 +1,60 @@
+package com.malk.minjiaoyuan.controller;
+
+import com.malk.minjiaoyuan.service.MJYService;
+import com.malk.server.aliwork.YDConf;
+import com.malk.server.aliwork.YDParam;
+import com.malk.server.common.McR;
+import com.malk.service.aliwork.YDClient;
+import com.malk.service.aliwork.YDService;
+import com.malk.service.dingtalk.DDClient;
+import com.malk.service.dingtalk.DDClient_Contacts;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Profile;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+import java.util.Map;
+
+@Profile({"dev"})
+@RestController
+@RequestMapping({"/minjiaoyuan"})
+public class TestControl {
+    private static final Logger log = LoggerFactory.getLogger(com.malk.minjiaoyuan.controller.TestControl.class);
+
+    @Autowired
+    private YDClient ydClient;
+
+    @Autowired
+    private YDConf ydConf;
+
+    @Autowired
+    private MJYService mjyService;
+
+    @Autowired
+    private YDService ydService;
+
+    @Autowired
+    private DDClient ddClient;
+
+    @Autowired
+    private DDClient_Contacts ddClient_contacts;
+
+    @PostMapping({"test2"})
+    McR test2() {
+        return McR.success();
+    }
+
+    @PostMapping({"test"})
+    McR test() {
+        return McR.success();
+    }
+
+    public List<Map> getCollectData(String formInstanceId) {
+        YDParam ydParam = YDParam.builder().formUuid("FORM-AC666081555ANZAZ6D4IVCQLY5Y12P4ZSRTGLWD").formInstanceId(formInstanceId).tableFieldId("tableField_lgst1j3e").build();
+        return this.ydService.queryDetails(ydParam);
+    }
+}

+ 36 - 0
mjava-minjiaoyuan/src/main/java/com/malk/minjiaoyuan/schedule/MJYScheduleTask.java

@@ -0,0 +1,36 @@
+package com.malk.minjiaoyuan.schedule;
+
+import com.malk.minjiaoyuan.service.MJYService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.scheduling.annotation.Scheduled;
+
+/**
+ * @EnableScheduling 开启桑诺定时任务 [配置参考McScheduleTask]
+ */
+@Slf4j
+@Configuration
+@EnableScheduling
+@ConditionalOnProperty(name = {"spel.scheduling"})
+public class MJYScheduleTask {
+
+    @Autowired
+    private MJYService mjyService;
+
+    /**
+     * 定时同步后更新为已同步 [0...5分钟/次]
+     */
+    @Scheduled(cron = "0 0/5 * * * ?")
+    public void Time_Period_1() {
+        try {
+            log.info("###### [MJY]同步教师档案开始 [已邀请] ######");
+            mjyService.syncTeacherStatus();
+        } catch (Exception e) {
+            log.error(e.getMessage(), e); // 记录错误日志
+        }
+        log.info("###### [MJY]同步教师档案结束 [已邀请] ######");
+    }
+}

+ 38 - 0
mjava-minjiaoyuan/src/main/java/com/malk/minjiaoyuan/service/MJYService.java

@@ -0,0 +1,38 @@
+package com.malk.minjiaoyuan.service;
+
+import com.malk.server.aliwork.YDParam;
+
+import java.util.List;
+import java.util.Map;
+
+public interface MJYService {
+
+    // 获取学校与类型比例
+    int getSchoolRatio(String schoolName, String typeName);
+
+    // 查询全部数据
+    List<Map> queryAllBySync(YDParam param);
+
+    // 获取直入名单
+    List<String> getDirectList();
+
+    // 触发通知 [宜搭平台账号不会触发通知]
+    void triggerNotice(String formUuid, String createUserId, Map formData);
+
+    // 匹配学校负责人
+    List<Map> matchQuery(List<Map> schoolQuotaList);
+
+    // 同步教师档案 [已邀请]
+    void syncTeacherStatus();
+
+    // 教师申请名单[明细默认只返回前50]
+    List<Map> getCollectData(String paramString);
+
+    // 查询全部数据[异步], 删除和新增需先全量查询后, 在进行操作, 分页处理数据排序会发生变化
+    List<Map> queryAllBySync(YDParam paramYDParam, QueryLambda paramQueryLambda);
+
+    @FunctionalInterface
+    interface QueryLambda {
+        void dataList(List list);
+    }
+}

+ 194 - 0
mjava-minjiaoyuan/src/main/java/com/malk/minjiaoyuan/service/impl/MJYImplService.java

@@ -0,0 +1,194 @@
+package com.malk.minjiaoyuan.service.impl;
+
+import cn.hutool.core.util.ObjectUtil;
+import com.alibaba.fastjson.JSON;
+import com.malk.Util.UtilMap;
+import com.malk.minjiaoyuan.service.MJYService;
+import com.malk.server.aliwork.YDConf;
+import com.malk.server.aliwork.YDParam;
+import com.malk.server.common.McException;
+import com.malk.service.aliwork.YDClient;
+import com.malk.service.aliwork.YDService;
+import com.malk.service.dingtalk.DDClient;
+import com.malk.service.dingtalk.DDClient_Contacts;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+@Service
+@Slf4j
+public class MJYImplService implements MJYService {
+
+    @Autowired
+    private YDClient ydClient;
+
+    @Autowired
+    private YDService ydService;
+
+    // 名额配置
+    private List<Map> quotaList = new ArrayList<>();
+
+    // 获取学校与类型比例
+    @Override
+    public int getSchoolRatio(String schoolName, String typeName) {
+        if (quotaList.isEmpty()) {
+            List<Map> list = (List<Map>) ydClient.queryData(YDParam.builder()
+                    .formUuid("FORM-AC666081555ANZAZ6D4IVCQLY5Y12P4ZSRTGLKE")
+                    .pageSize(YDConf.PAGE_SIZE_LIMIT)
+                    .build(), YDConf.FORM_QUERY.retrieve_list_all).getData();
+            quotaList = list.stream().map(item -> (Map) item.get("formData")).collect(Collectors.toList());
+            log.info("名额配置数据, {}", quotaList.size());
+        }
+        Map formData = quotaList.stream().filter(item -> typeName.equals(item.get("selectField_lgf306u6"))).findAny().get();
+        int ratio = Integer.valueOf(String.valueOf(formData.get("numberField_lgezizyl")));
+        List<Map<String, ?>> details = (List<Map<String, ?>>) formData.get("tableField_lgezizyn");
+        Optional detail = details.stream().filter(item -> item.get("selectField_lgezizyo").equals(schoolName)).findAny();
+        if (detail.isPresent()) {
+            ratio = Integer.valueOf(String.valueOf(((Map) detail.get()).get("numberField_lgezizyq")));
+        }
+        return ratio;
+    }
+
+    // 查询全部数据
+    @Override
+    public List<Map> queryAllBySync(YDParam param) {
+        param.setPageSize(1);
+        long totalCount = ydClient.queryData(param, YDConf.FORM_QUERY.retrieve_list).getTotalCount();
+        List<Map> dataList = new ArrayList<>();
+        // Math.ceil 需要有浮点数, 否则转 int 类型忽略掉, 向上取整就会是当前值
+        for (int index = 1; index <= (int) Math.ceil(totalCount * 1.0 / YDConf.PAGE_SIZE_LIMIT); index++) {
+            // 对象拷贝: 避免并发下分页条件被修改导致数据混乱
+            YDParam ydParam = (YDParam) param.copyParam();
+            ydParam.setPageNumber(index);
+            ydParam.setPageSize(YDConf.PAGE_SIZE_LIMIT);
+            dataList.addAll((List) ydClient.queryData(ydParam, YDConf.FORM_QUERY.retrieve_list).getData());
+        }
+        return dataList;
+    }
+
+    // 查询全部数据[异步]
+    @Override
+    public List<Map> queryAllBySync(YDParam ydParam, MJYService.QueryLambda lambda) {
+        int pageSize = ((ydParam.getPageSize().intValue() > 0) ? ydParam.getPageSize() : YDConf.PAGE_SIZE_LIMIT).intValue();
+        ydParam.setPageSize(Integer.valueOf(1));
+        long totalCount = this.ydClient.queryData(ydParam, YDConf.FORM_QUERY.retrieve_list).getTotalCount();
+        List<Map> dataList = new ArrayList<>();
+        for (int index = 1; index <= (int) Math.ceil(totalCount * 1.0D / pageSize); index++) {
+            ydParam.setPageSize(Integer.valueOf(pageSize));
+            List<Map> formList = (List<Map>) this.ydClient.queryData(ydParam, YDConf.FORM_QUERY.retrieve_list).getData();
+            if (ObjectUtil.isNotNull(lambda))
+                lambda.dataList(formList);
+            dataList.addAll(formList);
+        }
+        return dataList;
+    }
+
+    // 获取直入名单
+    @Override
+    public List<String> getDirectList() {
+        YDParam ydParam = YDParam.builder()
+                .formUuid("FORM-AC666081555ANZAZ6D4IVCQLY5Y12P4ZSRTGLKE")
+                .searchCondition(JSON.toJSONString(UtilMap.map("selectField_lgf306u6", "直入名单")))
+                .pageSize(1)
+                .build();
+        String formInstanceId = (String) ((List<Map>) ydClient.queryData(ydParam, YDConf.FORM_QUERY.retrieve_search_form).getData()).get(0).get("formInstanceId");
+        ydParam.setFormInstanceId(formInstanceId);
+        ydParam.setTableFieldId("tableField_lgf2p2jm");
+        List<Map> details = ydService.queryDetails(ydParam);
+        log.info("直入名单, {}", details.size());
+        return details.stream().map(item -> (String) item.get("textField_lgt5j83x")).collect(Collectors.toList());
+    }
+
+    // 触发通知
+    @Override
+    public void triggerNotice(String formUuid, String createUserId, Map formData) {
+        YDParam ydParam = YDParam.builder()
+                .formUuid(formUuid)
+                .formDataJson(JSON.toJSONString(formData))
+                .userId(createUserId) // 触发通知
+                .build();
+        ydClient.operateData(ydParam, YDConf.FORM_OPERATION.create);
+    }
+
+    // 匹配学校负责人
+    @Override
+    public List<Map> matchQuery(List<Map> schoolQuotaList) {
+        YDParam ydParam = YDParam.builder()
+                .formUuid("FORM-AC666081555ANZAZ6D4IVCQLY5Y12P4ZSRTGLUE")
+                .build();
+        List<Map> schoolAuthList = queryAllBySync(ydParam);
+        List list = schoolQuotaList.stream().map(item -> {
+            // 条件: 学校全称
+            Optional optional = schoolAuthList.stream().filter(row -> ((Map) row.get("formData")).get("selectField_lgf41nj4").equals(item.get("textField_lgezb8r7"))).findAny();
+            if (optional.isPresent()) {
+                Map data = (Map) ((Map) optional.get()).get("formData");
+                // 前端展示格式: prd 学校负责人单选
+                List<String> empsName = (List<String>) data.get("employeeField_lgf7h60y");
+                List<String> empsId = (List<String>) data.get("employeeField_lgf7h60y_id");
+                List<Map> managers = new ArrayList<>();
+                for (int i = 0; i < empsName.size(); i++) {
+                    managers.add(UtilMap.map("name, value", empsName.get(i), empsId.get(i)));
+                }
+                item.put("employeeField_lgf7m9s4", managers);
+                log.info("匹配学校负责人, {}", data);
+            }
+            return item;
+        }).collect(Collectors.toList());
+        return list;
+    }
+
+    @Autowired
+    private DDClient ddClient;
+
+    @Autowired
+    private DDClient_Contacts ddClient_contacts;
+
+    // 同步教师档案 [已邀请]
+    @Override
+    public void syncTeacherStatus() {
+        // 查询已邀请教师档案数据
+        YDParam ydParam = YDParam.builder()
+                .formUuid("FORM-AC666081555ANZAZ6D4IVCQLY5Y12P4ZSRTGLAE")
+                .searchFieldJson(JSON.toJSONString(UtilMap.map("radioField_lhlhshbc", "已邀请")))
+                .build();
+        List<Map> dataList = queryAllBySync(ydParam);
+        log.info("同步教师数量, {}", dataList.size());
+        for (Map formData : dataList) {
+            Map dataForm = (Map) formData.get("formData");
+            String userId = dataForm.get("textField_lftczqr5").toString();
+            String remark;
+            String status = "已邀请";
+            // 是否进入架构
+            try {
+                ddClient_contacts.getUserInfoById(ddClient.getAccessToken(), userId);
+                remark = "已同步";
+                status = "已同步";
+            } catch (McException e) {
+                remark = e.getMessage();
+                log.error(e.getMessage(), e);
+            }
+            // 发送同步通知
+            if ("已同步".equals(remark)) {
+                String notice = dataForm.get("textField_lghs4pmx") + "老师[" + userId + "]";
+                notice += ", 您好: \n欢迎加入【闵行区教师梯队管理】架构, 您的档案已同步, 可发起骨干系列评选报名";
+                Map data = UtilMap.map("employeeField_lhgj6tc7, textField_lhlj3dgb, textareaField_lhgj6tcu", Arrays.asList(userId), userId, notice);
+                triggerNotice("FORM-8Y866XB1FGHAB037F4F7054SZMHI2RFZ1JLHLP", userId, data);
+            }
+            // 同步邀请状态
+            ydParam.setFormInstanceId(formData.get("formInstanceId").toString());
+            ydParam.setUpdateFormDataJson(JSON.toJSONString(UtilMap.map("textareaField_lhlqrv31, radioField_lhlhshbc, employeeField_lgeyfc4d", remark, status, Arrays.asList(userId))));
+            ydClient.operateData(ydParam, YDConf.FORM_OPERATION.update);
+            log.info("同步教师状态, {}, {}", userId, remark);
+        }
+    }
+
+    // 教师申请名单[明细默认只返回前50]
+    @Override
+    public List<Map> getCollectData(String formInstanceId) {
+        YDParam ydParam = YDParam.builder().formUuid("FORM-AC666081555ANZAZ6D4IVCQLY5Y12P4ZSRTGLWD").formInstanceId(formInstanceId).tableFieldId("tableField_lgiacs44").build();
+        return this.ydService.queryDetails(ydParam);
+    }
+}

+ 65 - 0
mjava-minjiaoyuan/src/main/resources/application-dev.yml

@@ -0,0 +1,65 @@
+# 环境配置
+server:
+  port: 9001
+  servlet:
+    context-path: /api
+
+# condition
+spel:
+  scheduling: false        # 定时任务是否执行
+  multiSource: false       # 是否多数据源配置
+
+spring:
+  # database
+  datasource:
+    driver-class-name: com.mysql.cj.jdbc.Driver
+    username: root
+    password: mu123
+    url: jdbc:mysql://127.0.0.1:3306/mjava?serverTimezone=Asia/Shanghai&useUnicode=yes&characterEncoding=UTF-8&useSSL=true
+  jpa:
+    hibernate:
+      ddl-auto: none      # JPA对表没有任何操作
+    show-sql: true
+    database: MYSQL
+    database-platform: org.hibernate.dialect.MySQL57Dialect
+
+# filepath
+file:
+  path:
+    file: /Users/malk/service/_Tool/var/mjava/tmp//file/
+    image: /Users/malk/service/_Tool/var/mjava/tmp//image/
+    tmp: /Users/malk/service/_Tool/var/mjava/tmp/
+  source:
+    fonts: /Users/malk/service/_Tool/fonts/simsun.ttc
+logging:
+  file:
+    path: /Users/malk/service/_Tool/var/mjava/log
+
+## dingtalk
+#dingtalk:
+#  agentId: 2550726809
+#  appKey: dingtift81fcga4rmrmk
+#  appSecret: Oa_S7CYYAfa3CurDbaTk1CBlSvfpcFs6ROjt8OTS8fDsjnS45X1CmxGgWbpJ8lI0
+#  corpId: dingcc1b1ffad0d5ca1d
+#  aesKey:
+#  token:
+#
+## aliwork
+#aliwork:
+#  appType: APP_GHMWTMHNZFEX24QOUC63
+#  systemToken: 4A9667B1NXM9XUSBDNR208ZMA2UQ20A99XEGLIC
+
+
+# dingtalk
+dingtalk:
+  agentId: 2559056539
+  appKey: dingpd6ukkzzcbsczp0n
+  appSecret: 7tTurS8akT9OYegOIe9sBpqdLXOxNCtlNgIwqdolH3VkTxupXzN_fQwASzBQHE6A
+  corpId: ding0f12f2ed788f674ef5bf40eda33b7ba0
+  aesKey:
+  token:
+
+# aliwork
+aliwork:
+  appType: APP_AD5T4ITVLW40MKR7V3LM
+  systemToken: 7N5664D1GX5A9VWICV06RCOARNMW273ZSRTGL7N7

+ 47 - 0
mjava-minjiaoyuan/src/main/resources/application-prod.yml

@@ -0,0 +1,47 @@
+# 环境配置
+server:
+  port: 9007
+
+# condition
+spel:
+  scheduling: true        # 定时任务是否执行
+  multiSource: false      # 是否多数据源配置
+
+spring:
+  # database
+  datasource:
+    driver-class-name: com.mysql.cj.jdbc.Driver
+    username: root
+    password: cp-root@2022++
+    url: jdbc:mysql://47.97.181.40:3306/mjava?serverTimezone=Asia/Shanghai&useUnicode=yes&characterEncoding=UTF-8&useSSL=true
+  jpa:
+    database: MYSQL
+    database-platform: org.hibernate.dialect.MySQL57Dialect
+
+## dingtalk
+#dingtalk:
+#  agentId: 2550726809
+#  appKey: dingtift81fcga4rmrmk
+#  appSecret: Oa_S7CYYAfa3CurDbaTk1CBlSvfpcFs6ROjt8OTS8fDsjnS45X1CmxGgWbpJ8lI0
+#  corpId: dingcc1b1ffad0d5ca1d
+#  aesKey:
+#  token:
+#
+## aliwork
+#aliwork:
+#  appType: APP_GHMWTMHNZFEX24QOUC63
+#  systemToken: 4A9667B1NXM9XUSBDNR208ZMA2UQ20A99XEGLIC
+
+# dingtalk
+dingtalk:
+  agentId: 2559056539
+  appKey: dingpd6ukkzzcbsczp0n
+  appSecret: 7tTurS8akT9OYegOIe9sBpqdLXOxNCtlNgIwqdolH3VkTxupXzN_fQwASzBQHE6A
+  corpId: ding0f12f2ed788f674ef5bf40eda33b7ba0
+  aesKey:
+  token:
+
+# aliwork
+aliwork:
+  appType: APP_AD5T4ITVLW40MKR7V3LM
+  systemToken: 7N5664D1GX5A9VWICV06RCOARNMW273ZSRTGL7N7

+ 35 - 0
mjava-minjiaoyuan/src/test/resources/server.sh

@@ -0,0 +1,35 @@
+#!/bin/bash
+appname='mjava-minjiaoyuan'
+if [ "$1" == "dev" ]; then
+  java -Xms256m -Xmx256m -jar $appname.jar --spring.profiles.active=dev
+else
+  if [ "$1" == "start" ]; then
+    nohup java -Xms256m -Xmx256m -jar $appname.jar &
+    echo "server prod is starting"
+  else
+    if [ "$1" == "test" ]; then
+      nohup java -Xms256m -Xmx256m -jar $appname.jar --spring.profiles.active=test &
+      echo "server test is starting"
+    else
+      if [ "$1" == "stop" ]; then
+        PID=$(ps -ef | grep $appname.jar | grep -v grep | awk '{ print $2 }')
+        if [ -z "$PID" ]; then
+          echo "server is already stopped"
+        else
+          echo kill $PID
+          kill $PID
+        fi
+      else
+        if [ "$1" == "status" ]; then
+          PID=$(ps -ef | grep $appname.jar | grep -v grep | awk '{ print $2 }')
+          if [ -z "$PID" ]; then
+            echo "server is stopped"
+          else
+            echo "server is running"
+            echo $PID
+          fi
+        fi
+      fi
+    fi
+  fi
+fi

+ 1 - 0
mjava-xintianlong/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst

@@ -0,0 +1 @@
+com/malk/xintianlong/repository/dao/HSViewDao.class

BIN
mjava-xintianlong/target/mjava-xintianlong.jar.original


+ 30 - 0
mjava/target/classes/META-INF/spring-configuration-metadata.json

@@ -60,6 +60,11 @@
       "type": "com.malk.server.common.FilePath$Path",
       "sourceType": "com.malk.server.common.FilePath$Path"
     },
+    {
+      "name": "file.path",
+      "type": "com.malk.server.common.FilePath$Path",
+      "sourceType": "com.malk.server.common.FilePath$Path"
+    },
     {
       "name": "file.source",
       "type": "com.malk.server.common.FilePath$Source",
@@ -95,6 +100,11 @@
       "type": "com.malk.server.common.FilePath$Source",
       "sourceType": "com.malk.server.common.FilePath$Source"
     },
+    {
+      "name": "file.source",
+      "type": "com.malk.server.common.FilePath$Source",
+      "sourceType": "com.malk.server.common.FilePath$Source"
+    },
     {
       "name": "fxiaoke",
       "type": "com.malk.server.fxiaoke.FXKConf",
@@ -244,6 +254,16 @@
       "type": "java.lang.String",
       "sourceType": "com.malk.server.common.FilePath$Path"
     },
+    {
+      "name": "file.path.file",
+      "type": "java.lang.String",
+      "sourceType": "com.malk.server.common.FilePath$Path"
+    },
+    {
+      "name": "file.path.image",
+      "type": "java.lang.String",
+      "sourceType": "com.malk.server.common.FilePath$Path"
+    },
     {
       "name": "file.path.image",
       "type": "java.lang.String",
@@ -304,6 +324,16 @@
       "type": "java.lang.String",
       "sourceType": "com.malk.server.common.FilePath$Path"
     },
+    {
+      "name": "file.path.tmp",
+      "type": "java.lang.String",
+      "sourceType": "com.malk.server.common.FilePath$Path"
+    },
+    {
+      "name": "file.source.fonts",
+      "type": "java.lang.String",
+      "sourceType": "com.malk.server.common.FilePath$Source"
+    },
     {
       "name": "file.source.fonts",
       "type": "java.lang.String",

+ 1 - 0
pom.xml

@@ -19,6 +19,7 @@
         <module>mjava-xiding</module>
         <module>mjava-shanghaishiwei</module>
         <module>mjava-guyuan</module>
+        <module>mjava-minjiaoyuan</module>
     </modules>
     <packaging>pom</packaging>