Merge branch 'main' of http://27.223.88.102:33000/chenx/qhmes
This commit is contained in:
@@ -61,6 +61,11 @@ public interface ISysImChatService {
|
||||
* @return 消息VO,发送失败返回 null
|
||||
*/
|
||||
SysImMessageVO sendSystemSingleMessage(String fromUserId, String toUserId, Integer tenantId, String content, String msgType);
|
||||
|
||||
/**
|
||||
* 审批待办卡片:从「工作通知」公众号推送给处理人。
|
||||
*/
|
||||
SysImMessageVO sendApprovalHandlerMessage(String toUserId, Integer tenantId, String content, String msgType);
|
||||
//update-end---author:GHT ---date:2026-05-29 for:【QH-MES审批流设计】系统单聊消息(绕过同部门校验,供审批等系统通知场景)-----
|
||||
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@ import org.jeecg.modules.system.mapper.SysUserTenantMapper;
|
||||
import org.jeecg.modules.system.service.ISysPermissionService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -64,6 +65,13 @@ public class SysImChatServiceImpl implements ISysImChatService {
|
||||
private static final String MSG_IMAGE_PREVIEW = "[图片]";
|
||||
private static final String MSG_BIZ_RECORD_PREVIEW = "[业务数据]";
|
||||
private static final String IM_RECORD_QUERY_KEY = "imRecordId";
|
||||
/** IM 工作通知公众号账号(审批等系统消息统一从此账号推送) */
|
||||
private static final String WORK_NOTIFY_USERNAME = "im_work_notify";
|
||||
private static final String WORK_NOTIFY_REALNAME = "工作通知";
|
||||
private static final String WORK_NOTIFY_USER_ID = "1995000000000000999";
|
||||
private static final String CONTACT_TYPE_WORK_NOTIFY = "work_notify";
|
||||
private static final String CONTACT_TYPE_USER = "user";
|
||||
private volatile String workNotifyUserIdCache;
|
||||
|
||||
@Autowired
|
||||
private ISysPermissionService sysPermissionService;
|
||||
@@ -107,7 +115,11 @@ public class SysImChatServiceImpl implements ISysImChatService {
|
||||
if (conversation != null) {
|
||||
return buildConversationVo(conversation, userId, targetUserId);
|
||||
}
|
||||
validateTenantChat(userId, tenantId, orgCode, targetUserId);
|
||||
//update-begin---author:GHT ---date:20260610 for:【IM审批通用化】工作通知公众号会话免同部门校验-----------
|
||||
if (!isWorkNotifyUser(targetUserId)) {
|
||||
validateTenantChat(userId, tenantId, orgCode, targetUserId);
|
||||
}
|
||||
//update-end---author:GHT ---date:20260610 for:【IM审批通用化】工作通知公众号会话免同部门校验-----------
|
||||
//update-end---author:cursor ---date:20260528 for:【IM聊天-OA】已有会话快速打开-----------
|
||||
conversation = new SysImConversation();
|
||||
conversation.setConvType(CONV_TYPE_SINGLE);
|
||||
@@ -439,6 +451,11 @@ public class SysImChatServiceImpl implements ISysImChatService {
|
||||
throw new JeecgBootException("消息内容不能为空");
|
||||
}
|
||||
assertMember(userId, dto.getConversationId());
|
||||
//update-begin---author:GHT ---date:20260610 for:【IM审批通用化】工作通知公众号只读,禁止用户发消息-----------
|
||||
if (isWorkNotifyConversation(dto.getConversationId())) {
|
||||
throw new JeecgBootException("工作通知为系统消息通道,不支持发送消息");
|
||||
}
|
||||
//update-end---author:GHT ---date:20260610 for:【IM审批通用化】工作通知公众号只读,禁止用户发消息-----------
|
||||
Date now = new Date();
|
||||
SysImMessage message = new SysImMessage();
|
||||
message.setConversationId(dto.getConversationId());
|
||||
@@ -480,8 +497,8 @@ public class SysImChatServiceImpl implements ISysImChatService {
|
||||
if (oConvertUtils.isEmpty(fromUserId) || oConvertUtils.isEmpty(toUserId) || oConvertUtils.isEmpty(content)) {
|
||||
return null;
|
||||
}
|
||||
// 不给自己发送
|
||||
if (fromUserId.equals(toUserId)) {
|
||||
log.warn("IM系统消息跳过:收发为同一人 toUserId={}", toUserId);
|
||||
return null;
|
||||
}
|
||||
Integer tenant = tenantId == null ? 0 : tenantId;
|
||||
@@ -500,8 +517,17 @@ public class SysImChatServiceImpl implements ISysImChatService {
|
||||
conversation.setCreateTime(now);
|
||||
conversation.setUpdateTime(now);
|
||||
conversationMapper.insert(conversation);
|
||||
createMember(conversation.getId(), fromUserId, now);
|
||||
createMember(conversation.getId(), toUserId, now);
|
||||
ensureMember(conversation.getId(), fromUserId, now);
|
||||
if (!fromUserId.equals(toUserId)) {
|
||||
ensureMember(conversation.getId(), toUserId, now);
|
||||
}
|
||||
} else {
|
||||
//update-begin---author:GHT ---date:20260610 for:【IM审批通用化】已有会话补全缺失成员-----------
|
||||
ensureMember(conversation.getId(), fromUserId, now);
|
||||
if (!fromUserId.equals(toUserId)) {
|
||||
ensureMember(conversation.getId(), toUserId, now);
|
||||
}
|
||||
//update-end---author:GHT ---date:20260610 for:【IM审批通用化】已有会话补全缺失成员-----------
|
||||
}
|
||||
// 写入消息
|
||||
SysImMessage message = new SysImMessage();
|
||||
@@ -522,6 +548,22 @@ public class SysImChatServiceImpl implements ISysImChatService {
|
||||
pushChatMessage(conversation.getId(), fromUserId, messageVo, conversation.getConvType());
|
||||
return messageVo;
|
||||
}
|
||||
|
||||
//update-begin---author:GHT ---date:20260610 for:【IM审批通用化】审批待办统一由系统账号发给处理人-----------
|
||||
@Override
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
|
||||
public SysImMessageVO sendApprovalHandlerMessage(String toUserId, Integer tenantId, String content, String msgType) {
|
||||
if (oConvertUtils.isEmpty(toUserId) || oConvertUtils.isEmpty(content)) {
|
||||
return null;
|
||||
}
|
||||
String fromUserId = ensureWorkNotifyUserId();
|
||||
if (fromUserId.equals(toUserId)) {
|
||||
log.warn("审批待办IM发送失败:接收人不能是工作通知公众号 toUserId={}", toUserId);
|
||||
return null;
|
||||
}
|
||||
return sendSystemSingleMessage(fromUserId, toUserId, tenantId, content, msgType);
|
||||
}
|
||||
//update-end---author:GHT ---date:20260610 for:【IM审批通用化】审批待办统一由系统账号发给处理人-----------
|
||||
//update-end---author:GHT ---date:2026-05-29 for:【QH-MES审批流设计】系统单聊消息(绕过同部门校验)-----
|
||||
|
||||
//update-begin---author:cursor ---date:20260528 for:【IM聊天-OA】标记已读-----------
|
||||
@@ -541,13 +583,19 @@ public class SysImChatServiceImpl implements ISysImChatService {
|
||||
//update-begin---author:cursor ---date:20260528 for:【IM聊天-OA】本部门成员列表(含会话摘要)-----------
|
||||
@Override
|
||||
public List<SysImContactVO> listDeptMembers(String userId, Integer tenantId, String orgCode, String keyword) {
|
||||
List<SysImContactVO> result = new ArrayList<>();
|
||||
//update-begin---author:GHT ---date:20260610 for:【IM审批通用化】同事列表置顶工作通知公众号-----------
|
||||
if (matchWorkNotifyKeyword(keyword)) {
|
||||
result.add(buildWorkNotifyContact(userId, tenantId));
|
||||
}
|
||||
String workNotifyId = ensureWorkNotifyUserId();
|
||||
String resolvedOrgCode = resolveOrgCode(userId, tenantId, orgCode);
|
||||
if (oConvertUtils.isEmpty(resolvedOrgCode)) {
|
||||
throw new JeecgBootException("未获取到当前部门,请切换部门后重试");
|
||||
return result;
|
||||
}
|
||||
List<SysUser> users = userDepartMapper.querySameDepartUserList(resolvedOrgCode, userId, tenantId, keyword);
|
||||
if (users == null || users.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
return result;
|
||||
}
|
||||
Map<String, SysImConversationVO> convMap = new HashMap<>(16);
|
||||
if (tenantId != null && tenantId > 0) {
|
||||
@@ -557,20 +605,26 @@ public class SysImChatServiceImpl implements ISysImChatService {
|
||||
}
|
||||
}
|
||||
}
|
||||
List<SysImContactVO> result = users.stream().map(user -> {
|
||||
SysImContactVO vo = toContactVo(user);
|
||||
SysImConversationVO conv = convMap.get(user.getId());
|
||||
if (conv != null) {
|
||||
vo.setConversationId(conv.getConversationId());
|
||||
vo.setLastContent(conv.getLastContent());
|
||||
vo.setLastTime(conv.getLastTime());
|
||||
vo.setUnreadCount(conv.getUnreadCount());
|
||||
}
|
||||
return vo;
|
||||
}).collect(Collectors.toList());
|
||||
result.sort(Comparator
|
||||
List<SysImContactVO> colleagues = users.stream()
|
||||
.filter(user -> !workNotifyId.equals(user.getId()) && !WORK_NOTIFY_USERNAME.equals(user.getUsername()))
|
||||
.map(user -> {
|
||||
SysImContactVO vo = toContactVo(user);
|
||||
vo.setContactType(CONTACT_TYPE_USER);
|
||||
SysImConversationVO conv = convMap.get(user.getId());
|
||||
if (conv != null) {
|
||||
vo.setConversationId(conv.getConversationId());
|
||||
vo.setLastContent(conv.getLastContent());
|
||||
vo.setLastTime(conv.getLastTime());
|
||||
vo.setUnreadCount(conv.getUnreadCount());
|
||||
}
|
||||
return vo;
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
colleagues.sort(Comparator
|
||||
.comparing(SysImContactVO::getLastTime, Comparator.nullsLast(Comparator.reverseOrder()))
|
||||
.thenComparing(item -> oConvertUtils.getString(item.getRealname(), item.getUsername())));
|
||||
result.addAll(colleagues);
|
||||
//update-end---author:GHT ---date:20260610 for:【IM审批通用化】同事列表置顶工作通知公众号-----------
|
||||
return result;
|
||||
}
|
||||
//update-end---author:cursor ---date:20260528 for:【IM聊天-OA】本部门成员列表(含会话摘要)-----------
|
||||
@@ -583,9 +637,111 @@ public class SysImChatServiceImpl implements ISysImChatService {
|
||||
vo.setAvatar(user.getAvatar());
|
||||
vo.setOrgCodeTxt(user.getOrgCodeTxt());
|
||||
vo.setUnreadCount(0);
|
||||
vo.setContactType(CONTACT_TYPE_USER);
|
||||
return vo;
|
||||
}
|
||||
|
||||
private SysImContactVO buildWorkNotifyContact(String userId, Integer tenantId) {
|
||||
String workNotifyId = ensureWorkNotifyUserId();
|
||||
SysImContactVO vo = new SysImContactVO();
|
||||
vo.setId(workNotifyId);
|
||||
vo.setUsername(WORK_NOTIFY_USERNAME);
|
||||
vo.setRealname(WORK_NOTIFY_REALNAME);
|
||||
vo.setUnreadCount(0);
|
||||
vo.setContactType(CONTACT_TYPE_WORK_NOTIFY);
|
||||
if (tenantId != null && tenantId > 0) {
|
||||
SysImConversationVO conv = findSingleConversationSummary(userId, tenantId, workNotifyId);
|
||||
if (conv != null) {
|
||||
vo.setConversationId(conv.getConversationId());
|
||||
vo.setLastContent(conv.getLastContent());
|
||||
vo.setLastTime(conv.getLastTime());
|
||||
vo.setUnreadCount(conv.getUnreadCount());
|
||||
}
|
||||
}
|
||||
return vo;
|
||||
}
|
||||
|
||||
private SysImConversationVO findSingleConversationSummary(String userId, Integer tenantId, String targetUserId) {
|
||||
String pairKey = buildPairKey(userId, targetUserId);
|
||||
SysImConversation conversation = conversationMapper.selectOne(new LambdaQueryWrapper<SysImConversation>()
|
||||
.eq(SysImConversation::getTenantId, tenantId)
|
||||
.eq(SysImConversation::getUserPairKey, pairKey));
|
||||
if (conversation == null) {
|
||||
return null;
|
||||
}
|
||||
SysImConversationMember member = getMember(userId, conversation.getId());
|
||||
SysImConversationVO vo = buildConversationVo(conversation, userId, targetUserId);
|
||||
vo.setUnreadCount(member == null ? 0 : member.getUnreadCount());
|
||||
return vo;
|
||||
}
|
||||
|
||||
private boolean matchWorkNotifyKeyword(String keyword) {
|
||||
if (oConvertUtils.isEmpty(keyword)) {
|
||||
return true;
|
||||
}
|
||||
String key = keyword.trim().toLowerCase();
|
||||
return WORK_NOTIFY_REALNAME.contains(keyword.trim())
|
||||
|| WORK_NOTIFY_REALNAME.toLowerCase().contains(key)
|
||||
|| WORK_NOTIFY_USERNAME.contains(key)
|
||||
|| key.contains("工作")
|
||||
|| key.contains("通知");
|
||||
}
|
||||
|
||||
private String ensureWorkNotifyUserId() {
|
||||
if (oConvertUtils.isNotEmpty(workNotifyUserIdCache)) {
|
||||
return workNotifyUserIdCache;
|
||||
}
|
||||
synchronized (this) {
|
||||
if (oConvertUtils.isNotEmpty(workNotifyUserIdCache)) {
|
||||
return workNotifyUserIdCache;
|
||||
}
|
||||
SysUser user = userMapper.selectOne(new LambdaQueryWrapper<SysUser>()
|
||||
.eq(SysUser::getUsername, WORK_NOTIFY_USERNAME)
|
||||
.eq(SysUser::getDelFlag, 0)
|
||||
.last("LIMIT 1"));
|
||||
if (user == null) {
|
||||
user = userMapper.selectById(WORK_NOTIFY_USER_ID);
|
||||
}
|
||||
if (user == null) {
|
||||
user = createWorkNotifyUser();
|
||||
}
|
||||
workNotifyUserIdCache = user.getId();
|
||||
return workNotifyUserIdCache;
|
||||
}
|
||||
}
|
||||
|
||||
private SysUser createWorkNotifyUser() {
|
||||
SysUser user = new SysUser();
|
||||
user.setId(WORK_NOTIFY_USER_ID);
|
||||
user.setUsername(WORK_NOTIFY_USERNAME);
|
||||
user.setRealname(WORK_NOTIFY_REALNAME);
|
||||
user.setPassword("disabled");
|
||||
user.setSalt("");
|
||||
user.setStatus(2);
|
||||
user.setDelFlag(0);
|
||||
user.setCreateBy("system");
|
||||
user.setCreateTime(new Date());
|
||||
userMapper.insert(user);
|
||||
return user;
|
||||
}
|
||||
|
||||
private boolean isWorkNotifyUser(String userId) {
|
||||
return oConvertUtils.isNotEmpty(userId) && userId.equals(ensureWorkNotifyUserId());
|
||||
}
|
||||
|
||||
private boolean isWorkNotifyConversation(String conversationId) {
|
||||
if (oConvertUtils.isEmpty(conversationId)) {
|
||||
return false;
|
||||
}
|
||||
SysImConversation conversation = conversationMapper.selectById(conversationId);
|
||||
if (conversation == null || !CONV_TYPE_SINGLE.equals(conversation.getConvType())) {
|
||||
return false;
|
||||
}
|
||||
String workNotifyId = ensureWorkNotifyUserId();
|
||||
String pairKey = conversation.getUserPairKey();
|
||||
return oConvertUtils.isNotEmpty(pairKey) && pairKey.contains(workNotifyId);
|
||||
}
|
||||
|
||||
private String resolveOrgCode(String userId, Integer tenantId, String orgCode) {
|
||||
if (oConvertUtils.isNotEmpty(orgCode)) {
|
||||
return orgCode;
|
||||
@@ -610,6 +766,17 @@ public class SysImChatServiceImpl implements ISysImChatService {
|
||||
}
|
||||
|
||||
private void createMember(String conversationId, String userId, Date now) {
|
||||
ensureMember(conversationId, userId, now);
|
||||
}
|
||||
|
||||
/** 幂等创建会话成员,避免 uk_im_member 重复插入 */
|
||||
private void ensureMember(String conversationId, String userId, Date now) {
|
||||
if (oConvertUtils.isEmpty(conversationId) || oConvertUtils.isEmpty(userId)) {
|
||||
return;
|
||||
}
|
||||
if (getMember(userId, conversationId) != null) {
|
||||
return;
|
||||
}
|
||||
SysImConversationMember member = new SysImConversationMember();
|
||||
member.setConversationId(conversationId);
|
||||
member.setUserId(userId);
|
||||
@@ -742,7 +909,11 @@ public class SysImChatServiceImpl implements ISysImChatService {
|
||||
sender = userMapper.selectById(message.getSenderId());
|
||||
}
|
||||
if (sender != null) {
|
||||
vo.setSenderName(sender.getRealname());
|
||||
if (WORK_NOTIFY_USERNAME.equals(sender.getUsername())) {
|
||||
vo.setSenderName(WORK_NOTIFY_REALNAME);
|
||||
} else {
|
||||
vo.setSenderName(sender.getRealname());
|
||||
}
|
||||
vo.setSenderAvatar(sender.getAvatar());
|
||||
}
|
||||
return vo;
|
||||
|
||||
@@ -28,4 +28,6 @@ public class SysImContactVO {
|
||||
private java.util.Date lastTime;
|
||||
@Schema(description = "未读数")
|
||||
private Integer unreadCount;
|
||||
@Schema(description = "联系人类型 user=同事 work_notify=工作通知公众号")
|
||||
private String contactType;
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.jeecg.common.aspect.annotation.Dict;
|
||||
import org.jeecg.modules.print.vo.PrintBizFieldItemVO;
|
||||
import org.jeecgframework.poi.excel.annotation.Excel;
|
||||
|
||||
@@ -46,6 +47,7 @@ public final class PrintBizEntityFieldIntrospector {
|
||||
PrintBizFieldItemVO vo =
|
||||
new PrintBizFieldItemVO(name, resolveLabel(f), "");
|
||||
fillJavaJdbcSimple(vo, f.getType());
|
||||
fillDictMeta(vo, f);
|
||||
ordered.putIfAbsent(name, vo);
|
||||
}
|
||||
c = c.getSuperclass();
|
||||
@@ -223,6 +225,69 @@ public final class PrintBizEntityFieldIntrospector {
|
||||
return f.getName();
|
||||
}
|
||||
|
||||
//update-begin---author:GHT ---date:2026-06-10 for:【钉钉审批模板绑定】扫描@Dict并补全字典元数据-----------
|
||||
/** 扫描 @Dict 注解,供绑定页选择「原值/显示文本」 */
|
||||
public static void fillDictMeta(PrintBizFieldItemVO vo, Field f) {
|
||||
if (vo == null || f == null) {
|
||||
return;
|
||||
}
|
||||
Dict dict = f.getAnnotation(Dict.class);
|
||||
if (dict == null) {
|
||||
vo.setTranslateKind("NONE");
|
||||
return;
|
||||
}
|
||||
if (StringUtils.isNotBlank(dict.dictTable())) {
|
||||
vo.setTranslateKind("TABLE");
|
||||
vo.setDictTable(dict.dictTable().trim());
|
||||
vo.setDictText(StringUtils.isNotBlank(dict.dicText()) ? dict.dicText().trim() : "");
|
||||
vo.setDictCodeField(StringUtils.isNotBlank(dict.dicCode()) ? dict.dicCode().trim() : "id");
|
||||
} else if (StringUtils.isNotBlank(dict.dicCode())) {
|
||||
vo.setTranslateKind("DICT");
|
||||
vo.setDictCode(dict.dicCode().trim());
|
||||
} else {
|
||||
vo.setTranslateKind("NONE");
|
||||
}
|
||||
}
|
||||
|
||||
/** 按字段名在实体类上补全字典元数据(catalog 缓存字段可能缺 translateKind) */
|
||||
public static void enrichDictMeta(List<PrintBizFieldItemVO> fields, Class<?> clazz, String fieldKeyPrefix) {
|
||||
if (fields == null || fields.isEmpty() || clazz == null) {
|
||||
return;
|
||||
}
|
||||
String prefix = StringUtils.isBlank(fieldKeyPrefix) ? "" : fieldKeyPrefix.trim();
|
||||
if (StringUtils.isNotBlank(prefix) && !prefix.endsWith(".")) {
|
||||
prefix = prefix + ".";
|
||||
}
|
||||
Map<String, Field> fieldMap = new LinkedHashMap<>();
|
||||
Class<?> c = clazz;
|
||||
while (c != null && c != Object.class) {
|
||||
for (Field f : c.getDeclaredFields()) {
|
||||
fieldMap.putIfAbsent(f.getName(), f);
|
||||
}
|
||||
c = c.getSuperclass();
|
||||
}
|
||||
for (PrintBizFieldItemVO vo : fields) {
|
||||
if (vo == null || StringUtils.isBlank(vo.getFieldKey())) {
|
||||
continue;
|
||||
}
|
||||
String key = vo.getFieldKey();
|
||||
if (StringUtils.isNotBlank(prefix) && key.startsWith(prefix)) {
|
||||
key = key.substring(prefix.length());
|
||||
}
|
||||
int dot = key.indexOf('.');
|
||||
if (dot >= 0) {
|
||||
key = key.substring(dot + 1);
|
||||
}
|
||||
Field f = fieldMap.get(key);
|
||||
if (f != null) {
|
||||
fillDictMeta(vo, f);
|
||||
} else if (StringUtils.isBlank(vo.getTranslateKind())) {
|
||||
vo.setTranslateKind("NONE");
|
||||
}
|
||||
}
|
||||
}
|
||||
//update-end---author:GHT ---date:2026-06-10 for:【钉钉审批模板绑定】扫描@Dict并补全字典元数据-----------
|
||||
|
||||
/** 按全限定类名加载 Class,失败返回 null */
|
||||
public static Class<?> tryLoadClass(String entityClassFqn) {
|
||||
if (StringUtils.isBlank(entityClassFqn)) {
|
||||
|
||||
@@ -35,6 +35,24 @@ public class PrintBizFieldItemVO implements Serializable {
|
||||
@Schema(description = "简化种类,便于前端格式化")
|
||||
private String simpleKind;
|
||||
|
||||
//update-begin---author:GHT ---date:2026-06-10 for:【钉钉审批模板绑定】字段元数据支持字典/表字典-----------
|
||||
/** 取值翻译类型:NONE=普通字段,DICT=字典,TABLE=表字典(部门/用户等) */
|
||||
@Schema(description = "取值翻译类型:NONE/DICT/TABLE")
|
||||
private String translateKind;
|
||||
|
||||
@Schema(description = "字典编码(dicCode),translateKind=DICT 时有效")
|
||||
private String dictCode;
|
||||
|
||||
@Schema(description = "字典表名,translateKind=TABLE 时有效")
|
||||
private String dictTable;
|
||||
|
||||
@Schema(description = "字典表文本列,translateKind=TABLE 时有效")
|
||||
private String dictText;
|
||||
|
||||
@Schema(description = "字典表编码列,translateKind=TABLE 时有效")
|
||||
private String dictCodeField;
|
||||
//update-end---author:GHT ---date:2026-06-10 for:【钉钉审批模板绑定】字段元数据支持字典/表字典-----------
|
||||
|
||||
/** 兼容旧三参构造(类型字段为空) */
|
||||
public PrintBizFieldItemVO(String fieldKey, String label, String description) {
|
||||
this.fieldKey = fieldKey;
|
||||
@@ -53,6 +71,13 @@ public class PrintBizFieldItemVO implements Serializable {
|
||||
o.setJavaType(src.getJavaType());
|
||||
o.setJdbcType(src.getJdbcType());
|
||||
o.setSimpleKind(src.getSimpleKind());
|
||||
//update-begin---author:GHT ---date:2026-06-10 for:【钉钉审批模板绑定】复制字段时保留字典元数据-----------
|
||||
o.setTranslateKind(src.getTranslateKind());
|
||||
o.setDictCode(src.getDictCode());
|
||||
o.setDictTable(src.getDictTable());
|
||||
o.setDictText(src.getDictText());
|
||||
o.setDictCodeField(src.getDictCodeField());
|
||||
//update-end---author:GHT ---date:2026-06-10 for:【钉钉审批模板绑定】复制字段时保留字典元数据-----------
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
@@ -56,6 +56,11 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.messaging.simp.SimpMessagingTemplate;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
//update-begin---author:GHT ---date:2026-06-08 for:【XSLMES-20260608】同步钉钉ID功能-----------
|
||||
import com.jeecg.dingtalk.api.core.response.Response;
|
||||
import com.jeecg.dingtalk.api.user.JdtUserAPI;
|
||||
import org.jeecg.modules.system.service.impl.ThirdAppDingtalkServiceImpl;
|
||||
//update-end---author:GHT ---date:2026-06-08 for:【XSLMES-20260608】同步钉钉ID功能-----------
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
@@ -125,6 +130,11 @@ public class SysUserController {
|
||||
@Autowired(required = false)
|
||||
private SimpMessagingTemplate simpMessagingTemplate;
|
||||
|
||||
//update-begin---author:GHT ---date:2026-06-08 for:【XSLMES-20260608】注入钉钉服务,用于同步钉钉ID-----------
|
||||
@Autowired(required = false)
|
||||
private ThirdAppDingtalkServiceImpl thirdAppDingtalkService;
|
||||
//update-end---author:GHT ---date:2026-06-08 for:【XSLMES-20260608】注入钉钉服务,用于同步钉钉ID-----------
|
||||
|
||||
private void notifyScadaUserChanged(String action, String userId) {
|
||||
try {
|
||||
JSONObject payload = new JSONObject();
|
||||
@@ -2246,6 +2256,60 @@ public class SysUserController {
|
||||
* yes_{URL编码后的默认密码} -> 用户当前密码为默认初始密码,前端需弹出强制修改提示
|
||||
* no -> 用户密码不是默认密码,或未开启默认密码检测开关
|
||||
*/
|
||||
//update-begin---author:GHT ---date:2026-06-08 for:【XSLMES-20260608】批量同步钉钉用户ID接口-----------
|
||||
/**
|
||||
* 批量同步钉钉ID:根据用户手机号查询钉钉userId并回写到sys_user.ding_user_id。
|
||||
* 匹配不到的用户只做提示,不影响其他用户继续匹配。
|
||||
*/
|
||||
@Operation(summary = "同步钉钉用户ID")
|
||||
@PostMapping("/syncDingUserId")
|
||||
public Result<JSONObject> syncDingUserId() {
|
||||
if (thirdAppDingtalkService == null) {
|
||||
return Result.error("钉钉集成未配置,无法同步");
|
||||
}
|
||||
String accessToken = thirdAppDingtalkService.getAccessTokenForBackground();
|
||||
if (oConvertUtils.isEmpty(accessToken)) {
|
||||
return Result.error("获取钉钉 AccessToken 失败,请检查钉钉应用配置");
|
||||
}
|
||||
// 查询所有有手机号的用户
|
||||
List<SysUser> users = sysUserService.list(
|
||||
new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<SysUser>()
|
||||
.isNotNull(SysUser::getPhone)
|
||||
.ne(SysUser::getPhone, "")
|
||||
.eq(SysUser::getDelFlag, 0)
|
||||
);
|
||||
int successCount = 0;
|
||||
int failCount = 0;
|
||||
List<String> failDetails = new ArrayList<>();
|
||||
for (SysUser user : users) {
|
||||
try {
|
||||
Response<String> resp = JdtUserAPI.getUseridByMobile(user.getPhone(), accessToken);
|
||||
if (resp != null && resp.isSuccess() && oConvertUtils.isNotEmpty(resp.getResult())) {
|
||||
sysUserService.lambdaUpdate()
|
||||
.eq(SysUser::getId, user.getId())
|
||||
.set(SysUser::getDingUserId, resp.getResult())
|
||||
.update();
|
||||
successCount++;
|
||||
} else {
|
||||
failCount++;
|
||||
failDetails.add(user.getRealname() + "(" + user.getPhone() + ")");
|
||||
log.info("[syncDingUserId] 手机号未匹配到钉钉用户 realname={} phone={}", user.getRealname(), user.getPhone());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
failCount++;
|
||||
failDetails.add(user.getRealname() + "(" + user.getPhone() + ")");
|
||||
log.warn("[syncDingUserId] 查询钉钉ID异常 realname={} phone={}", user.getRealname(), user.getPhone(), e);
|
||||
}
|
||||
}
|
||||
JSONObject result = new JSONObject();
|
||||
result.put("successCount", successCount);
|
||||
result.put("failCount", failCount);
|
||||
result.put("failDetails", failDetails);
|
||||
String msg = "同步完成:成功 " + successCount + " 人,未匹配 " + failCount + " 人";
|
||||
return Result.OK(msg, result);
|
||||
}
|
||||
//update-end---author:GHT ---date:2026-06-08 for:【XSLMES-20260608】批量同步钉钉用户ID接口-----------
|
||||
|
||||
@GetMapping("/verifyIzDefaultPwd")
|
||||
public Result<String> verifyIzDefaultPwd() throws UnsupportedEncodingException {
|
||||
// 未配置 Firewall 或已关闭默认密码检测开关 (enableDefaultPwdCheck=false) 时,直接返回 "no" 表示无需提示
|
||||
|
||||
@@ -32,8 +32,12 @@ import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.InetAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -72,6 +72,17 @@ public class SysThirdAppConfig {
|
||||
private Integer streamEnabled;
|
||||
//update-end---author:GHT ---date:20260604 for:【钉钉Stream回调】Stream事件推送主配置标识-----
|
||||
|
||||
//update-begin---author:GHT ---date:20260609 for:【钉钉Stream开发】第三方配置页Stream接收节点可视化-----------
|
||||
@Schema(description = "是否限制仅指定节点接收Stream(0-否,1-是)")
|
||||
private Integer streamReceiverEnabled;
|
||||
@Schema(description = "允许接收Stream的IP白名单,逗号分隔")
|
||||
private String streamDesignatedIps;
|
||||
@Schema(description = "允许接收Stream的主机名白名单,逗号分隔")
|
||||
private String streamDesignatedHosts;
|
||||
@Schema(description = "Stream集群Redis选主(0-否,1-是)")
|
||||
private Integer streamClusterMode;
|
||||
//update-end---author:GHT ---date:20260609 for:【钉钉Stream开发】第三方配置页Stream接收节点可视化-----------
|
||||
|
||||
/**创建日期*/
|
||||
@Excel(name = "创建日期", width = 20, format = "yyyy-MM-dd HH:mm:ss")
|
||||
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
|
||||
@@ -272,4 +272,11 @@ public class SysUser implements Serializable {
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private String belongDepIds;
|
||||
|
||||
//update-begin---author:GHT ---date:2026-06-08 for:【XSLMES-20260608】新增钉钉用户ID字段,支持同步钉钉ID功能-----------
|
||||
/**
|
||||
* 钉钉用户ID
|
||||
*/
|
||||
private String dingUserId;
|
||||
//update-end---author:GHT ---date:2026-06-08 for:【XSLMES-20260608】新增钉钉用户ID字段,支持同步钉钉ID功能-----------
|
||||
}
|
||||
|
||||
@@ -1228,6 +1228,29 @@ public class ThirdAppDingtalkServiceImpl implements IThirdAppService {
|
||||
}
|
||||
//update-end---author:GHT ---date:20260604 for:【钉钉Stream回调】获取钉钉应用凭证(Stream模式专用)-----
|
||||
|
||||
//update-begin---author:GHT ---date:20260609 for:【钉钉Stream开发】获取Stream主配置(含节点白名单)-----------
|
||||
/**
|
||||
* 获取 Stream 主配置记录(stream_enabled=1 优先)。
|
||||
*/
|
||||
public SysThirdAppConfig getStreamMasterConfig() {
|
||||
java.util.List<SysThirdAppConfig> all = configMapper.selectList(
|
||||
new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<SysThirdAppConfig>()
|
||||
.eq(SysThirdAppConfig::getThirdType, THIRD_TYPE)
|
||||
.eq(SysThirdAppConfig::getStatus, 1)
|
||||
.orderByDesc(SysThirdAppConfig::getStreamEnabled)
|
||||
.orderByDesc(SysThirdAppConfig::getTenantId));
|
||||
if (all == null || all.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
for (SysThirdAppConfig c : all) {
|
||||
if (c.getStreamEnabled() != null && c.getStreamEnabled() == 1) {
|
||||
return c;
|
||||
}
|
||||
}
|
||||
return all.get(0);
|
||||
}
|
||||
//update-end---author:GHT ---date:20260609 for:【钉钉Stream开发】获取Stream主配置(含节点白名单)-----------
|
||||
|
||||
//update-begin---author:GHT ---date:20260604 for:【钉钉Stream回调】后台线程专用AccessToken(绕过租户检查)-----
|
||||
/**
|
||||
* 后台线程专用:获取钉钉 AccessToken,不依赖 TenantContext。
|
||||
|
||||
@@ -34,6 +34,12 @@
|
||||
<artifactId>jeecg-module-xslmes</artifactId>
|
||||
<version>${jeecgboot.version}</version>
|
||||
</dependency>
|
||||
<!-- 钉钉 Stream SDK:显式声明,确保 IDE 调试运行时 classpath 包含 dingtalk-stream GHT 20260605 -->
|
||||
<dependency>
|
||||
<groupId>com.dingtalk.open</groupId>
|
||||
<artifactId>dingtalk-stream</artifactId>
|
||||
<version>1.3.12</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jeecgframework.boot3</groupId>
|
||||
<artifactId>jeecg-module-device-sync</artifactId>
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
# 复制为 application-dev-local.yml(同目录),仅本机生效,勿提交 Git
|
||||
# 作用:只有你这台电脑接收钉钉 Stream 回调与补偿扫描,其他共用 dev 库的机器不会抢消息
|
||||
#
|
||||
# 1. 复制:application-dev-local.yml.example -> application-dev-local.yml
|
||||
# 2. 查本机 IP(PowerShell: ipconfig,看 IPv4 地址)
|
||||
# 3. 将 designated-ips 改成你的 IP(推荐,比主机名稳定)
|
||||
# 4. 重启 JeecgBoot
|
||||
#
|
||||
# 启动后若未匹配,日志会打印 localIps=... 便于核对
|
||||
|
||||
jeecg:
|
||||
xslmes:
|
||||
dingtalk:
|
||||
stream:
|
||||
receiver-enabled: true
|
||||
# 推荐:仅 IP 白名单(二选一或同时配置,满足其一即可)
|
||||
designated-ips:
|
||||
- 192.168.1.100
|
||||
# 可选:主机名白名单(hostname 命令查看)
|
||||
# designated-hosts:
|
||||
# - LAPTOP-9LEM1NNJ
|
||||
@@ -20,6 +20,9 @@ management:
|
||||
include: metrics,httpexchanges,jeecghttptrace
|
||||
|
||||
spring:
|
||||
config:
|
||||
# 开发者本机覆盖配置(不提交 Git),用于指定仅本机接收钉钉 Stream 回调
|
||||
import: optional:classpath:application-dev-local.yml
|
||||
# main:
|
||||
# # 启动加速 (建议开发环境,开启后flyway自动升级失效)
|
||||
# lazy-initialization: true
|
||||
@@ -211,6 +214,20 @@ mybatis-plus:
|
||||
minidao:
|
||||
base-package: org.jeecg.modules.jmreport.*,org.jeecg.modules.drag.*
|
||||
jeecg:
|
||||
xslmes:
|
||||
dingtalk:
|
||||
stream:
|
||||
# 共享 dev 默认关闭;仅本机在 application-dev-local.yml 开启(见 application-dev-local.yml.example)
|
||||
receiver-enabled: false
|
||||
# 白名单二选一或同时配置(满足其一即可);推荐 designated-ips,比主机名稳定
|
||||
designated-hosts: []
|
||||
designated-ips: []
|
||||
# 多实例部署务必 true:Redis 选主,仅 Leader 建 Stream 长连接
|
||||
cluster-mode: true
|
||||
leader-renew-interval-ms: 10000
|
||||
follower-retry-interval-ms: 15000
|
||||
health-log-interval-ms: 60000
|
||||
idle-warn-seconds: 1800
|
||||
# 自定义资源请求前缀(js、css等解决nginx转发问题)
|
||||
custom-resource-prefix-path:
|
||||
# AI集成
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
-- 【审核集成 Phase0】新建4张集成表 + 扩展审批台账
|
||||
-- author: GHT date: 2026-06-05
|
||||
SET NAMES utf8mb4;
|
||||
|
||||
-- ① 单据注册中心
|
||||
CREATE TABLE IF NOT EXISTS `mes_xsl_biz_doc_registry` (
|
||||
`id` varchar(32) NOT NULL COMMENT '主键',
|
||||
`doc_code` varchar(64) NOT NULL COMMENT '业务编码 如 formula_spec',
|
||||
`table_name` varchar(128) NOT NULL COMMENT '物理表名',
|
||||
`display_name` varchar(128) DEFAULT NULL COMMENT '中文名',
|
||||
`enabled` tinyint DEFAULT 1 COMMENT '启用 0否 1是',
|
||||
`remark` varchar(500) DEFAULT NULL COMMENT '备注',
|
||||
`del_flag` int DEFAULT 0 COMMENT '逻辑删除',
|
||||
`tenant_id` int DEFAULT NULL COMMENT '租户ID',
|
||||
`sys_org_code` varchar(64) DEFAULT NULL,
|
||||
`create_by` varchar(50) DEFAULT NULL,
|
||||
`create_time` datetime DEFAULT NULL,
|
||||
`update_by` varchar(50) DEFAULT NULL,
|
||||
`update_time` datetime DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_biz_doc_code_tenant` (`doc_code`, `tenant_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='MES单据注册中心';
|
||||
|
||||
-- 预置常用单据
|
||||
INSERT IGNORE INTO `mes_xsl_biz_doc_registry`
|
||||
(`id`, `doc_code`, `table_name`, `display_name`, `enabled`, `del_flag`, `tenant_id`, `create_by`, `create_time`)
|
||||
VALUES
|
||||
(REPLACE(UUID(),'-',''), 'formula_spec', 'mes_xsl_formula_spec', '配合示方', 1, 0, 0, 'admin', NOW()),
|
||||
(REPLACE(UUID(),'-',''), 'mixing_spec', 'mes_xsl_mixing_spec', '密炼示方', 1, 0, 0, 'admin', NOW()),
|
||||
(REPLACE(UUID(),'-',''), 'mixer_ps_compile', 'mes_xsl_mixer_ps_compile', '密炼PS编制', 1, 0, 0, 'admin', NOW()),
|
||||
(REPLACE(UUID(),'-',''), 'rubber_quick_test_std', 'mes_xsl_rubber_quick_test_std', '快检实验标准', 1, 0, 0, 'admin', NOW()),
|
||||
(REPLACE(UUID(),'-',''), 'raw_material_entry', 'mes_xsl_raw_material_entry', '原料入场记录', 1, 0, 0, 'admin', NOW());
|
||||
|
||||
-- ② 集成方案
|
||||
CREATE TABLE IF NOT EXISTS `mes_xsl_integration_plan` (
|
||||
`id` varchar(32) NOT NULL COMMENT '主键',
|
||||
`plan_code` varchar(64) NOT NULL COMMENT '方案编码(唯一)',
|
||||
`plan_name` varchar(128) NOT NULL COMMENT '方案名称',
|
||||
`source_table` varchar(128) NOT NULL COMMENT '源单表名',
|
||||
`trigger_phase` varchar(20) NOT NULL COMMENT '触发时机 onApprove/onReject/onNodeApprove',
|
||||
`exec_mode` varchar(10) DEFAULT 'async' COMMENT '执行模式 sync同步/async异步提交后',
|
||||
`match_condition` varchar(500) DEFAULT NULL COMMENT '匹配条件(空=无条件)',
|
||||
`status` varchar(1) DEFAULT '0' COMMENT '0草稿 1已发布 2已停用',
|
||||
`remark` varchar(500) DEFAULT NULL,
|
||||
`del_flag` int DEFAULT 0,
|
||||
`tenant_id` int DEFAULT NULL,
|
||||
`sys_org_code` varchar(64) DEFAULT NULL,
|
||||
`create_by` varchar(50) DEFAULT NULL,
|
||||
`create_time` datetime DEFAULT NULL,
|
||||
`update_by` varchar(50) DEFAULT NULL,
|
||||
`update_time` datetime DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_int_plan_table_phase` (`source_table`, `trigger_phase`, `status`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='审核集成方案';
|
||||
|
||||
-- ③ 集成动作
|
||||
CREATE TABLE IF NOT EXISTS `mes_xsl_integration_action` (
|
||||
`id` varchar(32) NOT NULL COMMENT '主键',
|
||||
`plan_id` varchar(32) NOT NULL COMMENT '所属方案ID',
|
||||
`action_name` varchar(128) NOT NULL COMMENT '动作名称',
|
||||
`action_type` varchar(30) NOT NULL DEFAULT 'SQL_UPDATE' COMMENT '动作类型 Phase0仅SQL_UPDATE',
|
||||
`sql_template` text DEFAULT NULL COMMENT 'SQL_UPDATE模板,支持#{source.xxx}变量',
|
||||
`exec_order` int DEFAULT 0 COMMENT '执行顺序(升序)',
|
||||
`on_fail` varchar(10) DEFAULT 'stop' COMMENT '失败策略 stop终止/continue继续',
|
||||
`idempotent_key` varchar(200) DEFAULT NULL COMMENT '幂等键表达式(空=record_id+action_id)',
|
||||
`enabled` tinyint DEFAULT 1 COMMENT '启用',
|
||||
`remark` varchar(500) DEFAULT NULL,
|
||||
`del_flag` int DEFAULT 0,
|
||||
`create_by` varchar(50) DEFAULT NULL,
|
||||
`create_time` datetime DEFAULT NULL,
|
||||
`update_by` varchar(50) DEFAULT NULL,
|
||||
`update_time` datetime DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_int_action_plan` (`plan_id`, `exec_order`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='审核集成动作';
|
||||
|
||||
-- ④ 集成执行日志
|
||||
CREATE TABLE IF NOT EXISTS `mes_xsl_integration_log` (
|
||||
`id` varchar(32) NOT NULL COMMENT '主键',
|
||||
`record_id` varchar(32) DEFAULT NULL COMMENT '审批台账ID',
|
||||
`plan_id` varchar(32) DEFAULT NULL COMMENT '方案ID',
|
||||
`action_id` varchar(32) DEFAULT NULL COMMENT '动作ID',
|
||||
`idempotent_key` varchar(200) DEFAULT NULL COMMENT '幂等键',
|
||||
`status` varchar(10) DEFAULT NULL COMMENT 'success/failed/skipped',
|
||||
`source_biz_id` varchar(64) DEFAULT NULL COMMENT '源单ID',
|
||||
`source_biz_table` varchar(128) DEFAULT NULL COMMENT '源单表名',
|
||||
`error_message` text DEFAULT NULL COMMENT '错误信息',
|
||||
`retry_count` int DEFAULT 0 COMMENT '重试次数',
|
||||
`exec_time_ms` bigint DEFAULT NULL COMMENT '耗时ms',
|
||||
`request_snapshot` text DEFAULT NULL COMMENT '执行前变量快照',
|
||||
`response_snapshot` text DEFAULT NULL COMMENT '执行结果快照',
|
||||
`create_by` varchar(50) DEFAULT NULL,
|
||||
`create_time` datetime DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_intlog_record` (`record_id`),
|
||||
KEY `idx_intlog_idempotent` (`idempotent_key`(191)),
|
||||
KEY `idx_intlog_plan_action` (`plan_id`, `action_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='审核集成执行日志';
|
||||
|
||||
-- ⑤ 扩展 mes_xsl_approval_record(幂等:列已存在则跳过,避免重复执行报 1060)
|
||||
SET @db = DATABASE();
|
||||
|
||||
SET @sql = IF(
|
||||
(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'mes_xsl_approval_record' AND COLUMN_NAME = 'integration_status') = 0,
|
||||
'ALTER TABLE `mes_xsl_approval_record` ADD COLUMN `integration_status` varchar(2) DEFAULT ''0'' COMMENT ''编排状态 0未执行 1成功 2部分失败 3失败'' AFTER `finish_time`',
|
||||
'SELECT 1'
|
||||
);
|
||||
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||||
|
||||
SET @sql = IF(
|
||||
(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'mes_xsl_approval_record' AND COLUMN_NAME = 'integration_remark') = 0,
|
||||
'ALTER TABLE `mes_xsl_approval_record` ADD COLUMN `integration_remark` varchar(500) DEFAULT NULL COMMENT ''编排摘要/错误信息'' AFTER `integration_status`',
|
||||
'SELECT 1'
|
||||
);
|
||||
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||||
@@ -0,0 +1,74 @@
|
||||
-- 【审核集成 Phase0】字典数据
|
||||
-- author: GHT date: 2026-06-05
|
||||
SET NAMES utf8mb4;
|
||||
|
||||
-- 集成动作类型
|
||||
INSERT IGNORE INTO `sys_dict` (`id`,`dict_name`,`dict_code`,`description`,`del_flag`,`create_by`,`create_time`,`type`,`tenant_id`)
|
||||
VALUES ('1995000000000000360','集成动作类型','mes_xsl_integration_action_type','审核集成动作类型',0,'admin',NOW(),0,0);
|
||||
|
||||
INSERT IGNORE INTO `sys_dict_item` (`id`,`dict_id`,`item_text`,`item_value`,`description`,`sort_order`,`status`,`create_by`,`create_time`)
|
||||
VALUES
|
||||
('1995000000000000361','1995000000000000360','SQL更新','SQL_UPDATE','执行UPDATE/INSERT SQL',1,1,'admin',NOW()),
|
||||
('1995000000000000362','1995000000000000360','更新单据','UPDATE_DOC','结构化更新目标单据(Phase1)',2,1,'admin',NOW()),
|
||||
('1995000000000000363','1995000000000000360','生成单据','CREATE_DOC','生成目标主+子表(Phase1)',3,1,'admin',NOW()),
|
||||
('1995000000000000364','1995000000000000360','调用接口','CALL_API','HTTP调用业务接口(Phase2)',4,1,'admin',NOW()),
|
||||
('1995000000000000365','1995000000000000360','调用Handler','CALL_HANDLER','Spring Bean处理(Phase2)',5,1,'admin',NOW());
|
||||
|
||||
-- 集成触发时机
|
||||
INSERT IGNORE INTO `sys_dict` (`id`,`dict_name`,`dict_code`,`description`,`del_flag`,`create_by`,`create_time`,`type`,`tenant_id`)
|
||||
VALUES ('1995000000000000366','集成触发时机','mes_xsl_integration_trigger_phase','审核集成方案触发时机',0,'admin',NOW(),0,0);
|
||||
|
||||
INSERT IGNORE INTO `sys_dict_item` (`id`,`dict_id`,`item_text`,`item_value`,`description`,`sort_order`,`status`,`create_by`,`create_time`)
|
||||
VALUES
|
||||
('1995000000000000367','1995000000000000366','审批通过','onApprove','整个流程最终通过时触发',1,1,'admin',NOW()),
|
||||
('1995000000000000368','1995000000000000366','审批驳回','onReject','任一节点驳回时触发',2,1,'admin',NOW()),
|
||||
('1995000000000000369','1995000000000000366','节点通过','onNodeApprove','单个节点通过(中间态)时触发',3,1,'admin',NOW());
|
||||
|
||||
-- 集成方案状态
|
||||
INSERT IGNORE INTO `sys_dict` (`id`,`dict_name`,`dict_code`,`description`,`del_flag`,`create_by`,`create_time`,`type`,`tenant_id`)
|
||||
VALUES ('1995000000000000370','集成方案状态','mes_xsl_integration_plan_status','审核集成方案状态',0,'admin',NOW(),0,0);
|
||||
|
||||
INSERT IGNORE INTO `sys_dict_item` (`id`,`dict_id`,`item_text`,`item_value`,`description`,`sort_order`,`status`,`create_by`,`create_time`)
|
||||
VALUES
|
||||
('1995000000000000371','1995000000000000370','草稿','0','未发布,不生效',1,1,'admin',NOW()),
|
||||
('1995000000000000372','1995000000000000370','已发布','1','生效中',2,1,'admin',NOW()),
|
||||
('1995000000000000373','1995000000000000370','已停用','2','已停用',3,1,'admin',NOW());
|
||||
|
||||
-- 集成执行日志状态
|
||||
INSERT IGNORE INTO `sys_dict` (`id`,`dict_name`,`dict_code`,`description`,`del_flag`,`create_by`,`create_time`,`type`,`tenant_id`)
|
||||
VALUES ('1995000000000000374','集成执行状态','mes_xsl_integration_log_status','审核集成执行日志状态',0,'admin',NOW(),0,0);
|
||||
|
||||
INSERT IGNORE INTO `sys_dict_item` (`id`,`dict_id`,`item_text`,`item_value`,`description`,`sort_order`,`status`,`create_by`,`create_time`)
|
||||
VALUES
|
||||
('1995000000000000375','1995000000000000374','成功','success','执行成功',1,1,'admin',NOW()),
|
||||
('1995000000000000376','1995000000000000374','失败','failed','执行失败',2,1,'admin',NOW()),
|
||||
('1995000000000000377','1995000000000000374','已跳过','skipped','幂等命中跳过',3,1,'admin',NOW());
|
||||
|
||||
-- 集成执行模式
|
||||
INSERT IGNORE INTO `sys_dict` (`id`,`dict_name`,`dict_code`,`description`,`del_flag`,`create_by`,`create_time`,`type`,`tenant_id`)
|
||||
VALUES ('1995000000000000378','集成执行模式','mes_xsl_integration_exec_mode','审批后编排执行模式',0,'admin',NOW(),0,0);
|
||||
|
||||
INSERT IGNORE INTO `sys_dict_item` (`id`,`dict_id`,`item_text`,`item_value`,`description`,`sort_order`,`status`,`create_by`,`create_time`)
|
||||
VALUES
|
||||
('1995000000000000379','1995000000000000378','异步(推荐)','async','事务提交后异步执行,审批不因编排失败回滚',1,1,'admin',NOW()),
|
||||
('1995000000000000380','1995000000000000378','同步','sync','与审批同事务,编排失败回滚审批',2,1,'admin',NOW());
|
||||
|
||||
-- 编排执行状态(台账扩展字段)
|
||||
INSERT IGNORE INTO `sys_dict` (`id`,`dict_name`,`dict_code`,`description`,`del_flag`,`create_by`,`create_time`,`type`,`tenant_id`)
|
||||
VALUES ('1995000000000000381','编排执行状态','mes_xsl_integration_orch_status','审批台账的编排执行状态',0,'admin',NOW(),0,0);
|
||||
|
||||
INSERT IGNORE INTO `sys_dict_item` (`id`,`dict_id`,`item_text`,`item_value`,`description`,`sort_order`,`status`,`create_by`,`create_time`)
|
||||
VALUES
|
||||
('1995000000000000382','1995000000000000381','未执行','0','未触发编排',1,1,'admin',NOW()),
|
||||
('1995000000000000383','1995000000000000381','全部成功','1','所有动作均成功',2,1,'admin',NOW()),
|
||||
('1995000000000000384','1995000000000000381','部分失败','2','存在on_fail=continue的失败动作',3,1,'admin',NOW()),
|
||||
('1995000000000000385','1995000000000000381','失败','3','遇到on_fail=stop的失败动作中止',4,1,'admin',NOW());
|
||||
|
||||
-- 失败策略
|
||||
INSERT IGNORE INTO `sys_dict` (`id`,`dict_name`,`dict_code`,`description`,`del_flag`,`create_by`,`create_time`,`type`,`tenant_id`)
|
||||
VALUES ('1995000000000000386','动作失败策略','mes_xsl_integration_on_fail','集成动作失败后的处理策略',0,'admin',NOW(),0,0);
|
||||
|
||||
INSERT IGNORE INTO `sys_dict_item` (`id`,`dict_id`,`item_text`,`item_value`,`description`,`sort_order`,`status`,`create_by`,`create_time`)
|
||||
VALUES
|
||||
('1995000000000000387','1995000000000000386','停止','stop','失败后停止后续动作',1,1,'admin',NOW()),
|
||||
('1995000000000000388','1995000000000000386','继续','continue','失败后继续执行后续动作',2,1,'admin',NOW());
|
||||
@@ -0,0 +1,50 @@
|
||||
-- 【审核集成 Phase0】菜单 + 权限(挂在 MESToDing审批配置 父菜单 178046026420801 下)
|
||||
-- author: GHT date: 2026-06-05
|
||||
SET NAMES utf8mb4;
|
||||
|
||||
-- 单据注册中心
|
||||
INSERT INTO sys_permission(id,parent_id,name,url,component,component_name,redirect,menu_type,perms,perms_type,sort_no,always_show,icon,is_route,is_leaf,keep_alive,hidden,hide_tab,description,status,del_flag,rule_flag,create_by,create_time,update_by,update_time,internal_or_external)
|
||||
VALUES('178046026420838','178046026420801','单据注册中心','/xslmes/mesXslBizDocRegistryList','xslmes/approval/integration/MesXslBizDocRegistryList',NULL,NULL,0,NULL,'1',4.00,0,'ant-design:database-outlined',1,0,0,0,0,NULL,'1',0,0,'admin','2026-06-05 00:00:00',NULL,NULL,0);
|
||||
|
||||
INSERT INTO sys_permission(id,parent_id,name,url,component,is_route,component_name,redirect,menu_type,perms,perms_type,sort_no,always_show,icon,is_leaf,keep_alive,hidden,hide_tab,description,create_by,create_time,update_by,update_time,del_flag,rule_flag,status,internal_or_external)
|
||||
VALUES('178046026420839','178046026420838','查询单据注册',NULL,NULL,0,NULL,NULL,2,'xslmes:mes_xsl_biz_doc_registry:list','1',NULL,0,NULL,1,0,0,0,NULL,'admin','2026-06-05 00:00:00',NULL,NULL,0,0,'1',0);
|
||||
INSERT INTO sys_permission(id,parent_id,name,url,component,is_route,component_name,redirect,menu_type,perms,perms_type,sort_no,always_show,icon,is_leaf,keep_alive,hidden,hide_tab,description,create_by,create_time,update_by,update_time,del_flag,rule_flag,status,internal_or_external)
|
||||
VALUES('178046026420840','178046026420838','新增单据注册',NULL,NULL,0,NULL,NULL,2,'xslmes:mes_xsl_biz_doc_registry:add','1',NULL,0,NULL,1,0,0,0,NULL,'admin','2026-06-05 00:00:00',NULL,NULL,0,0,'1',0);
|
||||
INSERT INTO sys_permission(id,parent_id,name,url,component,is_route,component_name,redirect,menu_type,perms,perms_type,sort_no,always_show,icon,is_leaf,keep_alive,hidden,hide_tab,description,create_by,create_time,update_by,update_time,del_flag,rule_flag,status,internal_or_external)
|
||||
VALUES('178046026420841','178046026420838','编辑单据注册',NULL,NULL,0,NULL,NULL,2,'xslmes:mes_xsl_biz_doc_registry:edit','1',NULL,0,NULL,1,0,0,0,NULL,'admin','2026-06-05 00:00:00',NULL,NULL,0,0,'1',0);
|
||||
INSERT INTO sys_permission(id,parent_id,name,url,component,is_route,component_name,redirect,menu_type,perms,perms_type,sort_no,always_show,icon,is_leaf,keep_alive,hidden,hide_tab,description,create_by,create_time,update_by,update_time,del_flag,rule_flag,status,internal_or_external)
|
||||
VALUES('178046026420842','178046026420838','删除单据注册',NULL,NULL,0,NULL,NULL,2,'xslmes:mes_xsl_biz_doc_registry:delete','1',NULL,0,NULL,1,0,0,0,NULL,'admin','2026-06-05 00:00:00',NULL,NULL,0,0,'1',0);
|
||||
|
||||
-- 集成方案管理(含内嵌动作管理)
|
||||
INSERT INTO sys_permission(id,parent_id,name,url,component,component_name,redirect,menu_type,perms,perms_type,sort_no,always_show,icon,is_route,is_leaf,keep_alive,hidden,hide_tab,description,status,del_flag,rule_flag,create_by,create_time,update_by,update_time,internal_or_external)
|
||||
VALUES('178046026420830','178046026420801','集成方案管理','/xslmes/mesXslIntegrationPlanList','xslmes/approval/integration/MesXslIntegrationPlanList',NULL,NULL,0,NULL,'1',5.00,0,'ant-design:node-index-outlined',1,0,0,0,0,NULL,'1',0,0,'admin','2026-06-05 00:00:00',NULL,NULL,0);
|
||||
|
||||
INSERT INTO sys_permission(id,parent_id,name,url,component,is_route,component_name,redirect,menu_type,perms,perms_type,sort_no,always_show,icon,is_leaf,keep_alive,hidden,hide_tab,description,create_by,create_time,update_by,update_time,del_flag,rule_flag,status,internal_or_external)
|
||||
VALUES('178046026420831','178046026420830','查询集成方案',NULL,NULL,0,NULL,NULL,2,'xslmes:mes_xsl_integration_plan:list','1',NULL,0,NULL,1,0,0,0,NULL,'admin','2026-06-05 00:00:00',NULL,NULL,0,0,'1',0);
|
||||
INSERT INTO sys_permission(id,parent_id,name,url,component,is_route,component_name,redirect,menu_type,perms,perms_type,sort_no,always_show,icon,is_leaf,keep_alive,hidden,hide_tab,description,create_by,create_time,update_by,update_time,del_flag,rule_flag,status,internal_or_external)
|
||||
VALUES('178046026420832','178046026420830','新增集成方案',NULL,NULL,0,NULL,NULL,2,'xslmes:mes_xsl_integration_plan:add','1',NULL,0,NULL,1,0,0,0,NULL,'admin','2026-06-05 00:00:00',NULL,NULL,0,0,'1',0);
|
||||
INSERT INTO sys_permission(id,parent_id,name,url,component,is_route,component_name,redirect,menu_type,perms,perms_type,sort_no,always_show,icon,is_leaf,keep_alive,hidden,hide_tab,description,create_by,create_time,update_by,update_time,del_flag,rule_flag,status,internal_or_external)
|
||||
VALUES('178046026420833','178046026420830','编辑集成方案',NULL,NULL,0,NULL,NULL,2,'xslmes:mes_xsl_integration_plan:edit','1',NULL,0,NULL,1,0,0,0,NULL,'admin','2026-06-05 00:00:00',NULL,NULL,0,0,'1',0);
|
||||
INSERT INTO sys_permission(id,parent_id,name,url,component,is_route,component_name,redirect,menu_type,perms,perms_type,sort_no,always_show,icon,is_leaf,keep_alive,hidden,hide_tab,description,create_by,create_time,update_by,update_time,del_flag,rule_flag,status,internal_or_external)
|
||||
VALUES('178046026420834','178046026420830','删除集成方案',NULL,NULL,0,NULL,NULL,2,'xslmes:mes_xsl_integration_plan:delete','1',NULL,0,NULL,1,0,0,0,NULL,'admin','2026-06-05 00:00:00',NULL,NULL,0,0,'1',0);
|
||||
INSERT INTO sys_permission(id,parent_id,name,url,component,is_route,component_name,redirect,menu_type,perms,perms_type,sort_no,always_show,icon,is_leaf,keep_alive,hidden,hide_tab,description,create_by,create_time,update_by,update_time,del_flag,rule_flag,status,internal_or_external)
|
||||
VALUES('178046026420843','178046026420830','发布集成方案',NULL,NULL,0,NULL,NULL,2,'xslmes:mes_xsl_integration_plan:publish','1',NULL,0,NULL,1,0,0,0,NULL,'admin','2026-06-05 00:00:00',NULL,NULL,0,0,'1',0);
|
||||
|
||||
-- 集成执行日志
|
||||
INSERT INTO sys_permission(id,parent_id,name,url,component,component_name,redirect,menu_type,perms,perms_type,sort_no,always_show,icon,is_route,is_leaf,keep_alive,hidden,hide_tab,description,status,del_flag,rule_flag,create_by,create_time,update_by,update_time,internal_or_external)
|
||||
VALUES('178046026420835','178046026420801','集成执行日志','/xslmes/mesXslIntegrationLogList','xslmes/approval/integration/MesXslIntegrationLogList',NULL,NULL,0,NULL,'1',6.00,0,'ant-design:file-search-outlined',1,0,0,0,0,NULL,'1',0,0,'admin','2026-06-05 00:00:00',NULL,NULL,0);
|
||||
|
||||
INSERT INTO sys_permission(id,parent_id,name,url,component,is_route,component_name,redirect,menu_type,perms,perms_type,sort_no,always_show,icon,is_leaf,keep_alive,hidden,hide_tab,description,create_by,create_time,update_by,update_time,del_flag,rule_flag,status,internal_or_external)
|
||||
VALUES('178046026420836','178046026420835','查询集成日志',NULL,NULL,0,NULL,NULL,2,'xslmes:mes_xsl_integration_log:list','1',NULL,0,NULL,1,0,0,0,NULL,'admin','2026-06-05 00:00:00',NULL,NULL,0,0,'1',0);
|
||||
INSERT INTO sys_permission(id,parent_id,name,url,component,is_route,component_name,redirect,menu_type,perms,perms_type,sort_no,always_show,icon,is_leaf,keep_alive,hidden,hide_tab,description,create_by,create_time,update_by,update_time,del_flag,rule_flag,status,internal_or_external)
|
||||
VALUES('178046026420837','178046026420835','重试集成动作',NULL,NULL,0,NULL,NULL,2,'xslmes:mes_xsl_integration_log:retry','1',NULL,0,NULL,1,0,0,0,NULL,'admin','2026-06-05 00:00:00',NULL,NULL,0,0,'1',0);
|
||||
|
||||
-- 授权给超管角色(f6817f48af4fb3af11b9e8bf182f618b)
|
||||
INSERT INTO sys_role_permission (id,role_id,permission_id,data_rule_ids,operate_date,operate_ip)
|
||||
SELECT REPLACE(UUID(),'-',''),'f6817f48af4fb3af11b9e8bf182f618b',id,NULL,'2026-06-05 00:00:00','127.0.0.1'
|
||||
FROM sys_permission
|
||||
WHERE id IN (
|
||||
'178046026420830','178046026420831','178046026420832','178046026420833','178046026420834','178046026420843',
|
||||
'178046026420835','178046026420836','178046026420837',
|
||||
'178046026420838','178046026420839','178046026420840','178046026420841','178046026420842'
|
||||
);
|
||||
@@ -0,0 +1,106 @@
|
||||
-- 【审核集成 Phase0】密炼PS编制 — 集成方案演示数据
|
||||
-- 功能说明:
|
||||
-- 将密炼PS现有三节点审批(校对→审核→批准)的状态流转逻辑,
|
||||
-- 转化为可视化的集成方案配置,验证 SQL_UPDATE 动作执行器的实际效果。
|
||||
-- 注意:
|
||||
-- 方案初始状态为"草稿(0)",不会自动触发。
|
||||
-- 需要在【集成方案管理】页面手动"发布"后才生效。
|
||||
-- 现有 @ApprovalBizAction HTTP 回调仍然生效(两套并行,SQL 以 AND status=? 条件防重)。
|
||||
-- author: GHT date: 2026-06-05
|
||||
SET NAMES utf8mb4;
|
||||
|
||||
-- =============================================================
|
||||
-- 方案一:审批全部通过 — 推进主表 + 配合示方到最终批准态
|
||||
-- 触发时机:onApprove(最终通过整个流程时)
|
||||
-- =============================================================
|
||||
INSERT IGNORE INTO `mes_xsl_integration_plan`
|
||||
(`id`,`plan_code`,`plan_name`,`source_table`,`trigger_phase`,`exec_mode`,`match_condition`,`status`,`remark`,`del_flag`,`tenant_id`,`create_by`,`create_time`)
|
||||
VALUES
|
||||
('mxpsonapproveplan000001','mixer_ps_on_approve','密炼PS-审批通过→批准态同步','mes_xsl_mixer_ps_compile','onApprove','async',NULL,'0',
|
||||
'最终审批通过后:主表 status→approve,配合示方 status→recognition_pass',
|
||||
0,0,'admin',NOW());
|
||||
|
||||
INSERT IGNORE INTO `mes_xsl_integration_action`
|
||||
(`id`,`plan_id`,`action_name`,`action_type`,`sql_template`,`exec_order`,`on_fail`,`enabled`,`remark`,`del_flag`,`create_by`,`create_time`)
|
||||
VALUES
|
||||
('mxpsonapprove_act001','mxpsonapproveplan000001',
|
||||
'主表→批准态','SQL_UPDATE',
|
||||
'UPDATE mes_xsl_mixer_ps_compile SET status=''approve'', approve_time=NOW() WHERE id=#{source.id} AND status=''audit''',
|
||||
1,'stop',1,'只在 audit 态才更新,防止重复触发',0,'admin',NOW()),
|
||||
|
||||
('mxpsonapprove_act002','mxpsonapproveplan000001',
|
||||
'配合示方→认定通过','SQL_UPDATE',
|
||||
'UPDATE mes_xsl_formula_spec SET status=''recognition_pass'', approve_time=NOW() WHERE issue_number=#{source.issue_number} AND issue_number IS NOT NULL',
|
||||
2,'continue',1,'通过 issue_number 级联同步,issue_number 为空时影响0行自动跳过',0,'admin',NOW()),
|
||||
|
||||
('mxpsonapprove_act003','mxpsonapproveplan000001',
|
||||
'混炼示方→同步批准时间','SQL_UPDATE',
|
||||
'UPDATE mes_xsl_mixing_spec SET approve_time=NOW() WHERE issue_number=#{source.issue_number} AND issue_number IS NOT NULL',
|
||||
3,'continue',1,'仅同步时间戳,不改变混炼示方 status',0,'admin',NOW());
|
||||
|
||||
-- =============================================================
|
||||
-- 方案二:审批驳回 — 全量回退到编制态,清空所有痕迹
|
||||
-- 触发时机:onReject(任一节点被驳回时)
|
||||
-- =============================================================
|
||||
INSERT IGNORE INTO `mes_xsl_integration_plan`
|
||||
(`id`,`plan_code`,`plan_name`,`source_table`,`trigger_phase`,`exec_mode`,`match_condition`,`status`,`remark`,`del_flag`,`tenant_id`,`create_by`,`create_time`)
|
||||
VALUES
|
||||
('mxpsonrejectplan000002','mixer_ps_on_reject','密炼PS-审批驳回→恢复编制态','mes_xsl_mixer_ps_compile','onReject','async',NULL,'0',
|
||||
'驳回后:主表+配合示方回到 compile,清空校对/审核/批准全部痕迹字段',
|
||||
0,0,'admin',NOW());
|
||||
|
||||
INSERT IGNORE INTO `mes_xsl_integration_action`
|
||||
(`id`,`plan_id`,`action_name`,`action_type`,`sql_template`,`exec_order`,`on_fail`,`enabled`,`remark`,`del_flag`,`create_by`,`create_time`)
|
||||
VALUES
|
||||
('mxpsonreject_act001','mxpsonrejectplan000002',
|
||||
'主表→回退编制态','SQL_UPDATE',
|
||||
'UPDATE mes_xsl_mixer_ps_compile SET status=''compile'', proofread_by=NULL, proofread_time=NULL, audit_by=NULL, audit_time=NULL, approve_by=NULL, approve_time=NULL WHERE id=#{source.id}',
|
||||
1,'stop',1,'无条件回退,清空所有审批痕迹',0,'admin',NOW()),
|
||||
|
||||
('mxpsonreject_act002','mxpsonrejectplan000002',
|
||||
'配合示方→回退编制态','SQL_UPDATE',
|
||||
'UPDATE mes_xsl_formula_spec SET status=''compile'', proofread_by=NULL, proofread_time=NULL, audit_by=NULL, audit_time=NULL, approve_by=NULL, approve_time=NULL WHERE issue_number=#{source.issue_number} AND issue_number IS NOT NULL',
|
||||
2,'continue',1,'级联回退配合示方状态',0,'admin',NOW()),
|
||||
|
||||
('mxpsonreject_act003','mxpsonrejectplan000002',
|
||||
'混炼示方→清空痕迹','SQL_UPDATE',
|
||||
'UPDATE mes_xsl_mixing_spec SET proofread_by=NULL, proofread_time=NULL, audit_by=NULL, audit_time=NULL, approve_by=NULL, approve_time=NULL WHERE issue_number=#{source.issue_number} AND issue_number IS NOT NULL',
|
||||
3,'continue',1,'混炼示方只清痕迹不改 status',0,'admin',NOW());
|
||||
|
||||
-- =============================================================
|
||||
-- 方案三:节点逐级通过 — 利用条件 WHERE 区分校对/审核两个节点
|
||||
-- 触发时机:onNodeApprove(每通过一个中间节点时触发一次)
|
||||
-- 关键设计:每个 UPDATE 带 AND status='当前期望状态' 条件,
|
||||
-- 当 status 不匹配时影响 0 行,自动跳过,实现节点自动识别
|
||||
-- =============================================================
|
||||
INSERT IGNORE INTO `mes_xsl_integration_plan`
|
||||
(`id`,`plan_code`,`plan_name`,`source_table`,`trigger_phase`,`exec_mode`,`match_condition`,`status`,`remark`,`del_flag`,`tenant_id`,`create_by`,`create_time`)
|
||||
VALUES
|
||||
('mxpsnodeapprplan000003','mixer_ps_node_approve','密炼PS-节点通过→逐级状态推进','mes_xsl_mixer_ps_compile','onNodeApprove','async',NULL,'0',
|
||||
'利用条件 WHERE 区分校对/审核两节点:每次只有一条 SQL 真正命中(影响1行),另一条影响0行自动跳过',
|
||||
0,0,'admin',NOW());
|
||||
|
||||
INSERT IGNORE INTO `mes_xsl_integration_action`
|
||||
(`id`,`plan_id`,`action_name`,`action_type`,`sql_template`,`exec_order`,`on_fail`,`enabled`,`remark`,`del_flag`,`create_by`,`create_time`)
|
||||
VALUES
|
||||
-- 第1、2条:校对节点通过(当前 status=compile 时命中)
|
||||
('mxpsnodeappr_act001','mxpsnodeapprplan000003',
|
||||
'校对通过-主表→proofread','SQL_UPDATE',
|
||||
'UPDATE mes_xsl_mixer_ps_compile SET status=''proofread'', proofread_time=NOW() WHERE id=#{source.id} AND status=''compile''',
|
||||
1,'continue',1,'status=compile 才命中(校对节点);status=proofread 时影响0行自动跳过',0,'admin',NOW()),
|
||||
|
||||
('mxpsnodeappr_act002','mxpsnodeapprplan000003',
|
||||
'校对通过-配合示方→submit','SQL_UPDATE',
|
||||
'UPDATE mes_xsl_formula_spec SET status=''submit'', proofread_time=NOW() WHERE issue_number=#{source.issue_number} AND status=''compile'' AND issue_number IS NOT NULL',
|
||||
2,'continue',1,'配合示方校对态同步',0,'admin',NOW()),
|
||||
|
||||
-- 第3、4条:审核节点通过(当前 status=proofread 时命中)
|
||||
('mxpsnodeappr_act003','mxpsnodeapprplan000003',
|
||||
'审核通过-主表→audit','SQL_UPDATE',
|
||||
'UPDATE mes_xsl_mixer_ps_compile SET status=''audit'', audit_time=NOW() WHERE id=#{source.id} AND status=''proofread''',
|
||||
3,'continue',1,'status=proofread 才命中(审核节点);校对节点时影响0行跳过',0,'admin',NOW()),
|
||||
|
||||
('mxpsnodeappr_act004','mxpsnodeapprplan000003',
|
||||
'审核通过-配合示方→review_pass','SQL_UPDATE',
|
||||
'UPDATE mes_xsl_formula_spec SET status=''review_pass'', audit_time=NOW() WHERE issue_number=#{source.issue_number} AND status=''submit'' AND issue_number IS NOT NULL',
|
||||
4,'continue',1,'配合示方审核态同步',0,'admin',NOW());
|
||||
@@ -0,0 +1,5 @@
|
||||
-- 【审核集成 Phase0】新增动作可视化配置字段
|
||||
-- 用于存储可视化编辑器的配置 JSON,支持重新打开时还原可视化状态
|
||||
-- author: GHT date: 2026-06-05
|
||||
ALTER TABLE `mes_xsl_integration_action`
|
||||
ADD COLUMN `action_config` TEXT DEFAULT NULL COMMENT '可视化配置JSON(可视化编辑器专用,用于重新打开时还原配置)' AFTER `sql_template`;
|
||||
@@ -0,0 +1,132 @@
|
||||
-- 【审批注册中心】扩展注册配置 + 审批痕迹明细表(每单据一行)
|
||||
-- author: GHT date: 2026-06-05 for:【XSLMES-20260605-K8R2】
|
||||
SET NAMES utf8mb4;
|
||||
SET @db = DATABASE();
|
||||
|
||||
-- ① 扩展 mes_xsl_biz_doc_registry(幂等:列已存在则跳过)
|
||||
SET @sql = IF(
|
||||
(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'mes_xsl_biz_doc_registry' AND COLUMN_NAME = 'enabled_stages') = 0,
|
||||
'ALTER TABLE `mes_xsl_biz_doc_registry` ADD COLUMN `enabled_stages` varchar(128) DEFAULT NULL COMMENT ''启用环节(多选逗号分隔 proofread,audit,approve)'' AFTER `enabled`',
|
||||
'SELECT 1'
|
||||
);
|
||||
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||||
|
||||
SET @sql = IF(
|
||||
(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'mes_xsl_biz_doc_registry' AND COLUMN_NAME = 'status_field') = 0,
|
||||
'ALTER TABLE `mes_xsl_biz_doc_registry` ADD COLUMN `status_field` varchar(64) DEFAULT ''status'' COMMENT ''业务状态字段名'' AFTER `enabled_stages`',
|
||||
'SELECT 1'
|
||||
);
|
||||
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||||
|
||||
SET @sql = IF(
|
||||
(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'mes_xsl_biz_doc_registry' AND COLUMN_NAME = 'proofread_by_field') = 0,
|
||||
'ALTER TABLE `mes_xsl_biz_doc_registry` ADD COLUMN `proofread_by_field` varchar(64) DEFAULT ''proofread_by'' COMMENT ''校对人字段名'' AFTER `status_field`',
|
||||
'SELECT 1'
|
||||
);
|
||||
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||||
|
||||
SET @sql = IF(
|
||||
(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'mes_xsl_biz_doc_registry' AND COLUMN_NAME = 'proofread_time_field') = 0,
|
||||
'ALTER TABLE `mes_xsl_biz_doc_registry` ADD COLUMN `proofread_time_field` varchar(64) DEFAULT ''proofread_time'' COMMENT ''校对时间字段名'' AFTER `proofread_by_field`',
|
||||
'SELECT 1'
|
||||
);
|
||||
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||||
|
||||
SET @sql = IF(
|
||||
(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'mes_xsl_biz_doc_registry' AND COLUMN_NAME = 'audit_by_field') = 0,
|
||||
'ALTER TABLE `mes_xsl_biz_doc_registry` ADD COLUMN `audit_by_field` varchar(64) DEFAULT ''audit_by'' COMMENT ''审核人字段名'' AFTER `proofread_time_field`',
|
||||
'SELECT 1'
|
||||
);
|
||||
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||||
|
||||
SET @sql = IF(
|
||||
(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'mes_xsl_biz_doc_registry' AND COLUMN_NAME = 'audit_time_field') = 0,
|
||||
'ALTER TABLE `mes_xsl_biz_doc_registry` ADD COLUMN `audit_time_field` varchar(64) DEFAULT ''audit_time'' COMMENT ''审核时间字段名'' AFTER `audit_by_field`',
|
||||
'SELECT 1'
|
||||
);
|
||||
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||||
|
||||
SET @sql = IF(
|
||||
(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'mes_xsl_biz_doc_registry' AND COLUMN_NAME = 'approve_by_field') = 0,
|
||||
'ALTER TABLE `mes_xsl_biz_doc_registry` ADD COLUMN `approve_by_field` varchar(64) DEFAULT ''approve_by'' COMMENT ''批准人字段名'' AFTER `audit_time_field`',
|
||||
'SELECT 1'
|
||||
);
|
||||
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||||
|
||||
SET @sql = IF(
|
||||
(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'mes_xsl_biz_doc_registry' AND COLUMN_NAME = 'approve_time_field') = 0,
|
||||
'ALTER TABLE `mes_xsl_biz_doc_registry` ADD COLUMN `approve_time_field` varchar(64) DEFAULT ''approve_time'' COMMENT ''批准时间字段名'' AFTER `approve_by_field`',
|
||||
'SELECT 1'
|
||||
);
|
||||
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||||
|
||||
ALTER TABLE `mes_xsl_biz_doc_registry` COMMENT='MES审批注册中心';
|
||||
|
||||
-- 密炼PS编制默认开启三环节
|
||||
UPDATE `mes_xsl_biz_doc_registry`
|
||||
SET `enabled_stages` = 'proofread,audit,approve',
|
||||
`status_field` = 'status',
|
||||
`proofread_by_field` = 'proofread_by',
|
||||
`proofread_time_field` = 'proofread_time',
|
||||
`audit_by_field` = 'audit_by',
|
||||
`audit_time_field` = 'audit_time',
|
||||
`approve_by_field` = 'approve_by',
|
||||
`approve_time_field` = 'approve_time',
|
||||
`update_by` = 'admin',
|
||||
`update_time` = NOW()
|
||||
WHERE `doc_code` = 'mixer_ps_compile' AND `del_flag` = 0;
|
||||
|
||||
-- ② 审批痕迹明细(每业务单据一行,按 biz_table + biz_data_id 唯一)
|
||||
CREATE TABLE IF NOT EXISTS `mes_xsl_approval_trace` (
|
||||
`id` varchar(32) NOT NULL COMMENT '主键',
|
||||
`registry_id` varchar(32) DEFAULT NULL COMMENT '审批注册配置ID',
|
||||
`biz_table` varchar(128) NOT NULL COMMENT '业务表名',
|
||||
`biz_data_id` varchar(32) NOT NULL COMMENT '业务单据ID',
|
||||
`proofread_by` varchar(80) DEFAULT NULL COMMENT '校对人',
|
||||
`proofread_time` datetime DEFAULT NULL COMMENT '校对时间',
|
||||
`audit_by` varchar(80) DEFAULT NULL COMMENT '审核人',
|
||||
`audit_time` datetime DEFAULT NULL COMMENT '审核时间',
|
||||
`approve_by` varchar(80) DEFAULT NULL COMMENT '批准人',
|
||||
`approve_time` datetime DEFAULT NULL COMMENT '批准时间',
|
||||
`remark` varchar(500) DEFAULT NULL COMMENT '备注',
|
||||
`del_flag` int DEFAULT 0 COMMENT '逻辑删除',
|
||||
`tenant_id` int DEFAULT NULL COMMENT '租户ID',
|
||||
`sys_org_code` varchar(64) DEFAULT NULL,
|
||||
`create_by` varchar(50) DEFAULT NULL,
|
||||
`create_time` datetime DEFAULT NULL,
|
||||
`update_by` varchar(50) DEFAULT NULL,
|
||||
`update_time` datetime DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uk_approval_trace_biz` (`biz_table`, `biz_data_id`, `tenant_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='MES审批痕迹明细(每单据一行)';
|
||||
|
||||
-- ③ 审批环节字典(注册中心多选)
|
||||
INSERT IGNORE INTO `sys_dict` (`id`,`dict_name`,`dict_code`,`description`,`del_flag`,`create_by`,`create_time`,`type`,`tenant_id`)
|
||||
VALUES ('1995000000000000390','审批环节','mes_xsl_approval_stage','审批注册中心可启用环节',0,'admin',NOW(),0,0);
|
||||
|
||||
INSERT IGNORE INTO `sys_dict_item` (`id`,`dict_id`,`item_text`,`item_value`,`description`,`sort_order`,`status`,`create_by`,`create_time`)
|
||||
VALUES
|
||||
('1995000000000000391','1995000000000000390','校对','proofread','校对环节',1,1,'admin',NOW()),
|
||||
('1995000000000000392','1995000000000000390','审核','audit','审核环节',2,1,'admin',NOW()),
|
||||
('1995000000000000393','1995000000000000390','批准','approve','批准环节',3,1,'admin',NOW());
|
||||
|
||||
-- ④ 菜单:重命名 + 新增审批痕迹
|
||||
UPDATE `sys_permission`
|
||||
SET `name` = '审批注册中心', `update_by` = 'admin', `update_time` = NOW()
|
||||
WHERE `id` = '178046026420838';
|
||||
|
||||
INSERT IGNORE INTO `sys_permission`
|
||||
(`id`,`parent_id`,`name`,`url`,`component`,`is_route`,`component_name`,`redirect`,`menu_type`,`perms`,`perms_type`,`sort_no`,`always_show`,`icon`,`is_leaf`,`keep_alive`,`hidden`,`hide_tab`,`description`,`status`,`del_flag`,`rule_flag`,`create_by`,`create_time`)
|
||||
VALUES
|
||||
('178046026420843','178046026420801','审批痕迹','/xslmes/mesXslApprovalTraceList','xslmes/approval/integration/MesXslApprovalTraceList',1,NULL,0,NULL,1,4.50,0,'ant-design:history-outlined',1,0,0,0,0,NULL,1,0,0,'admin',NOW());
|
||||
|
||||
INSERT IGNORE INTO `sys_permission`
|
||||
(`id`,`parent_id`,`name`,`perms`,`perms_type`,`menu_type`,`sort_no`,`is_leaf`,`create_by`,`create_time`)
|
||||
VALUES
|
||||
('178046026420844','178046026420843','查询审批痕迹','xslmes:mes_xsl_approval_trace:list',1,2,1,1,'admin',NOW());
|
||||
|
||||
INSERT IGNORE INTO `sys_role_permission` (`id`,`role_id`,`permission_id`,`operate_date`,`operate_ip`)
|
||||
VALUES (REPLACE(UUID(),'-',''),'f6817f48af4fb3af11b9e8bf182f618b','178046026420843',NOW(),'127.0.0.1');
|
||||
|
||||
INSERT IGNORE INTO `sys_role_permission` (`id`,`role_id`,`permission_id`,`operate_date`,`operate_ip`)
|
||||
VALUES (REPLACE(UUID(),'-',''),'f6817f48af4fb3af11b9e8bf182f618b','178046026420844',NOW(),'127.0.0.1');
|
||||
@@ -0,0 +1,26 @@
|
||||
-- 【审批注册中心】新增「查看明细」按钮权限,并授权给已有注册中心权限的角色
|
||||
-- author: GHT date: 2026-06-05 for:【XSLMES-20260605-K8R2】
|
||||
SET NAMES utf8mb4;
|
||||
|
||||
-- ① 审批注册中心下新增按钮权限:查看审批明细(列格式与 V3.9.2_132 按钮权限一致)
|
||||
INSERT IGNORE INTO sys_permission(id,parent_id,name,url,component,is_route,component_name,redirect,menu_type,perms,perms_type,sort_no,always_show,icon,is_leaf,keep_alive,hidden,hide_tab,description,create_by,create_time,update_by,update_time,del_flag,rule_flag,status,internal_or_external)
|
||||
VALUES('178046026420845','178046026420838','查看审批明细',NULL,NULL,0,NULL,NULL,2,'xslmes:mes_xsl_biz_doc_registry:trace','1',5,0,NULL,1,0,0,0,'审批注册中心操作列查看审批痕迹明细','admin',NOW(),NULL,NULL,0,0,'1',0);
|
||||
|
||||
-- ② 超管角色授权
|
||||
INSERT IGNORE INTO `sys_role_permission` (`id`,`role_id`,`permission_id`,`operate_date`,`operate_ip`)
|
||||
VALUES (REPLACE(UUID(),'-',''),'f6817f48af4fb3af11b9e8bf182f618b','178046026420845',NOW(),'127.0.0.1');
|
||||
|
||||
-- ③ 已有审批注册中心任意按钮权限的角色,自动补「查看明细」权限
|
||||
INSERT IGNORE INTO `sys_role_permission` (`id`,`role_id`,`permission_id`,`operate_date`,`operate_ip`)
|
||||
SELECT REPLACE(UUID(),'-',''), rp.`role_id`, '178046026420845', NOW(), '127.0.0.1'
|
||||
FROM `sys_role_permission` rp
|
||||
WHERE rp.`permission_id` IN (
|
||||
'178046026420839',
|
||||
'178046026420840',
|
||||
'178046026420841',
|
||||
'178046026420842'
|
||||
)
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM `sys_role_permission` x
|
||||
WHERE x.`role_id` = rp.`role_id` AND x.`permission_id` = '178046026420845'
|
||||
);
|
||||
@@ -0,0 +1,32 @@
|
||||
-- 【集成方案】与审批注册中心环节绑定
|
||||
-- author: GHT date: 2026-06-05 for:【XSLMES-20260605-K8R2】
|
||||
SET NAMES utf8mb4;
|
||||
SET @db = DATABASE();
|
||||
|
||||
-- ① 集成方案:关联注册中心 + 绑定审批环节
|
||||
SET @sql = IF(
|
||||
(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'mes_xsl_integration_plan' AND COLUMN_NAME = 'registry_id') = 0,
|
||||
'ALTER TABLE `mes_xsl_integration_plan` ADD COLUMN `registry_id` varchar(32) DEFAULT NULL COMMENT ''审批注册中心ID'' AFTER `source_table`',
|
||||
'SELECT 1'
|
||||
);
|
||||
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||||
|
||||
SET @sql = IF(
|
||||
(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'mes_xsl_integration_plan' AND COLUMN_NAME = 'trigger_stage') = 0,
|
||||
'ALTER TABLE `mes_xsl_integration_plan` ADD COLUMN `trigger_stage` varchar(32) DEFAULT NULL COMMENT ''绑定审批环节 proofread/audit/approve'' AFTER `trigger_phase`',
|
||||
'SELECT 1'
|
||||
);
|
||||
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||||
|
||||
-- ② 回填已有方案的注册中心与环节(按 source_table 关联)
|
||||
UPDATE `mes_xsl_integration_plan` p
|
||||
INNER JOIN `mes_xsl_biz_doc_registry` r ON r.table_name = p.source_table AND r.del_flag = 0 AND r.enabled = 1
|
||||
SET p.registry_id = r.id,
|
||||
p.trigger_stage = CASE p.trigger_phase
|
||||
WHEN 'onApprove' THEN 'approve'
|
||||
WHEN 'onNodeApprove' THEN NULL
|
||||
ELSE NULL
|
||||
END,
|
||||
p.update_by = 'admin',
|
||||
p.update_time = NOW()
|
||||
WHERE p.del_flag = 0 AND (p.registry_id IS NULL OR p.trigger_stage IS NULL);
|
||||
@@ -0,0 +1,87 @@
|
||||
-- 【集成方案】审批注册中心环节同步动作 + 密炼PS无代码审批方案示例
|
||||
-- author: GHT date: 2026-06-05 for:【XSLMES-20260605-K8R2】
|
||||
SET NAMES utf8mb4;
|
||||
|
||||
-- ① 集成动作类型字典扩展
|
||||
INSERT IGNORE INTO `sys_dict_item` (`id`,`dict_id`,`item_text`,`item_value`,`description`,`sort_order`,`status`,`create_by`,`create_time`)
|
||||
VALUES
|
||||
('1995000000000000394','1995000000000000360','审批环节同步','REGISTRY_STAGE_SYNC','按审批注册中心更新源单状态/操作人/痕迹',6,1,'admin',NOW()),
|
||||
('1995000000000000395','1995000000000000360','审批环节回退','REGISTRY_STAGE_REVERT','驳回时回退源单状态并清空痕迹',7,1,'admin',NOW());
|
||||
|
||||
-- ② 停用旧版 SQL 手写演示方案(保留数据,改为已停用)
|
||||
UPDATE `mes_xsl_integration_plan`
|
||||
SET `status` = '2', `update_by` = 'admin', `update_time` = NOW()
|
||||
WHERE `plan_code` IN ('mixer_ps_on_approve','mixer_ps_on_reject','mixer_ps_node_approve')
|
||||
AND `del_flag` = 0;
|
||||
|
||||
-- ③ 密炼PS — 校对环节通过
|
||||
INSERT IGNORE INTO `mes_xsl_integration_plan`
|
||||
(`id`,`plan_code`,`plan_name`,`source_table`,`registry_id`,`trigger_phase`,`trigger_stage`,`exec_mode`,`status`,`remark`,`del_flag`,`tenant_id`,`create_by`,`create_time`)
|
||||
SELECT
|
||||
'mxpsregproofread00001','mixer_ps_reg_proofread','密炼PS-校对通过(注册中心同步)',
|
||||
'mes_xsl_mixer_ps_compile', r.id, 'onNodeApprove', 'proofread', 'async', '0',
|
||||
'无需Java回调:更新status=proofread并写校对人/时间+审批痕迹', 0, 0, 'admin', NOW()
|
||||
FROM `mes_xsl_biz_doc_registry` r
|
||||
WHERE r.table_name='mes_xsl_mixer_ps_compile' AND r.del_flag=0 AND r.enabled=1
|
||||
LIMIT 1;
|
||||
|
||||
INSERT IGNORE INTO `mes_xsl_integration_action`
|
||||
(`id`,`plan_id`,`action_name`,`action_type`,`action_config`,`exec_order`,`on_fail`,`enabled`,`del_flag`,`create_by`,`create_time`)
|
||||
VALUES
|
||||
('mxpsregproofreadact01','mxpsregproofread00001','校对环节同步','REGISTRY_STAGE_SYNC',
|
||||
'{"visualType":"REGISTRY_STAGE_SYNC","stage":"proofread","expectedFrom":"compile"}',
|
||||
1,'stop',1,0,'admin',NOW());
|
||||
|
||||
-- ④ 密炼PS — 审核环节通过
|
||||
INSERT IGNORE INTO `mes_xsl_integration_plan`
|
||||
(`id`,`plan_code`,`plan_name`,`source_table`,`registry_id`,`trigger_phase`,`trigger_stage`,`exec_mode`,`status`,`remark`,`del_flag`,`tenant_id`,`create_by`,`create_time`)
|
||||
SELECT
|
||||
'mxpsregaudit00000002','mixer_ps_reg_audit','密炼PS-审核通过(注册中心同步)',
|
||||
'mes_xsl_mixer_ps_compile', r.id, 'onNodeApprove', 'audit', 'async', '0',
|
||||
'无需Java回调:更新status=audit并写审核人/时间+审批痕迹', 0, 0, 'admin', NOW()
|
||||
FROM `mes_xsl_biz_doc_registry` r
|
||||
WHERE r.table_name='mes_xsl_mixer_ps_compile' AND r.del_flag=0 AND r.enabled=1
|
||||
LIMIT 1;
|
||||
|
||||
INSERT IGNORE INTO `mes_xsl_integration_action`
|
||||
(`id`,`plan_id`,`action_name`,`action_type`,`action_config`,`exec_order`,`on_fail`,`enabled`,`del_flag`,`create_by`,`create_time`)
|
||||
VALUES
|
||||
('mxpsregauditact00001','mxpsregaudit00000002','审核环节同步','REGISTRY_STAGE_SYNC',
|
||||
'{"visualType":"REGISTRY_STAGE_SYNC","stage":"audit","expectedFrom":"proofread"}',
|
||||
1,'stop',1,0,'admin',NOW());
|
||||
|
||||
-- ⑤ 密炼PS — 批准(全流程通过)
|
||||
INSERT IGNORE INTO `mes_xsl_integration_plan`
|
||||
(`id`,`plan_code`,`plan_name`,`source_table`,`registry_id`,`trigger_phase`,`trigger_stage`,`exec_mode`,`status`,`remark`,`del_flag`,`tenant_id`,`create_by`,`create_time`)
|
||||
SELECT
|
||||
'mxpsregapprove000003','mixer_ps_reg_approve','密炼PS-批准通过(注册中心同步)',
|
||||
'mes_xsl_mixer_ps_compile', r.id, 'onApprove', 'approve', 'async', '0',
|
||||
'无需Java回调:更新status=approve并写批准人/时间+审批痕迹', 0, 0, 'admin', NOW()
|
||||
FROM `mes_xsl_biz_doc_registry` r
|
||||
WHERE r.table_name='mes_xsl_mixer_ps_compile' AND r.del_flag=0 AND r.enabled=1
|
||||
LIMIT 1;
|
||||
|
||||
INSERT IGNORE INTO `mes_xsl_integration_action`
|
||||
(`id`,`plan_id`,`action_name`,`action_type`,`action_config`,`exec_order`,`on_fail`,`enabled`,`del_flag`,`create_by`,`create_time`)
|
||||
VALUES
|
||||
('mxpsregapproveact01','mxpsregapprove000003','批准环节同步','REGISTRY_STAGE_SYNC',
|
||||
'{"visualType":"REGISTRY_STAGE_SYNC","stage":"approve","expectedFrom":"audit"}',
|
||||
1,'stop',1,0,'admin',NOW());
|
||||
|
||||
-- ⑥ 密炼PS — 驳回回退编制
|
||||
INSERT IGNORE INTO `mes_xsl_integration_plan`
|
||||
(`id`,`plan_code`,`plan_name`,`source_table`,`registry_id`,`trigger_phase`,`trigger_stage`,`exec_mode`,`status`,`remark`,`del_flag`,`tenant_id`,`create_by`,`create_time`)
|
||||
SELECT
|
||||
'mxpsregreject000004','mixer_ps_reg_reject','密炼PS-驳回回退(注册中心同步)',
|
||||
'mes_xsl_mixer_ps_compile', r.id, 'onReject', NULL, 'async', '0',
|
||||
'无需Java回调:回退status=compile并清空环节痕迹', 0, 0, 'admin', NOW()
|
||||
FROM `mes_xsl_biz_doc_registry` r
|
||||
WHERE r.table_name='mes_xsl_mixer_ps_compile' AND r.del_flag=0 AND r.enabled=1
|
||||
LIMIT 1;
|
||||
|
||||
INSERT IGNORE INTO `mes_xsl_integration_action`
|
||||
(`id`,`plan_id`,`action_name`,`action_type`,`action_config`,`exec_order`,`on_fail`,`enabled`,`del_flag`,`create_by`,`create_time`)
|
||||
VALUES
|
||||
('mxpsregrejectact001','mxpsregreject000004','驳回回退编制','REGISTRY_STAGE_REVERT',
|
||||
'{"visualType":"REGISTRY_STAGE_REVERT","targetStage":"compile"}',
|
||||
1,'stop',1,0,'admin',NOW());
|
||||
@@ -0,0 +1,7 @@
|
||||
-- 【XSLMES-20260605-K8R4】台账增加 node_activity_map 字段
|
||||
-- 存储 processForecast 结果:JSON数组,每项含 approvalMethod/totalActioners/completionAt
|
||||
-- completionAt = 累计已处理任务数边界,用于会签/依次审批多人等待完成判断
|
||||
SET NAMES utf8mb4;
|
||||
|
||||
ALTER TABLE `mes_xsl_approval_record`
|
||||
ADD COLUMN `node_activity_map` TEXT NULL COMMENT '钉钉节点活动映射(processForecast结果,JSON数组,含completionAt幂等边界)';
|
||||
@@ -0,0 +1,2 @@
|
||||
-- 用户表新增钉钉用户ID字段
|
||||
ALTER TABLE sys_user ADD COLUMN ding_user_id VARCHAR(100) DEFAULT NULL COMMENT '钉钉用户ID';
|
||||
@@ -0,0 +1,31 @@
|
||||
-- 【混炼示方】主表新增状态字段,复用配合示方状态字典
|
||||
-- author: cursor date: 2026-06-08 for:【XSLMES-20260608-A01】
|
||||
SET NAMES utf8mb4;
|
||||
SET @db = DATABASE();
|
||||
|
||||
SET @sql = IF(
|
||||
(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'mes_xsl_mixing_spec' AND COLUMN_NAME = 'status') = 0,
|
||||
'ALTER TABLE `mes_xsl_mixing_spec` ADD COLUMN `status` varchar(32) DEFAULT ''compile'' COMMENT ''状态(字典xslmes_formula_spec_status)'' AFTER `change_date`',
|
||||
'SELECT 1'
|
||||
);
|
||||
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
|
||||
|
||||
-- 按已有审批痕迹回填历史数据状态
|
||||
UPDATE `mes_xsl_mixing_spec` SET `status` = 'obsolete' WHERE `del_flag` = 1;
|
||||
UPDATE `mes_xsl_mixing_spec` SET `status` = 'recognition_pass' WHERE `del_flag` = 0 AND `approve_time` IS NOT NULL;
|
||||
UPDATE `mes_xsl_mixing_spec` SET `status` = 'review_pass' WHERE `del_flag` = 0 AND `approve_time` IS NULL AND `audit_time` IS NOT NULL;
|
||||
UPDATE `mes_xsl_mixing_spec` SET `status` = 'submit' WHERE `del_flag` = 0 AND `approve_time` IS NULL AND `audit_time` IS NULL AND `proofread_time` IS NOT NULL;
|
||||
|
||||
-- 混炼示方注册中心默认开启三环节并绑定 status 字段
|
||||
UPDATE `mes_xsl_biz_doc_registry`
|
||||
SET `enabled_stages` = 'proofread,audit,approve',
|
||||
`status_field` = 'status',
|
||||
`proofread_by_field` = 'proofread_by',
|
||||
`proofread_time_field` = 'proofread_time',
|
||||
`audit_by_field` = 'audit_by',
|
||||
`audit_time_field` = 'audit_time',
|
||||
`approve_by_field` = 'approve_by',
|
||||
`approve_time_field` = 'approve_time',
|
||||
`update_by` = 'admin',
|
||||
`update_time` = NOW()
|
||||
WHERE `doc_code` = 'mixing_spec' AND `del_flag` = 0;
|
||||
@@ -0,0 +1,5 @@
|
||||
-- 审批注册中心:增加列表接口路径字段,用于 ResponseBodyAdvice 自动注入审批痕迹字段
|
||||
ALTER TABLE mes_xsl_biz_doc_registry
|
||||
ADD COLUMN list_api_path VARCHAR(500) DEFAULT NULL
|
||||
COMMENT '列表接口路径(多个逗号分隔,如/xslmes/mesFormulaSpec/list),配置后自动注入审批痕迹字段到响应'
|
||||
AFTER approve_time_field;
|
||||
@@ -0,0 +1,28 @@
|
||||
-- 审批注册中心:移除操作人/时间字段配置列
|
||||
-- 操作人/时间统一由 mes_xsl_approval_trace 痕迹表承载,业务表只保留状态字段
|
||||
-- author: GHT date: 2026-06-09 for:【审批注册中心】业务表只写状态,操作人/时间由痕迹表承载
|
||||
SET @db = DATABASE();
|
||||
|
||||
SET @sql = IF((SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='mes_xsl_biz_doc_registry' AND COLUMN_NAME='proofread_by_field')>0,
|
||||
'ALTER TABLE `mes_xsl_biz_doc_registry` DROP COLUMN `proofread_by_field`','SELECT 1');
|
||||
PREPARE s FROM @sql; EXECUTE s; DEALLOCATE PREPARE s;
|
||||
|
||||
SET @sql = IF((SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='mes_xsl_biz_doc_registry' AND COLUMN_NAME='proofread_time_field')>0,
|
||||
'ALTER TABLE `mes_xsl_biz_doc_registry` DROP COLUMN `proofread_time_field`','SELECT 1');
|
||||
PREPARE s FROM @sql; EXECUTE s; DEALLOCATE PREPARE s;
|
||||
|
||||
SET @sql = IF((SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='mes_xsl_biz_doc_registry' AND COLUMN_NAME='audit_by_field')>0,
|
||||
'ALTER TABLE `mes_xsl_biz_doc_registry` DROP COLUMN `audit_by_field`','SELECT 1');
|
||||
PREPARE s FROM @sql; EXECUTE s; DEALLOCATE PREPARE s;
|
||||
|
||||
SET @sql = IF((SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='mes_xsl_biz_doc_registry' AND COLUMN_NAME='audit_time_field')>0,
|
||||
'ALTER TABLE `mes_xsl_biz_doc_registry` DROP COLUMN `audit_time_field`','SELECT 1');
|
||||
PREPARE s FROM @sql; EXECUTE s; DEALLOCATE PREPARE s;
|
||||
|
||||
SET @sql = IF((SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='mes_xsl_biz_doc_registry' AND COLUMN_NAME='approve_by_field')>0,
|
||||
'ALTER TABLE `mes_xsl_biz_doc_registry` DROP COLUMN `approve_by_field`','SELECT 1');
|
||||
PREPARE s FROM @sql; EXECUTE s; DEALLOCATE PREPARE s;
|
||||
|
||||
SET @sql = IF((SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='mes_xsl_biz_doc_registry' AND COLUMN_NAME='approve_time_field')>0,
|
||||
'ALTER TABLE `mes_xsl_biz_doc_registry` DROP COLUMN `approve_time_field`','SELECT 1');
|
||||
PREPARE s FROM @sql; EXECUTE s; DEALLOCATE PREPARE s;
|
||||
@@ -0,0 +1,89 @@
|
||||
-- =============================================
|
||||
-- 钉钉回调日志表 mes_xsl_ding_callback_log
|
||||
-- =============================================
|
||||
|
||||
CREATE TABLE `mes_xsl_ding_callback_log` (
|
||||
`id` varchar(36) NOT NULL COMMENT '主键',
|
||||
`event_id` varchar(100) DEFAULT NULL COMMENT '钉钉事件ID',
|
||||
`event_type` varchar(50) DEFAULT NULL COMMENT '事件类型(bpms_instance_change/bpms_task_change)',
|
||||
`process_instance_id` varchar(100) DEFAULT NULL COMMENT '审批实例ID',
|
||||
`raw_data` text DEFAULT NULL COMMENT '原始推送数据JSON',
|
||||
`received_time` datetime DEFAULT NULL COMMENT '接收时间',
|
||||
`processed` tinyint(1) DEFAULT 0 COMMENT '是否已处理集成方案(0否1是)',
|
||||
`process_remark` varchar(500) DEFAULT NULL COMMENT '处理备注',
|
||||
`biz_table` varchar(100) DEFAULT NULL COMMENT '关联业务表',
|
||||
`biz_data_id` varchar(100) DEFAULT NULL COMMENT '关联业务记录ID',
|
||||
`record_id` varchar(100) DEFAULT NULL COMMENT '关联审批台账ID',
|
||||
`create_by` varchar(50) DEFAULT NULL COMMENT '创建人',
|
||||
`create_time` datetime DEFAULT NULL COMMENT '创建日期',
|
||||
`update_by` varchar(50) DEFAULT NULL COMMENT '更新人',
|
||||
`update_time` datetime DEFAULT NULL COMMENT '更新日期',
|
||||
`del_flag` tinyint(1) DEFAULT 0 COMMENT '逻辑删除 0正常 1删除',
|
||||
`tenant_id` int DEFAULT 0 COMMENT '租户ID',
|
||||
`sys_org_code` varchar(64) DEFAULT NULL COMMENT '所属部门',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_ding_cb_log_instance` (`process_instance_id`),
|
||||
KEY `idx_ding_cb_log_event` (`event_id`),
|
||||
KEY `idx_ding_cb_log_processed` (`processed`),
|
||||
KEY `idx_ding_cb_log_received` (`received_time`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='钉钉回调日志';
|
||||
|
||||
-- =============================================
|
||||
-- 菜单权限(父节点:178046026420801 MESToDing审批配置)
|
||||
-- =============================================
|
||||
|
||||
INSERT INTO `sys_permission`
|
||||
(id, parent_id, name, url, component, component_name, redirect, menu_type,
|
||||
perms, perms_type, sort_no, always_show, icon, is_route, is_leaf, keep_alive,
|
||||
hidden, hide_tab, description, status, del_flag, rule_flag, create_by, create_time,
|
||||
update_by, update_time, internal_or_external)
|
||||
VALUES
|
||||
-- 主菜单页面
|
||||
('178098992722901', '178046026420801', '钉钉回调日志', '/xslmes/mesXslDingCallbackLogList',
|
||||
'xslmes/dingCallbackLog/MesXslDingCallbackLogList', 'MesXslDingCallbackLogList',
|
||||
NULL, 0, NULL, '1', 6, 0, NULL, 1, 0, 0, 0, 0, NULL, '1', 0, 0,
|
||||
'admin', NOW(), NULL, NULL, 0),
|
||||
|
||||
-- 添加按钮
|
||||
('178098992722902', '178098992722901', '添加', NULL, NULL, NULL, NULL, 2,
|
||||
'xslmes:mes_xsl_ding_callback_log:add', '1', 1, 0, NULL, 1, 1, 0, 0, 0,
|
||||
NULL, '1', 0, 0, 'admin', NOW(), NULL, NULL, 0),
|
||||
|
||||
-- 编辑按钮
|
||||
('178098992722903', '178098992722901', '编辑', NULL, NULL, NULL, NULL, 2,
|
||||
'xslmes:mes_xsl_ding_callback_log:edit', '1', 2, 0, NULL, 1, 1, 0, 0, 0,
|
||||
NULL, '1', 0, 0, 'admin', NOW(), NULL, NULL, 0),
|
||||
|
||||
-- 删除按钮
|
||||
('178098992722904', '178098992722901', '删除', NULL, NULL, NULL, NULL, 2,
|
||||
'xslmes:mes_xsl_ding_callback_log:delete', '1', 3, 0, NULL, 1, 1, 0, 0, 0,
|
||||
NULL, '1', 0, 0, 'admin', NOW(), NULL, NULL, 0),
|
||||
|
||||
-- 批量删除按钮
|
||||
('178098992722905', '178098992722901', '批量删除', NULL, NULL, NULL, NULL, 2,
|
||||
'xslmes:mes_xsl_ding_callback_log:deleteBatch', '1', 4, 0, NULL, 1, 1, 0, 0, 0,
|
||||
NULL, '1', 0, 0, 'admin', NOW(), NULL, NULL, 0),
|
||||
|
||||
-- 导出按钮
|
||||
('178098992722906', '178098992722901', '导出', NULL, NULL, NULL, NULL, 2,
|
||||
'xslmes:mes_xsl_ding_callback_log:exportXls', '1', 5, 0, NULL, 1, 1, 0, 0, 0,
|
||||
NULL, '1', 0, 0, 'admin', NOW(), NULL, NULL, 0),
|
||||
|
||||
-- 导入按钮
|
||||
('178098992722907', '178098992722901', '导入', NULL, NULL, NULL, NULL, 2,
|
||||
'xslmes:mes_xsl_ding_callback_log:importExcel', '1', 6, 0, NULL, 1, 1, 0, 0, 0,
|
||||
NULL, '1', 0, 0, 'admin', NOW(), NULL, NULL, 0);
|
||||
|
||||
-- =============================================
|
||||
-- 为 admin 角色授权(角色ID: f6817f48af4fb3af11b9e8bf182f618b)
|
||||
-- =============================================
|
||||
|
||||
INSERT INTO `sys_role_permission` (id, role_id, permission_id, data_rule_ids)
|
||||
VALUES
|
||||
(REPLACE(UUID(),'-',''), 'f6817f48af4fb3af11b9e8bf182f618b', '178098992722901', NULL),
|
||||
(REPLACE(UUID(),'-',''), 'f6817f48af4fb3af11b9e8bf182f618b', '178098992722902', NULL),
|
||||
(REPLACE(UUID(),'-',''), 'f6817f48af4fb3af11b9e8bf182f618b', '178098992722903', NULL),
|
||||
(REPLACE(UUID(),'-',''), 'f6817f48af4fb3af11b9e8bf182f618b', '178098992722904', NULL),
|
||||
(REPLACE(UUID(),'-',''), 'f6817f48af4fb3af11b9e8bf182f618b', '178098992722905', NULL),
|
||||
(REPLACE(UUID(),'-',''), 'f6817f48af4fb3af11b9e8bf182f618b', '178098992722906', NULL),
|
||||
(REPLACE(UUID(),'-',''), 'f6817f48af4fb3af11b9e8bf182f618b', '178098992722907', NULL);
|
||||
@@ -0,0 +1,6 @@
|
||||
-- GHT 20260609 【钉钉Stream开发】第三方配置页可视化:Stream 接收节点白名单
|
||||
ALTER TABLE sys_third_app_config
|
||||
ADD COLUMN stream_receiver_enabled TINYINT(1) NULL DEFAULT NULL COMMENT '是否限制仅指定节点接收Stream(0-否,1-是,NULL-沿用YAML)' AFTER stream_enabled,
|
||||
ADD COLUMN stream_designated_ips VARCHAR(1000) NULL DEFAULT NULL COMMENT '允许接收Stream的IP白名单(逗号分隔)' AFTER stream_receiver_enabled,
|
||||
ADD COLUMN stream_designated_hosts VARCHAR(500) NULL DEFAULT NULL COMMENT '允许接收Stream的主机名白名单(逗号分隔)' AFTER stream_designated_ips,
|
||||
ADD COLUMN stream_cluster_mode TINYINT(1) NULL DEFAULT NULL COMMENT 'Stream集群Redis选主(0-否,1-是,NULL-沿用YAML)' AFTER stream_designated_hosts;
|
||||
@@ -0,0 +1,7 @@
|
||||
-- TCU温度条件:新增是否附加、重量字段
|
||||
-- author: GHT date: 2026-06-10 for:【混炼示方】TCU温度条件新增是否附加/重量字段
|
||||
SET @db = DATABASE();
|
||||
|
||||
SET @sql = IF((SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='mes_xsl_mixing_spec_tcu' AND COLUMN_NAME='is_attach')=0,
|
||||
'ALTER TABLE `mes_xsl_mixing_spec_tcu` ADD COLUMN `is_attach` varchar(1) DEFAULT ''0'' COMMENT ''是否附加(字典yn)'' AFTER `drug_weigh_pos`, ADD COLUMN `attach_weight` decimal(18,6) DEFAULT NULL COMMENT ''附加重量'' AFTER `is_attach`','SELECT 1');
|
||||
PREPARE s FROM @sql; EXECUTE s; DEALLOCATE PREPARE s;
|
||||
@@ -0,0 +1,17 @@
|
||||
-- IM 工作通知公众号系统账号(审批等系统消息统一从此账号推送)
|
||||
SET NAMES utf8mb4;
|
||||
|
||||
INSERT IGNORE INTO `sys_user` (
|
||||
`id`, `username`, `realname`, `password`, `salt`, `status`, `del_flag`, `activiti_sync`, `create_by`, `create_time`
|
||||
) VALUES (
|
||||
'1995000000000000999',
|
||||
'im_work_notify',
|
||||
'工作通知',
|
||||
'disabled',
|
||||
'',
|
||||
2,
|
||||
0,
|
||||
1,
|
||||
'system',
|
||||
NOW()
|
||||
);
|
||||
Reference in New Issue
Block a user