信用监管对接统一监管门户的待办事项接口

This commit is contained in:
zhouxy 2026-05-22 14:28:45 +08:00
parent 4dc403b05c
commit 0d6465fb0f
21 changed files with 834 additions and 1 deletions

View File

@ -36,6 +36,7 @@ import com.chinaweal.aiccs.common.util.StringUtils;
import com.chinaweal.aiccs.common.util.UuidUtil;
import com.chinaweal.aiccs.crgs.system.entity.TaskList;
import com.chinaweal.aiccs.door.service.ITUserportalService;
import com.chinaweal.aiccs.door.service.IJgmhPortalTodoService;
import com.chinaweal.aiccs.org.entity.OrgUnits;
import com.chinaweal.aiccs.org.mapper.AicorgMapper;
import com.chinaweal.aiccs.org.mapper.TUsersMapper;
@ -65,6 +66,15 @@ import java.util.stream.Collectors;
@Service
public class TSTaskListServiceImpl extends BaseServiceImpl<TSTaskListMapper, TSTaskList> implements TSTaskListService {
/** 信用修复业务类型 */
private static final List<String> CREDIT_REPAIR_BUSTYPES = Arrays.asList(
BaseDataConstant.EXPTLIST_TYPE_REMOVE,
BaseDataConstant.EXPTLIST_TYPE_INDIVIDUAL_RESTORE,
BaseDataConstant.EXPTLIST_TYPE_FARMER_REMOVE,
BaseDataConstant.CREDIT_REPAIR_ILLEGAL_BIZ,
BaseDataConstant.BUSINESS_TYPE_REM_PUNISH
);
@Autowired
private UuidUtil uuidUtil;
@ -89,6 +99,9 @@ public class TSTaskListServiceImpl extends BaseServiceImpl<TSTaskListMapper, TST
@Resource
private ITUserportalService itUserportalService;
@Resource
private IJgmhPortalTodoService jgmhPortalTodoService;
@Resource
private TREntPriseTypeService entPriseTypeService;
@ -139,6 +152,8 @@ public class TSTaskListServiceImpl extends BaseServiceImpl<TSTaskListMapper, TST
itUserportalService.doorTaskSend(taskListModel);
// 信创门户待办推送
itUserportalService.doorTaskSend_XC(taskListModel);
// 统一监管门户待办推送记录创建
jgmhPortalTodoService.createPushRecord(taskListModel);
return taskListModel.getTasklistid();
}
@ -333,6 +348,10 @@ public class TSTaskListServiceImpl extends BaseServiceImpl<TSTaskListMapper, TST
taskListModel.setIssignon(BaseDataConstant.YES);
taskListModel.setAcceptgroupid("");
taskListModel.setLauptime(resultMap.getLaupTime());
// 统一监管门户待办标记为已办(仅信用修复业务类型)
if (CREDIT_REPAIR_BUSTYPES.contains(taskListModel.getBustype())) {
jgmhPortalTodoService.onHandleTodo(taskListModel.getTasklistid());
}
}
}
@ -354,6 +373,8 @@ public class TSTaskListServiceImpl extends BaseServiceImpl<TSTaskListMapper, TST
taskListModel.setLinkname(resultMap.getWorkflowName());
save(taskListModel);
taskListModel = baseMapper.selectByWorkflowID(workflowid);
// 统一监管门户待办推送记录创建
jgmhPortalTodoService.createPushRecord(taskListModel);
return taskListModel.getTasklistid();
}

View File

@ -0,0 +1,73 @@
package com.chinaweal.aiccs.door.controller;
import com.chinaweal.aiccs.door.dto.JgmhDebugPushResult;
import com.chinaweal.aiccs.door.service.IJgmhPortalTodoService;
import com.chinaweal.youfool.framework.springboot.rest.RestResult;
import com.chinaweal.youfool.framework.springboot.rest.ResultCode;
import com.github.xiaoymin.knife4j.annotations.ApiSort;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
* 统一监管门户待办对接 调试控制器
*
* 仅用于开发联调与线上排障传入 tasklistid 即可单独触发一笔待办推送
*
* 调用地址
* GET /aiccs-api/door/jgmh-todo/debug/push?tasklistid={tasklistid}
*
* 注意事项
* 1. 需要登录态Shiro JWT 鉴权
* 2. 受配置开关 jgmhDoor.debugEnabled 控制生产默认关闭
* 3. 不写入推送记录表仅同步调用门户接口
* 4. 绕过三重过滤不校验 origin/busstatus/bustype
*
* @author chinaweal
*/
@Api(tags = "统一监管门户对接-调试接口")
@ApiSort(99)
@RestController
@RequestMapping("/door/jgmh-todo")
@Slf4j
public class JgmhPortalTodoDebugController {
@Value("${jgmhDoor.debugEnabled:false}")
private boolean debugEnabled;
@Resource
private IJgmhPortalTodoService jgmhPortalTodoService;
/**
* 单笔调试推送
*
* 完整调用地址
* GET http://{host}:8086/aiccs-api/door/jgmh-todo/debug/push?tasklistid=xxx
*/
@ApiOperation("【调试】根据 tasklistid 单独推送一笔待办到统一监管门户")
@GetMapping("/debug/push")
public RestResult<JgmhDebugPushResult> debugPushSingle(
@ApiParam(value = "tstasklist 主键", required = true)
@RequestParam("tasklistid") String tasklistid) {
log.info("【调试推送】收到请求tasklistid={}", tasklistid);
if (!debugEnabled) {
log.warn("【调试推送】调试接口未开启,请检查配置 jgmhDoor.debugEnabled");
return RestResult.error(ResultCode.INTERFACE_FORBID_VISIT,
"调试接口未开启,请联系管理员开启 jgmhDoor.debugEnabled");
}
JgmhDebugPushResult result = jgmhPortalTodoService.debugPushSingle(tasklistid);
log.info("【调试推送】完成tasklistid={}, success={}, durationMs={}",
tasklistid, result.getSuccess(), result.getDurationMs());
return RestResult.ok(result);
}
}

View File

@ -0,0 +1,42 @@
package com.chinaweal.aiccs.door.dto;
import lombok.Data;
import lombok.experimental.Accessors;
/**
* 统一监管门户待办对接 调试推送结果
*
* 用于 JgmhPortalTodoDebugController.debugPushSingle 返回详细的调用过程信息
* 便于开发联调排查请求/响应token耗时等数据
*/
@Data
@Accessors(chain = true)
public class JgmhDebugPushResult {
/** 是否成功true=门户HTTP调用成功门户业务返回需自行判断 responseBody */
private Boolean success;
/** 业务说明(每个环节的概要描述) */
private String message;
/** 使用的 token脱敏后前4位 + **** + 后4位 */
private String token;
/** 实际发送给门户接口的请求体 JSON */
private String requestBody;
/** 门户接口返回的原始响应 */
private String responseBody;
/** HTTP 状态码 */
private Integer httpStatus;
/** 接口调用耗时(毫秒) */
private Long durationMs;
/** 组装后的待办事项预览JgmhTodoItemDto */
private Object todoItemPreview;
/** tstasklist 关键字段预览 */
private Object taskListPreview;
}

View File

@ -0,0 +1,60 @@
package com.chinaweal.aiccs.door.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.chinaweal.youfool.framework.springboot.json.LocalDateTimeStringSerializer;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import lombok.Data;
import lombok.experimental.Accessors;
import java.time.LocalDateTime;
@Data
@Accessors(chain = true)
@TableName("PORTAL_TODO_PUSH_RECORD")
public class PortalTodoPushRecord {
@TableId(value = "ID", type = IdType.ASSIGN_UUID)
private String id;
@TableField("TASKLISTID")
private String tasklistid;
@TableField("BUSTYPE")
private String bustype;
@TableField("DBSXID")
private String dbsxid;
@TableField("DBSXMC")
private String dbsxmc;
@TableField("DBSXZT")
private Integer dbsxzt;
@TableField("USERSID")
private String usersid;
@TableField("PUSHSTATUS")
private String pushstatus;
@TableField("PUSHMESSAGE")
private String pushmessage;
@TableField("PUSHCOUNT")
private Integer pushcount;
@TableField("LASTPUSHTIME")
@JsonSerialize(using = LocalDateTimeStringSerializer.class)
private LocalDateTime lastpushtime;
@TableField("CREATETIME")
@JsonSerialize(using = LocalDateTimeStringSerializer.class)
private LocalDateTime createtime;
@TableField("UPDATETIME")
@JsonSerialize(using = LocalDateTimeStringSerializer.class)
private LocalDateTime updatetime;
}

View File

@ -0,0 +1,8 @@
package com.chinaweal.aiccs.door.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.chinaweal.aiccs.door.entity.PortalTodoPushRecord;
public interface PortalTodoPushRecordMapper extends BaseMapper<PortalTodoPushRecord> {
}

View File

@ -0,0 +1,37 @@
package com.chinaweal.aiccs.door.service;
import com.chinaweal.aiccs.aiccs.business.entity.TSTaskList;
import com.chinaweal.aiccs.door.dto.JgmhDebugPushResult;
public interface IJgmhPortalTodoService {
/**
* 创建待推送记录工作流启动时调用
* 仅限外网申请 + 待受理 + 信用修复业务
*/
void createPushRecord(TSTaskList taskListModel);
/**
* 批量推送待办事项定时任务调用
*/
void pushPendingTodoItems();
/**
* 用户点击"办理"后调用将待办标记为已办
*/
void onHandleTodo(String tasklistid);
/**
* 调试用单笔推送指定 tasklistid 对应的待办数据到统一监管门户
*
* - 绕过三重过滤不校验 bustype/origin/busstatus可推送任意一笔待办
* - 同步直接调用门户接口不走定时任务
* - 不写入推送记录表不污染生产数据
* - 返回详细的调试信息请求体响应体耗时等
*
* 仅用于开发联调和线上排障不应在业务流程中使用
*
* @param tasklistid tstasklist 主键
* @return 调试结果详情
*/
JgmhDebugPushResult debugPushSingle(String tasklistid);
}

View File

@ -0,0 +1,8 @@
package com.chinaweal.aiccs.door.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.chinaweal.aiccs.door.entity.PortalTodoPushRecord;
public interface PortalTodoPushRecordService extends IService<PortalTodoPushRecord> {
}

View File

@ -0,0 +1,404 @@
package com.chinaweal.aiccs.door.service.impl;
import com.alibaba.fastjson.JSON;
import com.chinaweal.aiccs.aiccs.business.entity.TSTaskList;
import com.chinaweal.aiccs.aiccs.business.service.TSTaskListService;
import com.chinaweal.aiccs.common.constant.BaseDataConstant;
import com.chinaweal.aiccs.door.dto.JgmhDebugPushResult;
import com.chinaweal.aiccs.door.entity.PortalTodoPushRecord;
import com.chinaweal.aiccs.door.service.IJgmhPortalTodoService;
import com.chinaweal.aiccs.door.service.PortalTodoPushRecordService;
import com.chinaweal.aiccs.outside.api.JgmhDoorApi;
import com.chinaweal.aiccs.outside.dto.JgmhTodoItemDto;
import com.chinaweal.aiccs.outside.dto.JgmhTodoRequestDto;
import com.chinaweal.aiccs.org.entity.TUsers;
import com.chinaweal.aiccs.org.service.TUsersService;
import com.chinaweal.aiccs.redis.RedisService;
import com.chinaweal.youfool.framework.springboot.exception.custom.BusinessException;
import com.dtflys.forest.http.ForestResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@Service
@Slf4j
public class JgmhPortalTodoServiceImpl implements IJgmhPortalTodoService {
@Value("${jgmhDoor.enableTask}")
private boolean enableTask;
@Value("${jgmhDoor.appId}")
private String appId;
@Value("${jgmhDoor.redirectUrl}")
private String redirectUrl;
@Value("${jgmhDoor.mobileRedirectUrl:}")
private String mobileRedirectUrl;
@Resource
private JgmhDoorApi jgmhDoorApi;
@Resource
private PortalTodoPushRecordService pushRecordService;
@Resource
private TSTaskListService taskListService;
@Resource
private TUsersService tUsersService;
@Resource
private RedisService redisService;
private static final String TOKEN_CACHE_KEY = "JGMH_DOOR_TOKEN";
/**
* 信用修复业务类型白名单
* TSTaskListMapper.xml repairTaskQuery 的过滤条件保持一致
*/
private static final List<String> CREDIT_REPAIR_BUSTYPES = Arrays.asList(
BaseDataConstant.EXPTLIST_TYPE_REMOVE, // "7" 企业经营异常名录信用修复
BaseDataConstant.EXPTLIST_TYPE_INDIVIDUAL_RESTORE, // "12" 个体户经营异常名录信用修复
BaseDataConstant.EXPTLIST_TYPE_FARMER_REMOVE, // "14" 农专社经营异常名录信用修复
BaseDataConstant.CREDIT_REPAIR_ILLEGAL_BIZ, // "33" 严重违法失信信用修复
BaseDataConstant.BUSINESS_TYPE_REM_PUNISH // "27" 行政处罚信用修复
);
/** 外网申请标识 */
private static final String ORIGIN_OUTER = "1";
/** 待受理状态 */
private static final String BUSSTATUS_TOSIGN = BaseDataConstant.BUSINESS_STATUS_TOSIGN; // "-1"
/**
* 获取token带Redis缓存有效期2小时提前刷新
*/
public String getToken() {
String token = redisService.get(TOKEN_CACHE_KEY);
if (StringUtils.isNotBlank(token)) {
return token;
}
ForestResponse<String> response = jgmhDoorApi.getToken();
if (response.isSuccess()) {
token = response.getResult().trim();
redisService.set(TOKEN_CACHE_KEY, token, 7000);
return token;
}
throw new BusinessException("获取统一监管门户token失败: " + response.getResult());
}
/**
* 获取本地用户对应的统一监管门户用户ID
* 映射链路signuserid t_users.IMSUSERCODE USERSID
*/
private String getPortalUserId(String localUserId) {
TUsers tUser = tUsersService.getById(localUserId);
if (tUser == null || StringUtils.isBlank(tUser.getImsusercode())) {
return null;
}
return tUser.getImsusercode();
}
/**
* 创建待推送记录工作流启动时调用
*
* 三重过滤条件
* 1. BUSTYPE in ('7','12','14','33','27') 信用修复业务
* 2. ORIGIN = '1' 外网申请
* 3. BUSSTATUS = '-1' 待受理状态
*
* 三个条件必须同时满足任一不满足则跳过
*/
@Override
public void createPushRecord(TSTaskList taskListModel) {
if (!enableTask) return;
// 过滤条件1仅限信用修复业务
if (!CREDIT_REPAIR_BUSTYPES.contains(taskListModel.getBustype())) {
log.debug("统一监管门户待办推送非信用修复业务跳过。tasklistid={}, bustype={}",
taskListModel.getTasklistid(), taskListModel.getBustype());
return;
}
// 过滤条件2仅限外网申请
if (!ORIGIN_OUTER.equals(taskListModel.getOrigin())) {
log.debug("统一监管门户待办推送非外网申请跳过。tasklistid={}, origin={}",
taskListModel.getTasklistid(), taskListModel.getOrigin());
return;
}
// 过滤条件3仅限待受理状态
if (!BUSSTATUS_TOSIGN.equals(taskListModel.getBusstatus())) {
log.debug("统一监管门户待办推送非待受理状态跳过。tasklistid={}, busstatus={}",
taskListModel.getTasklistid(), taskListModel.getBusstatus());
return;
}
// 获取门户用户ID
String portalUserId = getPortalUserId(taskListModel.getSignuserid());
if (portalUserId == null) {
log.info("统一监管门户待办推送用户未关联IMS账号signuserid={}", taskListModel.getSignuserid());
return;
}
// 创建推送记录
// DBSXID 使用 tasklistid因为只有2步且无回退不存在多人共享问题
PortalTodoPushRecord record = new PortalTodoPushRecord();
record.setTasklistid(taskListModel.getTasklistid());
record.setBustype(taskListModel.getBustype());
record.setDbsxid(taskListModel.getTasklistid());
record.setDbsxmc(taskListModel.getBusname());
record.setDbsxzt(1); // 待办
record.setUsersid(portalUserId);
record.setPushstatus("0"); // 待推送
record.setPushcount(0);
record.setCreatetime(LocalDateTime.now());
record.setUpdatetime(LocalDateTime.now());
pushRecordService.save(record);
log.info("统一监管门户待办推送创建推送记录tasklistid={}, bustype={}, usersid={}",
taskListModel.getTasklistid(), taskListModel.getBustype(), portalUserId);
}
/**
* 用户点击"办理"后调用将待办标记为已办
*
* 调用时机TSTaskListServiceImpl.updateWorkFlow() busstatus "-1"待受理变为 "0"在办
* 不直接推送只更新推送记录状态重置为待推送下次定时任务推送状态变更
*/
@Override
public void onHandleTodo(String tasklistid) {
if (!enableTask) return;
PortalTodoPushRecord record = pushRecordService.lambdaQuery()
.eq(PortalTodoPushRecord::getTasklistid, tasklistid)
.eq(PortalTodoPushRecord::getDbsxzt, 1) // 当前是待办状态
.one();
if (record == null) return;
record.setDbsxzt(2); // 已办
record.setPushstatus("0"); // 重置为待推送
record.setUpdatetime(LocalDateTime.now());
pushRecordService.updateById(record);
log.info("统一监管门户待办推送用户点击办理标记为已办tasklistid={}", tasklistid);
}
/**
* 批量推送待办事项定时任务调用
*/
@Override
public void pushPendingTodoItems() {
if (!enableTask) return;
List<PortalTodoPushRecord> pendingRecords = pushRecordService.lambdaQuery()
.in(PortalTodoPushRecord::getPushstatus, "0", "2")
.lt(PortalTodoPushRecord::getPushcount, 3)
.list();
if (pendingRecords.isEmpty()) {
log.info("统一监管门户待办推送:无待推送记录");
return;
}
log.info("统一监管门户待办推送:待推送记录数={}", pendingRecords.size());
String token = getToken();
List<JgmhTodoItemDto> items = new ArrayList<>();
for (PortalTodoPushRecord record : pendingRecords) {
JgmhTodoItemDto item = buildTodoItem(record);
if (item != null) {
items.add(item);
}
}
if (items.isEmpty()) {
log.info("统一监管门户待办推送:无有效推送数据");
return;
}
JgmhTodoRequestDto requestDto = new JgmhTodoRequestDto();
requestDto.setData(items);
try {
ForestResponse<String> response = jgmhDoorApi.pushTodoItems(token, requestDto);
if (response.isSuccess()) {
for (PortalTodoPushRecord record : pendingRecords) {
record.setPushstatus("1");
record.setPushcount(record.getPushcount() + 1);
record.setLastpushtime(LocalDateTime.now());
}
log.info("统一监管门户待办推送:推送成功,记录数={}", pendingRecords.size());
} else {
markAsFailed(pendingRecords, response.getResult());
log.error("统一监管门户待办推送:推送失败,响应={}", response.getResult());
}
} catch (Exception e) {
markAsFailed(pendingRecords, e.getMessage());
log.error("统一监管门户待办推送:推送异常", e);
}
pushRecordService.updateBatchById(pendingRecords);
}
/**
* 组装推送数据项
*/
private JgmhTodoItemDto buildTodoItem(PortalTodoPushRecord record) {
TSTaskList taskList = taskListService.getById(record.getTasklistid());
JgmhTodoItemDto item = new JgmhTodoItemDto();
item.setDBSXID(record.getDbsxid());
item.setDBSXMC(record.getDbsxmc());
if (taskList != null) {
item.setXXSM(taskList.getLinkname() + " - " + taskList.getBusname());
item.setCJSJ(formatDateTime(taskList.getSendertime()));
item.setJZSJ(formatDateTime(taskList.getDeadlineDate()));
} else {
record.setPushstatus("2");
record.setPushcount(3);
record.setPushmessage("关联的tstasklist记录不存在");
record.setLastpushtime(LocalDateTime.now());
return null;
}
item.setDBSXZT(record.getDbsxzt());
item.setUSERSID(record.getUsersid());
item.setDBDZURL(redirectUrl);
item.setYDDDBURL(mobileRedirectUrl);
item.setLYXTAPPID(appId);
return item;
}
private void markAsFailed(List<PortalTodoPushRecord> records, String message) {
for (PortalTodoPushRecord record : records) {
record.setPushstatus("2");
record.setPushcount(record.getPushcount() + 1);
record.setPushmessage(message != null && message.length() > 500
? message.substring(0, 500) : message);
record.setLastpushtime(LocalDateTime.now());
}
}
private String formatDateTime(LocalDateTime dateTime) {
if (dateTime == null) return "";
return dateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
}
/**
* 调试用单笔推送指定 tasklistid 对应的待办数据到统一监管门户
*
* - 绕过三重过滤不校验 bustype/origin/busstatus可推送任意一笔待办
* - 同步直接调用门户接口不走定时任务
* - 不写入推送记录表不污染生产数据
* - 返回详细的调试信息请求体响应体耗时等
*/
@Override
public JgmhDebugPushResult debugPushSingle(String tasklistid) {
JgmhDebugPushResult result = new JgmhDebugPushResult();
long startTime = System.currentTimeMillis();
try {
// 1. 校验入参
if (StringUtils.isBlank(tasklistid)) {
return result.setSuccess(false).setMessage("tasklistid 不能为空");
}
// 2. 查询 tstasklist 记录
TSTaskList taskList = taskListService.getById(tasklistid);
if (taskList == null) {
return result.setSuccess(false)
.setMessage("tasklistid=" + tasklistid + " 对应的 tstasklist 记录不存在");
}
result.setTaskListPreview(buildTaskListPreview(taskList));
// 3. 获取门户用户ID
String portalUserId = getPortalUserId(taskList.getSignuserid());
if (portalUserId == null) {
return result.setSuccess(false)
.setMessage("当前 tasklistid 的签收人未关联 IMS 账号无法推送。signuserid="
+ taskList.getSignuserid());
}
// 4. 查询或临时构造推送记录(不写库)
PortalTodoPushRecord record = pushRecordService.lambdaQuery()
.eq(PortalTodoPushRecord::getTasklistid, tasklistid)
.last("LIMIT 1")
.one();
if (record == null) {
record = new PortalTodoPushRecord();
record.setTasklistid(tasklistid);
record.setBustype(taskList.getBustype());
record.setDbsxid(tasklistid);
record.setDbsxmc(taskList.getBusname());
record.setDbsxzt(1); // 默认按"待办"推送
record.setUsersid(portalUserId);
}
// 5. 组装推送数据
JgmhTodoItemDto item = buildTodoItem(record);
if (item == null) {
return result.setSuccess(false).setMessage("组装推送数据失败,请查看日志");
}
result.setTodoItemPreview(item);
// 6. 获取 token脱敏
String token = getToken();
result.setToken(maskToken(token));
// 7. 调用门户接口
JgmhTodoRequestDto requestDto = new JgmhTodoRequestDto();
requestDto.setData(Collections.singletonList(item));
result.setRequestBody(JSON.toJSONString(requestDto));
ForestResponse<String> response = jgmhDoorApi.pushTodoItems(token, requestDto);
result.setHttpStatus(response.getStatusCode());
result.setResponseBody(response.getResult());
if (response.isSuccess()) {
result.setSuccess(true)
.setMessage("HTTP 调用成功,请查看 responseBody 确认门户业务返回");
} else {
result.setSuccess(false)
.setMessage("HTTP 调用失败HTTP=" + response.getStatusCode());
}
} catch (Exception e) {
log.error("调试推送异常tasklistid={}", tasklistid, e);
result.setSuccess(false).setMessage("调试推送异常:" + e.getMessage());
} finally {
result.setDurationMs(System.currentTimeMillis() - startTime);
}
return result;
}
/** Token 脱敏前4位 + **** + 后4位 */
private String maskToken(String token) {
if (StringUtils.isBlank(token) || token.length() <= 8) return "****";
return token.substring(0, 4) + "****" + token.substring(token.length() - 4);
}
/** 提取 tstasklist 关键字段用于调试查看 */
private Map<String, Object> buildTaskListPreview(TSTaskList t) {
Map<String, Object> m = new LinkedHashMap<>();
m.put("tasklistid", t.getTasklistid());
m.put("bustype", t.getBustype());
m.put("busname", t.getBusname());
m.put("origin", t.getOrigin());
m.put("busstatus", t.getBusstatus());
m.put("signuserid", t.getSignuserid());
m.put("linkname", t.getLinkname());
m.put("sendertime", t.getSendertime());
m.put("deadlineDate", t.getDeadlineDate());
return m;
}
}

View File

@ -0,0 +1,14 @@
package com.chinaweal.aiccs.door.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.chinaweal.aiccs.door.entity.PortalTodoPushRecord;
import com.chinaweal.aiccs.door.mapper.PortalTodoPushRecordMapper;
import com.chinaweal.aiccs.door.service.PortalTodoPushRecordService;
import org.springframework.stereotype.Service;
@Service
public class PortalTodoPushRecordServiceImpl
extends ServiceImpl<PortalTodoPushRecordMapper, PortalTodoPushRecord>
implements PortalTodoPushRecordService {
}

View File

@ -0,0 +1,27 @@
package com.chinaweal.aiccs.outside.api;
import com.chinaweal.aiccs.outside.dto.JgmhTodoRequestDto;
import com.dtflys.forest.annotation.*;
import com.dtflys.forest.http.ForestResponse;
/**
* 统一监管门户 Forest API接口
*/
@BaseRequest(baseURL = "${jgmhDoorBaseUrl}")
public interface JgmhDoorApi {
/**
* 获取token
* GET /zt/api/auth/token?key={appid}
* Header: DI-Authorization: {app_secret}
*/
@GetRequest(url = "/zt/api/auth/token?key={appId}", headers = "DI-Authorization:${jgmhDoor.appSecret}")
ForestResponse<String> getToken();
/**
* 推送待办事项
* POST /zt/api/dataservice/v1/tyjgmhXZdbsx?token={token}
*/
@PostRequest(url = "/zt/api/dataservice/v1/tyjgmhXZdbsx?token={token}", contentType = "application/json")
ForestResponse<String> pushTodoItems(@Var("token") String token, @JSONBody JgmhTodoRequestDto requestDto);
}

View File

@ -0,0 +1,40 @@
package com.chinaweal.aiccs.outside.dto;
import lombok.Data;
/**
* 统一监管门户待办事项推送DTO
*/
@Data
public class JgmhTodoItemDto {
/** 待办事项ID */
private String DBSXID;
/** 待办事项名称 */
private String DBSXMC;
/** 详细说明 */
private String XXSM;
/** 待办事项状态(1待办 2已办) */
private Integer DBSXZT;
/** 门户用户ID */
private String USERSID;
/** PC端待办跳转地址 */
private String DBDZURL;
/** 移动端待办跳转地址 */
private String YDDDBURL;
/** 创建时间 格式: yyyy-MM-dd HH:mm:ss */
private String CJSJ;
/** 截止时间 格式: yyyy-MM-dd HH:mm:ss */
private String JZSJ;
/** 来源系统APPID */
private String LYXTAPPID;
}

View File

@ -0,0 +1,15 @@
package com.chinaweal.aiccs.outside.dto;
import lombok.Data;
import java.util.List;
/**
* 统一监管门户待办推送请求包装DTO
*/
@Data
public class JgmhTodoRequestDto {
/** 待办事项列表 */
private List<JgmhTodoItemDto> data;
}

View File

@ -0,0 +1,58 @@
package com.chinaweal.aiccs.schedule;
import com.chinaweal.aiccs.door.service.IJgmhPortalTodoService;
import com.chinaweal.aiccs.redis.RedisService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
/**
* 统一监管门户待办推送定时任务
* 每30分钟扫描推送记录表将待推送的记录推送到统一监管门户
*/
@Slf4j
@Configuration
@EnableScheduling
public class JgmhPortalTodoPushScheduled {
private static final String REDIS_LOCK_KEY = "schedule:jgmhPortalTodoPush:lock";
private static final int REDIS_LOCK_TIMEOUT = 30 * 60; // 30分钟
@Autowired
private IJgmhPortalTodoService jgmhPortalTodoService;
@Autowired
private RedisService redisService;
@Scheduled(cron = "${scheduling.cron.jgmhPortalTodoPush:-}")
public void pushTodoItems() {
if (!acquireLock()) {
log.warn("【统一监管门户待办推送任务】上一次执行尚未完成或锁已存在,本次跳过");
return;
}
try {
log.info("【统一监管门户待办推送任务】开始执行");
jgmhPortalTodoService.pushPendingTodoItems();
log.info("【统一监管门户待办推送任务】执行完成");
} catch (Exception e) {
log.error("【统一监管门户待办推送任务】执行异常:{}", e.getMessage(), e);
} finally {
releaseLock();
}
}
private boolean acquireLock() {
if (redisService.exists(REDIS_LOCK_KEY)) {
return false;
}
redisService.set(REDIS_LOCK_KEY, "1", REDIS_LOCK_TIMEOUT);
return true;
}
private void releaseLock() {
redisService.remove(REDIS_LOCK_KEY);
}
}

View File

@ -64,6 +64,7 @@ forest:
moveinDownload: /DownloadTransferApi
doorBaseUrl: http://172.16.52.60
xcDoorBaseUrl: http://10.201.62.2:6888
jgmhDoorBaseUrl: http://10.6.47.11:8088/tyjgmh # 统一监管门户
xcDoorCasUrl: http://10.201.62.2:6889
# 第三方文件上传配置
fileUpload:
@ -158,6 +159,7 @@ scheduling:
staticHqlcusers: 0 30 00 * * ? #定时获取浪潮用户
forceDeregisterNoticeExpired: '-' #拟强制注销公告期满更新定时任务
syncRevokeData: '-' #吊销数据同步任务同步REVOKELIST到E_REVOKE和E_GT_REVOKE表
jgmhPortalTodoPush: '-' #统一监管门户待办推送
ot:
bakCseDownloadPath: /ot/download/case
bakPermitDownloadPath: /ot/download/permit

View File

@ -78,6 +78,7 @@ forest:
moveinDownload: /DownloadTransferApi
doorBaseUrl: http://172.16.52.60
xcDoorBaseUrl: http://10.201.62.2:6888
jgmhDoorBaseUrl: http://10.6.47.11:8088/tyjgmh # 统一监管门户
# 第三方文件上传配置
fileUpload:
testUrl: http://172.26.0.10:9987/test/moveservice/enterprise/uploadfile #测试地址
@ -167,6 +168,7 @@ scheduling:
cancelEntRemove: '0 0 1 * * ?' #注销企业自动移出
syncRevokeData: '0 0 2 * * ?' #吊销数据同步任务同步REVOKELIST到E_REVOKE和E_GT_REVOKE表
anotherListPB: '0 0 22 * * ?' # 个体户移出名单标记另册管理定时任务
jgmhPortalTodoPush: '0 */30 * * * ?' #统一监管门户待办推送每30分钟
ot:
bakCseDownloadPath: /ot/download/case

View File

@ -68,6 +68,7 @@ forest:
moveinDownload: /DownloadTransferApi
doorBaseUrl: http://10.194.188.69
xcDoorBaseUrl: http://10.201.62.82
jgmhDoorBaseUrl: http://10.6.47.11:8088/tyjgmh # 统一监管门户
xcDoorCasUrl: http://10.201.62.81
# 第三方文件上传配置
fileUpload:
@ -145,6 +146,7 @@ scheduling:
moveOutData: '0 58 16 * * ?' #迁出省局数据定时任务
moveInData: '0 17 16 * * ?' #迁入省局数据定时任务
forceDeregisterNoticeExpired: '0 0 1 * * ?' #拟强制注销公告期满更新定时任务
jgmhPortalTodoPush: '0 */30 * * * ?' #统一监管门户待办推送每30分钟
ot:
bakCseDownloadPath: /ot/download/case

View File

@ -84,6 +84,7 @@ forest:
moveinDownload: /DownloadTransferApi
doorBaseUrl: http://10.194.188.69
xcDoorBaseUrl: http://10.201.62.82
jgmhDoorBaseUrl: http://10.6.47.11:8088/tyjgmh # 统一监管门户
xcDoorCasUrl: http://10.201.62.81
# 第三方文件上传配置
fileUpload:
@ -163,6 +164,7 @@ scheduling:
#attachmentUpload: '0 14 20 * * ?' #附件上传定时任务
#moveOutData: '0 58 16 * * ?' #迁出省局数据定时任务
forceDeregisterNoticeExpired: '0 0 1 * * ?' #拟强制注销公告期满更新定时任务
jgmhPortalTodoPush: '0 */30 * * * ?' #统一监管门户待办推送每30分钟
ot:

View File

@ -84,6 +84,7 @@ forest:
moveinDownload: /DownloadTransferApi
doorBaseUrl: http://10.194.188.69
xcDoorBaseUrl: http://10.201.62.82
jgmhDoorBaseUrl: http://10.6.47.11:8088/tyjgmh # 统一监管门户
xcDoorCasUrl: http://10.201.62.81
# 第三方文件上传配置
fileUpload:
@ -163,6 +164,7 @@ scheduling:
moveOutData: '0 30 22 * * ?' #迁出省局数据定时任务
#moveInData: '-' #迁入省局数据定时任务
forceDeregisterNoticeExpired: '0 0 1 * * ?' #拟强制注销公告期满更新定时任务
jgmhPortalTodoPush: '0 */30 * * * ?' #统一监管门户待办推送每30分钟
ot:
bakCseDownloadPath: /ot/download/case

View File

@ -31,7 +31,7 @@ spring:
username: SYSDBA
password: ChinaWeal2025
youfool:
url: jdbc:dm://172.22.80.73:15236?schema=YOUFOOL
url: jdbc:dm://172.22.80.73:15236?schema=SYSDBA
username: SYSDBA
password: ChinaWeal2025
aiceps:
@ -78,6 +78,7 @@ forest:
moveinDownload: /DownloadTransferApi
doorBaseUrl: http://172.16.52.60
xcDoorBaseUrl: http://10.201.62.2:6888
jgmhDoorBaseUrl: http://10.6.47.11:8088/tyjgmh # 统一监管门户
# 第三方文件上传配置
fileUpload:
testUrl: http://172.26.0.10:9987/test/moveservice/enterprise/uploadfile #测试地址
@ -167,6 +168,7 @@ scheduling:
cancelEntRemove: '0 0 1 * * ?' #注销企业自动移出
syncRevokeData: '0 0 2 * * ?' #吊销数据同步任务同步REVOKELIST到E_REVOKE和E_GT_REVOKE表
anotherListPB: '-' # 个体户移出名单标记另册管理定时任务
jgmhPortalTodoPush: '0 */30 * * * ?' #统一监管门户待办推送每30分钟
ot:
bakCseDownloadPath: /ot/download/case
bakPermitDownloadPath: /ot/download/permit

View File

@ -144,6 +144,15 @@ xcDoor:
enableTask: false # 开启推送待办
redirectUrl: http://10.21.5.138/integration/#/toDoList
# 统一监管门户
jgmhDoor:
enableTask: false # 开启推送待办
appId: a823ccd6b4954ec897d0d035c1534b2b
appSecret: RGRNOTZrNHBEbERRU1F1SHpZMVIzRQ==
redirectUrl: ${JGMH_DOOR_REDIRECT_URL:} # PC端待办跳转地址需根据环境配置
mobileRedirectUrl: ${JGMH_DOOR_MOBILE_REDIRECT_URL:} # 移动端待办跳转地址
debugEnabled: ${JGMH_DOOR_DEBUG_ENABLED:false} # 单笔调试推送接口开关,生产环境建议关闭
punishment:
api:
auth:

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.chinaweal.aiccs.door.mapper.PortalTodoPushRecordMapper">
</mapper>