南大三十年教职工疗休养
This commit is contained in:
@@ -45,4 +45,12 @@ public interface SysDataUserPullService extends BaseService<Sys_user_source> {
|
||||
* @return 同步过程统计信息
|
||||
*/
|
||||
NutMap syncTeacherMobile();
|
||||
|
||||
/**
|
||||
* 根据工号逐个调用数据中心手机号接口,并按工号同步到 sys_user.mobile。
|
||||
*
|
||||
* @param jobNos 工号集合
|
||||
* @return 同步过程统计信息,包含工号手机号映射
|
||||
*/
|
||||
NutMap syncTeacherMobileByJobNos(List<String> jobNos);
|
||||
}
|
||||
|
||||
@@ -411,19 +411,81 @@ public class SysDataUserPullServiceImpl extends BaseServiceImpl<Sys_user_source>
|
||||
@Override
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public NutMap syncTeacherMobile() {
|
||||
Sql sql = Sqls.create("SELECT loginname FROM sys_user WHERE loginname IS NOT NULL AND loginname <> ''");
|
||||
sql.setCallback(Sqls.callback.strList());
|
||||
dao().execute(sql);
|
||||
List<String> jobNos = sql.getList(String.class);
|
||||
return syncTeacherMobileByJobNos(jobNos);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据传入工号逐个调用手机号接口,接口分页参数保持原有 pageNum/pageSize,仅替换 gh 查询条件。
|
||||
*/
|
||||
@Override
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
public NutMap syncTeacherMobileByJobNos(List<String> jobNos) {
|
||||
List<String> distinctJobNos = jobNos == null ? Collections.emptyList() : jobNos.stream()
|
||||
.map(StrUtil::trimToEmpty)
|
||||
.filter(StrUtil::isNotBlank)
|
||||
.distinct()
|
||||
.toList();
|
||||
if (distinctJobNos.isEmpty()) {
|
||||
return NutMap.NEW()
|
||||
.addv("total", 0)
|
||||
.addv("pages", 0)
|
||||
.addv("requestUserCount", 0)
|
||||
.addv("pulledCount", 0)
|
||||
.addv("validMobileCount", 0)
|
||||
.addv("matchedUserCount", 0)
|
||||
.addv("updatedUserCount", 0)
|
||||
.addv("mobileMap", Collections.emptyMap())
|
||||
.addv("failedJobNos", Collections.emptyList());
|
||||
}
|
||||
|
||||
DataCenterProperties.Credential credential = dataCenterProperties.credential(TEACHER_MOBILE_CONFIG_KEY);
|
||||
String url = credential.getUrl();
|
||||
String token = credential.getToken();
|
||||
log.info("教职工手机号同步开始:url={}, tokenReady={}", url, StrUtil.isNotBlank(token));
|
||||
log.info("教职工手机号同步开始:url={}, tokenReady={}, requestUserCount={}", url, StrUtil.isNotBlank(token), distinctJobNos.size());
|
||||
|
||||
List<JSONObject> rawDataList = new ArrayList<>();
|
||||
int pageNum = 1;
|
||||
int pageSize = TEACHER_MOBILE_PAGE_SIZE;
|
||||
int total = 0;
|
||||
List<String> failedJobNos = new ArrayList<>();
|
||||
for (String jobNo : distinctJobNos) {
|
||||
try {
|
||||
rawDataList.addAll(requestTeacherMobileByJobNo(url, token, jobNo, pageSize));
|
||||
} catch (Exception e) {
|
||||
failedJobNos.add(jobNo);
|
||||
log.warn("教职工手机号单人工号拉取失败:jobNo={}, msg={}", jobNo, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, String> mobileMap = collectTeacherMobileMap(rawDataList);
|
||||
NutMap updateResult = updateTeacherMobile(mobileMap);
|
||||
NutMap result = NutMap.NEW()
|
||||
.addv("total", distinctJobNos.size())
|
||||
.addv("pages", distinctJobNos.size())
|
||||
.addv("requestUserCount", distinctJobNos.size())
|
||||
.addv("pulledCount", rawDataList.size())
|
||||
.addv("validMobileCount", mobileMap.size())
|
||||
.addv("matchedUserCount", updateResult.getInt("matchedUserCount", 0))
|
||||
.addv("updatedUserCount", updateResult.getInt("updatedUserCount", 0))
|
||||
.addv("mobileMap", mobileMap)
|
||||
.addv("failedJobNos", failedJobNos);
|
||||
log.info("教职工手机号同步完成:{}", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 按单个工号请求手机号接口,保留 pageNum/pageSize 分页参数,避免调用第三方全量分页。
|
||||
*/
|
||||
private List<JSONObject> requestTeacherMobileByJobNo(String url, String token, String jobNo, int pageSize) {
|
||||
List<JSONObject> rawDataList = new ArrayList<>();
|
||||
int pageNum = 1;
|
||||
int pages = 1;
|
||||
int total = 0;
|
||||
do {
|
||||
Map<String, Object> reqBody = buildTeacherMobileRequestBody(pageNum, pageSize);
|
||||
log.info("教职工手机号接口请求:pageNum={}, pageSize={}, body={}", pageNum, pageSize, reqBody);
|
||||
Map<String, Object> reqBody = buildTeacherMobileRequestBody(jobNo, pageNum, pageSize);
|
||||
log.info("教职工手机号接口请求:jobNo={}, pageNum={}, pageSize={}, body={}", jobNo, pageNum, pageSize, reqBody);
|
||||
|
||||
HttpRequest httpRequest = HttpUtil.createPost(url);
|
||||
httpRequest.header(Header.CONTENT_TYPE, "application/json");
|
||||
@@ -431,7 +493,7 @@ public class SysDataUserPullServiceImpl extends BaseServiceImpl<Sys_user_source>
|
||||
httpRequest.body(JSONUtil.toJsonStr(reqBody));
|
||||
|
||||
String resBody = httpRequest.execute().body();
|
||||
log.info("教职工手机号接口返回:pageNum={}, response={}", pageNum, resBody);
|
||||
log.info("教职工手机号接口返回:jobNo={}, pageNum={}, response={}", jobNo, pageNum, resBody);
|
||||
JSONObject resp = JSONUtil.parseObj(resBody);
|
||||
if (!"0".equals(resp.getStr("code"))) {
|
||||
throw new BaseException("获取教职工手机号失败,错误码: " + resp.getStr("code") + ";错误原因:" + resp.getStr("msg"));
|
||||
@@ -450,31 +512,20 @@ public class SysDataUserPullServiceImpl extends BaseServiceImpl<Sys_user_source>
|
||||
if (CollUtil.isNotEmpty(records)) {
|
||||
rawDataList.addAll(records.stream().map(v -> (JSONObject) v).toList());
|
||||
}
|
||||
log.info("教职工手机号拉取进度:pageNum={}, pages={}, total={}, pulled={}",
|
||||
pageNum, pages, total, rawDataList.size());
|
||||
log.info("教职工手机号单人工号拉取进度:jobNo={}, pageNum={}, pages={}, total={}, pulled={}",
|
||||
jobNo, pageNum, pages, total, rawDataList.size());
|
||||
pageNum++;
|
||||
} while (pageNum <= Math.max(pages, 1));
|
||||
|
||||
Map<String, String> mobileMap = collectTeacherMobileMap(rawDataList);
|
||||
NutMap updateResult = updateTeacherMobile(mobileMap);
|
||||
NutMap result = NutMap.NEW()
|
||||
.addv("total", total)
|
||||
.addv("pages", pages)
|
||||
.addv("pulledCount", rawDataList.size())
|
||||
.addv("validMobileCount", mobileMap.size())
|
||||
.addv("matchedUserCount", updateResult.getInt("matchedUserCount", 0))
|
||||
.addv("updatedUserCount", updateResult.getInt("updatedUserCount", 0));
|
||||
log.info("教职工手机号同步完成:{}", result);
|
||||
return result;
|
||||
return rawDataList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 组装手机号接口分页请求体,uid、gh、sjh 为空时表示全量分页拉取。
|
||||
* 组装手机号接口分页请求体,uid 和 sjh 保持空值,gh 使用当前待查询工号。
|
||||
*/
|
||||
private Map<String, Object> buildTeacherMobileRequestBody(int pageNum, int pageSize) {
|
||||
private Map<String, Object> buildTeacherMobileRequestBody(String jobNo, int pageNum, int pageSize) {
|
||||
Map<String, Object> reqBody = new LinkedHashMap<>();
|
||||
reqBody.put("uid", null);
|
||||
reqBody.put("gh", null);
|
||||
reqBody.put("gh", jobNo);
|
||||
reqBody.put("sjh", null);
|
||||
reqBody.put("pageNum", pageNum);
|
||||
reqBody.put("pageSize", pageSize);
|
||||
|
||||
+109
@@ -19,6 +19,7 @@ import com.budwk.app.flow.enums.ProcessInstanceStateEnum;
|
||||
import com.budwk.app.sys.enums.SysFileEngineTypeEnum;
|
||||
import com.budwk.app.sys.models.Sys_file;
|
||||
import com.budwk.app.sys.models.Sys_union;
|
||||
import com.budwk.app.sys.services.SysDataUserPullService;
|
||||
import com.budwk.app.sys.services.SysFileService;
|
||||
import com.budwk.app.sys.utils.SysFileMinIoUtil;
|
||||
import com.budwk.app.sys.views.View_user;
|
||||
@@ -131,6 +132,9 @@ public class ThirtyTeachTourLedgerController {
|
||||
@Inject
|
||||
private SysFileService sysFileService;
|
||||
|
||||
@Inject
|
||||
private SysDataUserPullService sysUserPullService;
|
||||
|
||||
@At("")
|
||||
@Ok("beetl:/platform/zhgh/dayofficework/ThirtyTeachTour/ledger/index.html")
|
||||
@SaCheckPermission("thirtyTeachTour.ledger")
|
||||
@@ -297,6 +301,111 @@ public class ThirtyTeachTourLedgerController {
|
||||
return Result.success();
|
||||
}
|
||||
|
||||
@At
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
@SaCheckPermission("thirtyTeachTour.ledger")
|
||||
@SLog(type = "tour", tag = "疗休养台账", msg = "获取台账人员手机号")
|
||||
public Result syncMobile(@Param("ids") String ids, Integer startYear, Integer endYear, String keyword, String unionId, String lineId,
|
||||
String travelPeriod, String lineType, Boolean directFamilyOnly, Boolean overCostOnly) {
|
||||
try {
|
||||
List<String> idList = StrUtil.isBlank(ids) ? Collections.emptyList() : Json.fromJsonAsList(String.class, ids);
|
||||
List<NutMap> ledgers = queryLedgerMobileTargets(idList, startYear, endYear, keyword, unionId, lineId, travelPeriod,
|
||||
lineType, directFamilyOnly, overCostOnly);
|
||||
List<String> jobNos = ledgers.stream()
|
||||
.map(row -> row.getString("jobNo", ""))
|
||||
.filter(StrUtil::isNotBlank)
|
||||
.distinct()
|
||||
.toList();
|
||||
if (jobNos.isEmpty()) {
|
||||
return Result.error("当前台账范围内没有可获取手机号的人员");
|
||||
}
|
||||
NutMap syncResult = sysUserPullService.syncTeacherMobileByJobNos(jobNos);
|
||||
int ledgerUpdatedCount = updateLedgerMobileBySyncResult(ledgers, syncResult);
|
||||
syncResult.put("ledgerCount", ledgers.size());
|
||||
syncResult.put("ledgerUpdatedCount", ledgerUpdatedCount);
|
||||
return Result.success(syncResult);
|
||||
} catch (Exception e) {
|
||||
return Result.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询本次需要获取手机号的台账人员;勾选时按台账ID取数,未勾选时复用页面当前筛选条件取数。
|
||||
*/
|
||||
private List<NutMap> queryLedgerMobileTargets(List<String> idList, Integer startYear, Integer endYear, String keyword, String unionId,
|
||||
String lineId, String travelPeriod, String lineType, Boolean directFamilyOnly,
|
||||
Boolean overCostOnly) {
|
||||
Cnd cnd;
|
||||
if (idList != null && !idList.isEmpty()) {
|
||||
cnd = Cnd.NEW();
|
||||
cnd.and("t.delFlag", "=", false);
|
||||
cnd.and("t.id", "in", idList);
|
||||
cnd.andEX("t.unionId", "=", resolveLedgerUnionId(null));
|
||||
appendApprovedWorkflowFilter(cnd);
|
||||
} else {
|
||||
cnd = buildQueryCnd(startYear, endYear, keyword, unionId, lineId, travelPeriod, lineType, directFamilyOnly, overCostOnly);
|
||||
}
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT
|
||||
t.id,
|
||||
t.jobNo,
|
||||
t.mobile
|
||||
FROM thirty_teach_tour_ledger t
|
||||
LEFT JOIN wf_process_instance ins ON ins.businessNo = t.id
|
||||
LEFT JOIN thirty_teach_tour_matter m ON m.id = t.matterId AND m.delFlag = 0
|
||||
LEFT JOIN thirty_teach_tour_line l ON l.id = t.lineId AND l.delFlag = 0
|
||||
LEFT JOIN thirty_teach_tour_ledger_direct_relative dr ON dr.ledgerId = t.id AND dr.delFlag = 0
|
||||
LEFT JOIN vw_user vu ON vu.loginname = t.jobNo
|
||||
LEFT JOIN (
|
||||
SELECT
|
||||
`year`,
|
||||
lineId,
|
||||
GROUP_CONCAT(
|
||||
DISTINCT CASE
|
||||
WHEN IFNULL(travelStartTime, '') <> '' AND IFNULL(travelEndTime, '') <> ''
|
||||
THEN CONCAT(travelStartTime, ' 至 ', travelEndTime)
|
||||
ELSE NULL
|
||||
END
|
||||
ORDER BY travelStartTime ASC
|
||||
SEPARATOR ';'
|
||||
) AS travelPeriod
|
||||
FROM thirty_teach_tour_matter
|
||||
WHERE delFlag = 0
|
||||
AND lineId IS NOT NULL
|
||||
AND lineId <> ''
|
||||
GROUP BY `year`, lineId
|
||||
) tp ON (t.matterId IS NULL OR t.matterId = '') AND tp.`year` = t.`year` AND tp.lineId = t.lineId
|
||||
$condition
|
||||
GROUP BY t.id
|
||||
""");
|
||||
sql.setCondition(cnd);
|
||||
sql.setCallback(Sqls.callback.maps());
|
||||
tourLedgerService.dao().execute(sql);
|
||||
return sql.getList(NutMap.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将手机号同步结果回写到当前台账范围内,保证台账列表刷新后展示最新手机号。
|
||||
*/
|
||||
private int updateLedgerMobileBySyncResult(List<NutMap> ledgers, NutMap syncResult) {
|
||||
if (ledgers == null || ledgers.isEmpty() || syncResult == null || !(syncResult.get("mobileMap") instanceof Map)) {
|
||||
return 0;
|
||||
}
|
||||
Map<?, ?> mobileMap = (Map<?, ?>) syncResult.get("mobileMap");
|
||||
int updatedCount = 0;
|
||||
for (NutMap ledger : ledgers) {
|
||||
String jobNo = ledger.getString("jobNo", "");
|
||||
Object mobileValue = mobileMap.get(jobNo);
|
||||
String newMobile = mobileValue == null ? "" : String.valueOf(mobileValue);
|
||||
if (StrUtil.isBlank(newMobile) || StrUtil.equals(newMobile, ledger.getString("mobile", ""))) {
|
||||
continue;
|
||||
}
|
||||
updatedCount += tourLedgerService.dao().update(ThirtyTeachTourLedger.class,
|
||||
Chain.make("mobile", newMobile), Cnd.where("id", "=", ledger.getString("id", "")));
|
||||
}
|
||||
return updatedCount;
|
||||
}
|
||||
|
||||
@At
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
@SaCheckPermission("thirtyTeachTour.ledger")
|
||||
|
||||
+29
@@ -5,8 +5,11 @@ import cn.dev33.satoken.annotation.SaMode;
|
||||
import cn.hutool.core.util.DesensitizedUtil;
|
||||
import com.alibaba.excel.EasyExcel;
|
||||
import com.budwk.app.base.annotation.SLog;
|
||||
import com.budwk.app.base.constant.RoleConstant;
|
||||
import com.budwk.app.base.page.Pagination;
|
||||
import com.budwk.app.base.result.Result;
|
||||
import com.budwk.app.sys.services.SysDataUserPullService;
|
||||
import com.budwk.app.web.commons.auth.utils.AuthUtil;
|
||||
import com.budwk.app.zhgh.staffmanage.member.models.MemberHistory;
|
||||
import com.budwk.app.zhgh.staffmanage.member.param.pageform.MemberInfoPageForm;
|
||||
import com.budwk.app.zhgh.staffmanage.member.service.MemberInfoService;
|
||||
@@ -30,6 +33,7 @@ import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @version 1.0
|
||||
@@ -47,6 +51,9 @@ public class MemberInfoGroupController {
|
||||
@Inject
|
||||
private MemberInfoService memberInfoService;
|
||||
|
||||
@Inject
|
||||
private SysDataUserPullService sysUserPullService;
|
||||
|
||||
@At("")
|
||||
@Ok("beetl:/platform/zhgh/staffmanage/member/info/group/index.html")
|
||||
@SaCheckPermission("member.info.group")
|
||||
@@ -79,6 +86,28 @@ public class MemberInfoGroupController {
|
||||
return Result.success(memberInfoService.dao().count(MemberHistory.class, Cnd.where("year", "=", year)));
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("member.info.group")
|
||||
@Aop(TransAop.READ_COMMITTED)
|
||||
@SLog(tag = "会员档案管理", msg = "获取会员手机号")
|
||||
public Result syncMobile() {
|
||||
try {
|
||||
if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) {
|
||||
return Result.error("当前用户无权获取会员手机号");
|
||||
}
|
||||
List<String> jobNos = memberInfoService.queryRandomBlankMobileMemberJobNos(500);
|
||||
if (jobNos.isEmpty()) {
|
||||
return Result.error("当前没有手机号为空的会员");
|
||||
}
|
||||
NutMap result = sysUserPullService.syncTeacherMobileByJobNos(jobNos);
|
||||
result.put("sampleCount", jobNos.size());
|
||||
return Result.success(result);
|
||||
} catch (Exception e) {
|
||||
log.error("会员手机号获取失败", e);
|
||||
return Result.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@At
|
||||
@SaCheckPermission("member.info.group")
|
||||
|
||||
@@ -68,4 +68,12 @@ public interface MemberInfoService extends BaseService<Sys_user> {
|
||||
* @param isFlag 是否清空更新
|
||||
*/
|
||||
NutMap handlingMemberImport(TempFile file, Boolean isFlag);
|
||||
|
||||
/**
|
||||
* 随机查询当前权限范围内手机号为空的会员工号。
|
||||
*
|
||||
* @param limit 查询人数上限
|
||||
* @return 会员工号集合
|
||||
*/
|
||||
List<String> queryRandomBlankMobileMemberJobNos(int limit);
|
||||
}
|
||||
|
||||
+28
@@ -113,6 +113,34 @@ public class MemberInfoServiceImpl extends BaseServiceImpl<Sys_user> implements
|
||||
return sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* 随机查询当前权限范围内手机号为空的会员工号,供批量补手机号功能使用。
|
||||
*/
|
||||
@Override
|
||||
public List<String> queryRandomBlankMobileMemberJobNos(int limit) {
|
||||
Cnd cnd = Cnd.NEW();
|
||||
cnd.and("u.member", "=", true);
|
||||
cnd.and("u.loginname", "<>", "");
|
||||
cnd.and(new SqlExpressionGroup()
|
||||
.or("u.mobile", "IS", null)
|
||||
.or("u.mobile", "=", ""));
|
||||
if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) {
|
||||
cnd.and("u.unionId", "=", SecurityUtil.getUnionId());
|
||||
}
|
||||
Sql sql = Sqls.create("""
|
||||
SELECT DISTINCT u.loginname
|
||||
FROM vw_user u
|
||||
$condition
|
||||
ORDER BY RAND()
|
||||
LIMIT @limit
|
||||
""");
|
||||
sql.setCondition(cnd);
|
||||
sql.setParam("limit", limit);
|
||||
sql.setCallback(Sqls.callback.strList());
|
||||
dao().execute(sql);
|
||||
return sql.getList(String.class);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Sql getMemberHistorySql(MemberInfoPageForm pageForm) {
|
||||
|
||||
Reference in New Issue
Block a user