feat: 归档L03与L09审批发布能力

- 新增统一审批中心与审批管理页面,支持流程配置、审批详情与角色/用户审批对象

- 接入聊天助手、知识库、工作流的发布与删除审批,并补齐发布态校验与快照展示
This commit is contained in:
2026-04-07 14:41:52 +08:00
parent 7e7c236c2a
commit 3f128e977a
138 changed files with 13035 additions and 346 deletions

View File

@@ -0,0 +1,66 @@
package tech.easyflow.approval.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.context.expression.MethodBasedEvaluationContext;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.stereotype.Component;
import tech.easyflow.approval.annotation.ApprovalAction;
import tech.easyflow.approval.service.ApprovalActionFacade;
import tech.easyflow.common.satoken.util.SaTokenUtil;
import java.lang.reflect.Method;
import java.math.BigInteger;
/**
* 提审动作切面。
*/
@Aspect
@Component
public class ApprovalActionAspect {
private final ApprovalActionFacade approvalActionFacade;
private final ExpressionParser expressionParser = new SpelExpressionParser();
private final ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
public ApprovalActionAspect(ApprovalActionFacade approvalActionFacade) {
this.approvalActionFacade = approvalActionFacade;
}
/**
* 拦截提审方法,先执行资源校验,再统一发起审批。
*
* @param joinPoint 切点
* @param approvalAction 注解
* @return 审批实例 ID
* @throws Throwable 执行异常
*/
@Around("@annotation(approvalAction)")
public Object doAround(ProceedingJoinPoint joinPoint, ApprovalAction approvalAction) throws Throwable {
Object identifier = resolveIdentifier(joinPoint, approvalAction.idExpr());
BigInteger resourceId = identifier == null ? null : new BigInteger(String.valueOf(identifier));
joinPoint.proceed();
return approvalActionFacade.submit(
approvalAction.resourceType(),
resourceId,
approvalAction.actionType(),
SaTokenUtil.getLoginAccount().getId()
);
}
private Object resolveIdentifier(ProceedingJoinPoint joinPoint, String idExpr) {
Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
MethodBasedEvaluationContext context = new MethodBasedEvaluationContext(
joinPoint.getTarget(),
method,
joinPoint.getArgs(),
parameterNameDiscoverer
);
return expressionParser.parseExpression(idExpr).getValue(context);
}
}

View File

@@ -0,0 +1,63 @@
package tech.easyflow.approval.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.context.expression.MethodBasedEvaluationContext;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.stereotype.Component;
import tech.easyflow.approval.annotation.RequirePublishedAccess;
import tech.easyflow.approval.service.ApprovalActionFacade;
import java.lang.reflect.Method;
/**
* 已发布访问门禁切面。
*/
@Aspect
@Component
public class RequirePublishedAccessAspect {
private final ApprovalActionFacade approvalActionFacade;
private final ExpressionParser expressionParser = new SpelExpressionParser();
private final ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
public RequirePublishedAccessAspect(ApprovalActionFacade approvalActionFacade) {
this.approvalActionFacade = approvalActionFacade;
}
/**
* 执行发布态门禁校验。
*
* @param joinPoint 切点
* @param requirePublishedAccess 注解
* @return 原方法返回值
* @throws Throwable 执行异常
*/
@Around("@annotation(requirePublishedAccess)")
public Object doAround(ProceedingJoinPoint joinPoint,
RequirePublishedAccess requirePublishedAccess) throws Throwable {
Object identifier = resolveIdentifier(joinPoint, requirePublishedAccess.idExpr());
approvalActionFacade.assertPublishedAccess(
requirePublishedAccess.resourceType(),
identifier,
requirePublishedAccess.denyMessage()
);
return joinPoint.proceed();
}
private Object resolveIdentifier(ProceedingJoinPoint joinPoint, String idExpr) {
Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
MethodBasedEvaluationContext context = new MethodBasedEvaluationContext(
joinPoint.getTarget(),
method,
joinPoint.getArgs(),
parameterNameDiscoverer
);
return expressionParser.parseExpression(idExpr).getValue(context);
}
}