loginDomain修正
This commit is contained in:
@@ -67,6 +67,21 @@
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
<!-- Spring Cloud Nacos 服务发现(Gateway 路由需要) -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>com.alibaba.nacos</groupId>
|
||||
<artifactId>nacos-logback-adapter-12</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>com.alibaba.nacos</groupId>
|
||||
<artifactId>logback-adapter</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mybatis.spring.boot</groupId>
|
||||
<artifactId>mybatis-spring-boot-starter</artifactId>
|
||||
|
||||
@@ -40,7 +40,7 @@ public class AgentController {
|
||||
* @since 2025-12-17
|
||||
*/
|
||||
@PostMapping
|
||||
@PreAuthorize("@ss.hasPermi('ai:agent:create')")
|
||||
@PreAuthorize("hasAuthority('ai:agent:create')")
|
||||
public ResultDomain<TbAgent> createAgent(@RequestBody TbAgent agent) {
|
||||
log.info("创建智能体: name={}", agent.getName());
|
||||
// 参数校验
|
||||
@@ -62,7 +62,7 @@ public class AgentController {
|
||||
* @since 2025-12-17
|
||||
*/
|
||||
@PutMapping
|
||||
@PreAuthorize("@ss.hasPermi('ai:agent:update')")
|
||||
@PreAuthorize("hasAuthority('ai:agent:update')")
|
||||
public ResultDomain<TbAgent> updateAgent(@RequestBody TbAgent agent) {
|
||||
log.info("更新智能体: agentId={}", agent.getAgentId());
|
||||
// 参数校验
|
||||
@@ -85,7 +85,7 @@ public class AgentController {
|
||||
* @since 2025-12-17
|
||||
*/
|
||||
@DeleteMapping("/{agentId}")
|
||||
@PreAuthorize("@ss.hasPermi('ai:agent:delete')")
|
||||
@PreAuthorize("hasAuthority('ai:agent:delete')")
|
||||
public ResultDomain<TbAgent> deleteAgent(@PathVariable("agentId") @NotNull String agentId) {
|
||||
log.info("删除智能体: agentId={}", agentId);
|
||||
TbAgent agent = new TbAgent();
|
||||
@@ -100,7 +100,7 @@ public class AgentController {
|
||||
* @since 2025-12-17
|
||||
*/
|
||||
@GetMapping("/{agentId}")
|
||||
@PreAuthorize("@ss.hasPermi('ai:agent:view')")
|
||||
@PreAuthorize("hasAuthority('ai:agent:view')")
|
||||
public ResultDomain<TbAgent> getAgent(@PathVariable("agentId") @NotNull String agentId) {
|
||||
log.info("获取智能体: agentId={}", agentId);
|
||||
ResultDomain<TbAgent> agentResult = agentService.selectAgentById(agentId);
|
||||
@@ -117,7 +117,7 @@ public class AgentController {
|
||||
* @since 2025-12-17
|
||||
*/
|
||||
@PostMapping("/page")
|
||||
@PreAuthorize("@ss.hasPermi('ai:agent:view')")
|
||||
@PreAuthorize("hasAuthority('ai:agent:view')")
|
||||
public ResultDomain<TbAgent> getAgentPage(@RequestBody PageRequest<TbAgent> pageRequest) {
|
||||
log.info("分页查询智能体");
|
||||
// 参数校验(支持嵌套属性路径)
|
||||
@@ -139,7 +139,7 @@ public class AgentController {
|
||||
* @since 2025-12-17
|
||||
*/
|
||||
@GetMapping("/list")
|
||||
@PreAuthorize("@ss.hasPermi('ai:agent:view')")
|
||||
@PreAuthorize("hasAuthority('ai:agent:view')")
|
||||
public ResultDomain<TbAgent> getAgentList(TbAgent tbAgent) {
|
||||
log.info("获取智能体列表");
|
||||
return agentService.getAgentList(tbAgent);
|
||||
|
||||
@@ -54,7 +54,7 @@ public class KnowledgeController {
|
||||
* @author yslg
|
||||
* @since 2025-12-18
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermission('ai:knowledge:create')")
|
||||
@PreAuthorize("hasAuthority('ai:knowledge:create')")
|
||||
@PostMapping
|
||||
public ResultDomain<TbKnowledge> createKnowledge(@RequestBody TbKnowledge knowledge) {
|
||||
ValidationResult result = ValidationUtils.validate(knowledge, Arrays.asList(
|
||||
@@ -75,7 +75,7 @@ public class KnowledgeController {
|
||||
* @author yslg
|
||||
* @since 2025-12-18
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermission('ai:knowledge:update')")
|
||||
@PreAuthorize("hasAuthority('ai:knowledge:update')")
|
||||
@PutMapping
|
||||
public ResultDomain<TbKnowledge> updateKnowledge(@RequestBody @Valid TbKnowledge knowledge) {
|
||||
ValidationResult result = ValidationUtils.validate(knowledge, Arrays.asList(
|
||||
@@ -97,7 +97,7 @@ public class KnowledgeController {
|
||||
* @author yslg
|
||||
* @since 2025-12-18
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermission('ai:knowledge:delete')")
|
||||
@PreAuthorize("hasAuthority('ai:knowledge:delete')")
|
||||
@DeleteMapping("/{knowledgeId}")
|
||||
public ResultDomain<Boolean> deleteKnowledge(@PathVariable("knowledgeId") @NotBlank String knowledgeId) {
|
||||
logger.info("删除知识库: knowledgeId={}", knowledgeId);
|
||||
@@ -110,7 +110,7 @@ public class KnowledgeController {
|
||||
* @author yslg
|
||||
* @since 2025-12-18
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermission('ai:knowledge:view')")
|
||||
@PreAuthorize("hasAuthority('ai:knowledge:view')")
|
||||
@GetMapping("/{knowledgeId}")
|
||||
public ResultDomain<TbKnowledge> getKnowledge(@PathVariable("knowledgeId") @NotBlank String knowledgeId) {
|
||||
logger.info("获取知识库: knowledgeId={}", knowledgeId);
|
||||
@@ -123,7 +123,7 @@ public class KnowledgeController {
|
||||
* @author yslg
|
||||
* @since 2025-12-18
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermission('ai:knowledge:view')")
|
||||
@PreAuthorize("hasAuthority('ai:knowledge:view')")
|
||||
@PostMapping("/list")
|
||||
public ResultDomain<TbKnowledge> listKnowledges(@RequestBody(required = false) TbKnowledge filter) {
|
||||
logger.info("查询知识库列表");
|
||||
@@ -136,7 +136,7 @@ public class KnowledgeController {
|
||||
* @author yslg
|
||||
* @since 2025-12-18
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermission('ai:knowledge:view')")
|
||||
@PreAuthorize("hasAuthority('ai:knowledge:view')")
|
||||
@PostMapping("/page")
|
||||
public ResultDomain<TbKnowledge> pageKnowledges(@RequestBody @Valid PageRequest<TbKnowledge> pageRequest) {
|
||||
logger.info("分页查询知识库");
|
||||
@@ -149,7 +149,7 @@ public class KnowledgeController {
|
||||
* @author yslg
|
||||
* @since 2025-12-18
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermission('ai:knowledge:view')")
|
||||
@PreAuthorize("hasAuthority('ai:knowledge:view')")
|
||||
@GetMapping("/{knowledgeId}/stats")
|
||||
public ResultDomain<TbKnowledge> getKnowledgeStats(@PathVariable("knowledgeId") @NotBlank String knowledgeId) {
|
||||
logger.info("获取知识库统计: knowledgeId={}", knowledgeId);
|
||||
@@ -164,7 +164,7 @@ public class KnowledgeController {
|
||||
* @author yslg
|
||||
* @since 2025-12-18
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermission('ai:knowledge:file:view')")
|
||||
@PreAuthorize("hasAuthority('ai:knowledge:file:view')")
|
||||
@GetMapping("/{knowledgeId}/documents")
|
||||
public ResultDomain<Map<String, Object>> getDocumentList(
|
||||
@PathVariable("knowledgeId") @NotBlank String knowledgeId,
|
||||
@@ -182,7 +182,7 @@ public class KnowledgeController {
|
||||
* @author yslg
|
||||
* @since 2025-12-18
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermission('ai:knowledge:file:upload')")
|
||||
@PreAuthorize("hasAuthority('ai:knowledge:file:upload')")
|
||||
@PostMapping(value = "/file/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
public ResultDomain<TbKnowledgeFile> uploadToKnowledge(
|
||||
@RequestParam("file") @NotNull MultipartFile file,
|
||||
@@ -200,7 +200,7 @@ public class KnowledgeController {
|
||||
* @author yslg
|
||||
* @since 2025-12-18
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermission('ai:knowledge:file:upload')")
|
||||
@PreAuthorize("hasAuthority('ai:knowledge:file:upload')")
|
||||
@PostMapping(value = "/file/batch-upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
public ResultDomain<TbKnowledgeFile> batchUploadToKnowledge(
|
||||
@RequestParam("files") @NotEmpty List<MultipartFile> files,
|
||||
@@ -218,7 +218,7 @@ public class KnowledgeController {
|
||||
* @author yslg
|
||||
* @since 2025-12-18
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermission('ai:knowledge:file:update')")
|
||||
@PreAuthorize("hasAuthority('ai:knowledge:file:update')")
|
||||
@PutMapping(value = "/file/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
public ResultDomain<TbKnowledgeFile> updateFile(
|
||||
@RequestParam("file") @NotNull MultipartFile file,
|
||||
@@ -234,7 +234,7 @@ public class KnowledgeController {
|
||||
* @author yslg
|
||||
* @since 2025-12-18
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermission('ai:knowledge:file:delete')")
|
||||
@PreAuthorize("hasAuthority('ai:knowledge:file:delete')")
|
||||
@DeleteMapping("/file/{fileId}")
|
||||
public ResultDomain<Boolean> deleteFile(@PathVariable("fileId") @NotBlank String fileId) {
|
||||
logger.info("删除知识库文件: fileId={}", fileId);
|
||||
@@ -247,7 +247,7 @@ public class KnowledgeController {
|
||||
* @author yslg
|
||||
* @since 2025-12-18
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermission('ai:knowledge:file:view')")
|
||||
@PreAuthorize("hasAuthority('ai:knowledge:file:view')")
|
||||
@GetMapping("/file/{fileId}/history")
|
||||
public ResultDomain<TbKnowledgeFile> getFileHistory(@PathVariable("fileId") @NotBlank String fileRootId) {
|
||||
logger.info("获取文件历史: fileRootId={}", fileRootId);
|
||||
@@ -263,7 +263,7 @@ public class KnowledgeController {
|
||||
* @author yslg
|
||||
* @since 2025-12-18
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermission('ai:dify:segment:view')")
|
||||
@PreAuthorize("hasAuthority('ai:dify:segment:view')")
|
||||
@GetMapping("/datasets/{datasetId}/documents/{documentId}/segments")
|
||||
public ResultDomain<JSONObject> getDocumentSegments(
|
||||
@PathVariable("datasetId") @NotBlank String datasetId,
|
||||
@@ -280,7 +280,7 @@ public class KnowledgeController {
|
||||
* @author yslg
|
||||
* @since 2025-12-18
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermission('ai:dify:segment:create')")
|
||||
@PreAuthorize("hasAuthority('ai:dify:segment:create')")
|
||||
@PostMapping("/datasets/{datasetId}/documents/{documentId}/segments")
|
||||
public ResultDomain<String> createSegment(
|
||||
@PathVariable("datasetId") @NotBlank String datasetId,
|
||||
@@ -299,7 +299,7 @@ public class KnowledgeController {
|
||||
* @author yslg
|
||||
* @since 2025-12-18
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermission('ai:dify:segment:update')")
|
||||
@PreAuthorize("hasAuthority('ai:dify:segment:update')")
|
||||
@PatchMapping("/datasets/{datasetId}/documents/{documentId}/segments/{segmentId}")
|
||||
public ResultDomain<String> updateSegment(
|
||||
@PathVariable("datasetId") @NotBlank String datasetId,
|
||||
@@ -318,7 +318,7 @@ public class KnowledgeController {
|
||||
* @author yslg
|
||||
* @since 2025-12-18
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermission('ai:dify:segment:delete')")
|
||||
@PreAuthorize("hasAuthority('ai:dify:segment:delete')")
|
||||
@DeleteMapping("/datasets/{datasetId}/documents/{documentId}/segments/{segmentId}")
|
||||
public ResultDomain<String> deleteSegment(
|
||||
@PathVariable("datasetId") @NotBlank String datasetId,
|
||||
@@ -338,7 +338,7 @@ public class KnowledgeController {
|
||||
* @author yslg
|
||||
* @since 2025-12-18
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermission('ai:dify:document:status')")
|
||||
@PreAuthorize("hasAuthority('ai:dify:document:status')")
|
||||
@PatchMapping("/datasets/{datasetId}/documents/{action}/status")
|
||||
public ResultDomain<String> updateDocumentStatus(
|
||||
@PathVariable("datasetId") @NotBlank String datasetId,
|
||||
|
||||
@@ -17,7 +17,17 @@ import org.springframework.web.filter.OncePerRequestFilter;
|
||||
import org.xyzh.common.auth.contants.AuthContants;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.xyzh.common.core.domain.LoginDomain;
|
||||
import org.xyzh.common.dto.sys.TbSysPermissionDTO;
|
||||
import org.xyzh.common.redis.service.RedisService;
|
||||
|
||||
/**
|
||||
* @description Gateway 认证模式配置 - 信任 Gateway 传递的用户信息
|
||||
@@ -30,7 +40,7 @@ import java.util.Collections;
|
||||
@Configuration
|
||||
@ConditionalOnProperty(name = "auth.gateway-mode", havingValue = "true")
|
||||
public class GatewayAuthConfig {
|
||||
private static final Logger log = LoggerFactory.getLogger(GatewayAuthConfig.class);
|
||||
private static final Logger logger = LoggerFactory.getLogger(GatewayAuthConfig.class);
|
||||
|
||||
/**
|
||||
* Gateway 信任过滤器 - 从请求头获取用户信息
|
||||
@@ -38,7 +48,7 @@ public class GatewayAuthConfig {
|
||||
*/
|
||||
@Bean
|
||||
public GatewayTrustFilter gatewayTrustFilter() {
|
||||
log.info("启用 Gateway 认证模式,微服务将信任 Gateway 传递的用户信息");
|
||||
logger.info("启用 Gateway 认证模式,微服务将信任 Gateway 传递的用户信息");
|
||||
return new GatewayTrustFilter();
|
||||
}
|
||||
|
||||
@@ -46,7 +56,12 @@ public class GatewayAuthConfig {
|
||||
* Gateway 信任过滤器实现
|
||||
*/
|
||||
public static class GatewayTrustFilter extends OncePerRequestFilter {
|
||||
private static final Logger log = LoggerFactory.getLogger(GatewayTrustFilter.class);
|
||||
private static final Logger logger = LoggerFactory.getLogger(GatewayTrustFilter.class);
|
||||
private static final String LOGIN_TOKEN_PREFIX = "login:token:";
|
||||
private static final String BEARER_PREFIX = "Bearer ";
|
||||
|
||||
@Autowired
|
||||
private RedisService redisService;
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(@NonNull HttpServletRequest request,
|
||||
@@ -59,12 +74,12 @@ public class GatewayAuthConfig {
|
||||
String username = request.getHeader(AuthContants.USERNAME_ATTRIBUTE);
|
||||
|
||||
if (StringUtils.hasText(userId)) {
|
||||
// 构造简化的 Principal(使用 userId 作为身份标识)
|
||||
// 注意:完整的 LoginDomain 应该从 Redis 加载,这里只是基本身份验证
|
||||
// 从 Redis 获取用户权限
|
||||
List<GrantedAuthority> authorities = loadUserAuthorities(request);
|
||||
|
||||
// 设置到 Spring Security 上下文
|
||||
UsernamePasswordAuthenticationToken authentication =
|
||||
new UsernamePasswordAuthenticationToken(userId, null, Collections.emptyList());
|
||||
new UsernamePasswordAuthenticationToken(userId, null, authorities);
|
||||
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||
|
||||
// 同时将用户信息设置到 request attributes 中,供业务代码使用
|
||||
@@ -73,10 +88,55 @@ public class GatewayAuthConfig {
|
||||
request.setAttribute(AuthContants.USERNAME_ATTRIBUTE, username);
|
||||
}
|
||||
|
||||
log.debug("从 Gateway 获取用户信息: userId={}, username={}", userId, username);
|
||||
logger.info("从 Gateway 获取用户信息: userId={}, username={}, 权限数={}", userId, username, authorities.size());
|
||||
}
|
||||
|
||||
filterChain.doFilter(request, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 从 Redis 加载用户权限列表
|
||||
*/
|
||||
private List<GrantedAuthority> loadUserAuthorities(HttpServletRequest request) {
|
||||
List<GrantedAuthority> authorities = new ArrayList<>();
|
||||
|
||||
try {
|
||||
String authHeader = request.getHeader("Authorization");
|
||||
logger.info("Authorization header: {}", authHeader != null ? "Bearer ***" : "null");
|
||||
|
||||
if (StringUtils.hasText(authHeader) && authHeader.startsWith(BEARER_PREFIX)) {
|
||||
String token = authHeader.substring(BEARER_PREFIX.length());
|
||||
String cacheKey = LOGIN_TOKEN_PREFIX + token;
|
||||
Object obj = redisService.get(cacheKey);
|
||||
|
||||
logger.info("Redis key: {}, obj type: {}", cacheKey, obj != null ? obj.getClass().getName() : "null");
|
||||
|
||||
LoginDomain login = null;
|
||||
if (obj instanceof LoginDomain) {
|
||||
login = (LoginDomain) obj;
|
||||
} else if (obj instanceof String) {
|
||||
// Redis 返回的是 JSON 字符串,需要反序列化
|
||||
login = JSON.parseObject((String) obj, LoginDomain.class);
|
||||
logger.info("从 JSON 反序列化 LoginDomain");
|
||||
}
|
||||
|
||||
if (login != null) {
|
||||
if (login.getUserPermissions() != null) {
|
||||
for (TbSysPermissionDTO permission : login.getUserPermissions()) {
|
||||
// status 为 null 或 true 时都视为有效权限
|
||||
if (permission.getCode() != null && !Boolean.FALSE.equals(permission.getStatus())) {
|
||||
authorities.add(new SimpleGrantedAuthority(permission.getCode()));
|
||||
}
|
||||
}
|
||||
}
|
||||
logger.info("加载用户权限: {} 个", authorities.size());
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.warn("加载用户权限失败: {}", e.getMessage(), e);
|
||||
}
|
||||
|
||||
return authorities;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,8 @@ import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
import org.xyzh.common.core.domain.LoginDomain;
|
||||
import org.xyzh.common.redis.service.RedisService;
|
||||
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
@@ -49,6 +51,9 @@ public class LoginUtil {
|
||||
Object obj = instance.redisService.get(cacheKey);
|
||||
if (obj instanceof LoginDomain) {
|
||||
return (LoginDomain) obj;
|
||||
} else if (obj instanceof String) {
|
||||
// Redis 返回的是 JSON 字符串,需要反序列化
|
||||
return JSON.parseObject((String) obj, LoginDomain.class);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// 忽略异常
|
||||
|
||||
@@ -74,6 +74,16 @@
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>com.alibaba.nacos</groupId>
|
||||
<artifactId>nacos-logback-adapter-12</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>com.alibaba.nacos</groupId>
|
||||
<artifactId>logback-adapter</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!-- MinIO 对象存储 -->
|
||||
|
||||
@@ -65,6 +65,16 @@
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>com.alibaba.nacos</groupId>
|
||||
<artifactId>nacos-logback-adapter-12</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>com.alibaba.nacos</groupId>
|
||||
<artifactId>logback-adapter</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
||||
@@ -128,6 +128,16 @@
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
|
||||
<version>${nacos.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>com.alibaba.nacos</groupId>
|
||||
<artifactId>nacos-logback-adapter-12</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>com.alibaba.nacos</groupId>
|
||||
<artifactId>logback-adapter</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
|
||||
@@ -38,7 +38,7 @@ public class DeptRoleController {
|
||||
* @since 2025-11-10
|
||||
*/
|
||||
@PostMapping("/dept")
|
||||
@PreAuthorize("@ss.hasPermi('system:dept:create')")
|
||||
@PreAuthorize("hasAuthority('system:dept:create')")
|
||||
public ResultDomain<TbSysDeptDTO> createDept(@RequestBody TbSysDeptDTO deptDTO) {
|
||||
return deptRoleService.insertDept(deptDTO);
|
||||
}
|
||||
@@ -52,7 +52,7 @@ public class DeptRoleController {
|
||||
* @since 2025-11-10
|
||||
*/
|
||||
@PutMapping("/dept")
|
||||
@PreAuthorize("@ss.hasPermi('system:dept:edit')")
|
||||
@PreAuthorize("hasAuthority('system:dept:edit')")
|
||||
public ResultDomain<TbSysDeptDTO> updateDept(@RequestBody TbSysDeptDTO deptDTO) {
|
||||
return deptRoleService.updateDept(deptDTO);
|
||||
}
|
||||
@@ -65,7 +65,7 @@ public class DeptRoleController {
|
||||
* @since 2025-11-10
|
||||
*/
|
||||
@DeleteMapping("/dept")
|
||||
@PreAuthorize("@ss.hasPermi('system:dept:delete')")
|
||||
@PreAuthorize("hasAuthority('system:dept:delete')")
|
||||
public ResultDomain<Boolean> deleteDept(@RequestBody TbSysDeptDTO deptDTO) {
|
||||
return deptRoleService.deleteDept(deptDTO);
|
||||
}
|
||||
@@ -78,7 +78,7 @@ public class DeptRoleController {
|
||||
* @since 2025-11-10
|
||||
*/
|
||||
@GetMapping("/dept/page")
|
||||
@PreAuthorize("@ss.hasPermi('system:dept:view')")
|
||||
@PreAuthorize("hasAuthority('system:dept:view')")
|
||||
public ResultDomain<UserDeptRoleVO> getDeptPage(@RequestBody PageRequest<UserDeptRoleVO> pageRequest) {
|
||||
return deptRoleService.getDeptPage(pageRequest);
|
||||
}
|
||||
@@ -91,7 +91,7 @@ public class DeptRoleController {
|
||||
* @since 2025-11-10
|
||||
*/
|
||||
@GetMapping("/dept/list")
|
||||
@PreAuthorize("@ss.hasPermi('system:dept:view')")
|
||||
@PreAuthorize("hasAuthority('system:dept:view')")
|
||||
public ResultDomain<UserDeptRoleVO> getDeptList(@RequestBody UserDeptRoleVO filter) {
|
||||
return deptRoleService.getDeptList(filter);
|
||||
}
|
||||
@@ -105,7 +105,7 @@ public class DeptRoleController {
|
||||
* @since 2025-11-10
|
||||
*/
|
||||
@PostMapping("/role")
|
||||
@PreAuthorize("@ss.hasPermi('system:role:create')")
|
||||
@PreAuthorize("hasAuthority('system:role:create')")
|
||||
public ResultDomain<TbSysRoleDTO> createRole(@RequestBody TbSysRoleDTO roleDTO) {
|
||||
return deptRoleService.insertRole(roleDTO);
|
||||
}
|
||||
@@ -118,7 +118,7 @@ public class DeptRoleController {
|
||||
* @since 2025-11-10
|
||||
*/
|
||||
@PutMapping("/role")
|
||||
@PreAuthorize("@ss.hasPermi('system:role:edit')")
|
||||
@PreAuthorize("hasAuthority('system:role:edit')")
|
||||
public ResultDomain<TbSysRoleDTO> updateRole(@RequestBody TbSysRoleDTO roleDTO) {
|
||||
return deptRoleService.updateRole(roleDTO);
|
||||
}
|
||||
@@ -131,7 +131,7 @@ public class DeptRoleController {
|
||||
* @since 2025-11-10
|
||||
*/
|
||||
@DeleteMapping("/role")
|
||||
@PreAuthorize("@ss.hasPermi('system:role:delete')")
|
||||
@PreAuthorize("hasAuthority('system:role:delete')")
|
||||
public ResultDomain<Boolean> deleteRole(@RequestBody TbSysRoleDTO roleDTO) {
|
||||
return deptRoleService.deleteRole(roleDTO);
|
||||
}
|
||||
@@ -144,7 +144,7 @@ public class DeptRoleController {
|
||||
* @since 2025-11-10
|
||||
*/
|
||||
@GetMapping("/role/page")
|
||||
@PreAuthorize("@ss.hasPermi('system:role:view')")
|
||||
@PreAuthorize("hasAuthority('system:role:view')")
|
||||
public ResultDomain<UserDeptRoleVO> getRolePage(@RequestBody PageRequest<UserDeptRoleVO> pageRequest) {
|
||||
return deptRoleService.getRolePage(pageRequest);
|
||||
}
|
||||
@@ -157,7 +157,7 @@ public class DeptRoleController {
|
||||
* @since 2025-11-10
|
||||
*/
|
||||
@GetMapping("/role/list")
|
||||
@PreAuthorize("@ss.hasPermi('system:role:view')")
|
||||
@PreAuthorize("hasAuthority('system:role:view')")
|
||||
public ResultDomain<UserDeptRoleVO> getRoleList(@RequestBody UserDeptRoleVO filter) {
|
||||
return deptRoleService.getRoleList(filter);
|
||||
}
|
||||
@@ -171,7 +171,7 @@ public class DeptRoleController {
|
||||
* @since 2025-11-11
|
||||
*/
|
||||
@PostMapping("/rolePermission/bind")
|
||||
@PreAuthorize("@ss.hasPermi('system:permission:manage')")
|
||||
@PreAuthorize("hasAuthority('system:permission:manage')")
|
||||
public ResultDomain<PermissionVO> getRolePermission(@RequestBody PermissionVO permissionVO) {
|
||||
return deptRoleService.setRolePermission(permissionVO);
|
||||
}
|
||||
@@ -184,7 +184,7 @@ public class DeptRoleController {
|
||||
* @since 2025-11-11
|
||||
*/
|
||||
@PostMapping("/rolePermission/list")
|
||||
@PreAuthorize("@ss.hasPermi('system:permission:view')")
|
||||
@PreAuthorize("hasAuthority('system:permission:view')")
|
||||
public ResultDomain<PermissionVO> getRolePermissionList(@RequestBody PermissionVO permissionVO) {
|
||||
return deptRoleService.getRolePermissionList(permissionVO);
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ public class PermissionController {
|
||||
* @since 2025-11-10
|
||||
*/
|
||||
@PostMapping("/module")
|
||||
@PreAuthorize("@ss.hasPermi('system:permission:manage')")
|
||||
@PreAuthorize("hasAuthority('system:permission:manage')")
|
||||
public ResultDomain<TbSysModuleDTO> createModule(@RequestBody TbSysModuleDTO moduleDTO) {
|
||||
return modulePermissionService.insertModule(moduleDTO);
|
||||
}
|
||||
@@ -50,7 +50,7 @@ public class PermissionController {
|
||||
* @since 2025-11-10
|
||||
*/
|
||||
@PutMapping("/moudule")
|
||||
@PreAuthorize("@ss.hasPermi('system:permission:manage')")
|
||||
@PreAuthorize("hasAuthority('system:permission:manage')")
|
||||
public ResultDomain<TbSysModuleDTO> updateModule(@RequestBody TbSysModuleDTO moduleDTO) {
|
||||
return modulePermissionService.updateModule(moduleDTO);
|
||||
}
|
||||
@@ -63,7 +63,7 @@ public class PermissionController {
|
||||
* @since 2025-11-10
|
||||
*/
|
||||
@DeleteMapping("/module")
|
||||
@PreAuthorize("@ss.hasPermi('system:permission:manage')")
|
||||
@PreAuthorize("hasAuthority('system:permission:manage')")
|
||||
public ResultDomain<Boolean> deleteModule(@RequestBody TbSysModuleDTO moduleDTO) {
|
||||
return modulePermissionService.deleteModule(moduleDTO);
|
||||
}
|
||||
@@ -76,7 +76,7 @@ public class PermissionController {
|
||||
* @since 2025-11-10
|
||||
*/
|
||||
@PostMapping("/module/page")
|
||||
@PreAuthorize("@ss.hasPermi('system:permission:view')")
|
||||
@PreAuthorize("hasAuthority('system:permission:view')")
|
||||
public ResultDomain<PermissionVO> getModulePage(@RequestBody PageRequest<PermissionVO> pageRequest) {
|
||||
return modulePermissionService.getModulePage(pageRequest);
|
||||
}
|
||||
@@ -89,7 +89,7 @@ public class PermissionController {
|
||||
* @since 2025-11-10
|
||||
*/
|
||||
@PostMapping("/module/list")
|
||||
@PreAuthorize("@ss.hasPermi('system:permission:view')")
|
||||
@PreAuthorize("hasAuthority('system:permission:view')")
|
||||
public ResultDomain<PermissionVO> getModuleList(@RequestBody PermissionVO filter) {
|
||||
return modulePermissionService.getModuleList(filter);
|
||||
}
|
||||
@@ -103,7 +103,7 @@ public class PermissionController {
|
||||
* @since 2025-11-10
|
||||
*/
|
||||
@PostMapping
|
||||
@PreAuthorize("@ss.hasPermi('system:permission:manage')")
|
||||
@PreAuthorize("hasAuthority('system:permission:manage')")
|
||||
public ResultDomain<TbSysPermissionDTO> createPermission(@RequestBody TbSysPermissionDTO permissionDTO) {
|
||||
return modulePermissionService.insertPermission(permissionDTO);
|
||||
}
|
||||
@@ -116,7 +116,7 @@ public class PermissionController {
|
||||
* @since 2025-11-10
|
||||
*/
|
||||
@PutMapping
|
||||
@PreAuthorize("@ss.hasPermi('system:permission:manage')")
|
||||
@PreAuthorize("hasAuthority('system:permission:manage')")
|
||||
public ResultDomain<TbSysPermissionDTO> updatePermission(@RequestBody TbSysPermissionDTO permissionDTO) {
|
||||
return modulePermissionService.updatePermission(permissionDTO);
|
||||
}
|
||||
@@ -129,7 +129,7 @@ public class PermissionController {
|
||||
* @since 2025-11-10
|
||||
*/
|
||||
@DeleteMapping
|
||||
@PreAuthorize("@ss.hasPermi('system:permission:manage')")
|
||||
@PreAuthorize("hasAuthority('system:permission:manage')")
|
||||
public ResultDomain<Boolean> deletePermission(@RequestBody TbSysPermissionDTO permissionDTO) {
|
||||
return modulePermissionService.deletePermission(permissionDTO);
|
||||
}
|
||||
@@ -142,7 +142,7 @@ public class PermissionController {
|
||||
* @since 2025-11-10
|
||||
*/
|
||||
@PostMapping("/page")
|
||||
@PreAuthorize("@ss.hasPermi('system:permission:view')")
|
||||
@PreAuthorize("hasAuthority('system:permission:view')")
|
||||
public ResultDomain<PermissionVO> getModulePermissionPage(@RequestBody PageRequest<PermissionVO> pageRequest) {
|
||||
return modulePermissionService.getModulePermissionPage(pageRequest);
|
||||
}
|
||||
@@ -155,7 +155,7 @@ public class PermissionController {
|
||||
* @since 2025-11-10
|
||||
*/
|
||||
@PostMapping("/list")
|
||||
@PreAuthorize("@ss.hasPermi('system:permission:view')")
|
||||
@PreAuthorize("hasAuthority('system:permission:view')")
|
||||
public ResultDomain<PermissionVO> getModulePermissionList(@RequestBody PermissionVO filter) {
|
||||
return modulePermissionService.getModulePermissionList(filter);
|
||||
}
|
||||
|
||||
@@ -30,31 +30,31 @@ public class SysConfigController {
|
||||
// ================= 系统配置相关接口 =================
|
||||
|
||||
@PostMapping
|
||||
@PreAuthorize("@ss.hasPermi('config:config:edit')")
|
||||
@PreAuthorize("hasAuthority('config:config:edit')")
|
||||
public ResultDomain<TbSysConfigDTO> createConfig(@RequestBody TbSysConfigDTO configDTO) {
|
||||
return sysConfigService.insertConfig(configDTO);
|
||||
}
|
||||
|
||||
@PutMapping
|
||||
@PreAuthorize("@ss.hasPermi('config:config:edit')")
|
||||
@PreAuthorize("hasAuthority('config:config:edit')")
|
||||
public ResultDomain<TbSysConfigDTO> updateConfig(@RequestBody TbSysConfigDTO configDTO) {
|
||||
return sysConfigService.updateConfig(configDTO);
|
||||
}
|
||||
|
||||
@DeleteMapping
|
||||
@PreAuthorize("@ss.hasPermi('config:config:edit')")
|
||||
@PreAuthorize("hasAuthority('config:config:edit')")
|
||||
public ResultDomain<Boolean> deleteConfig(@RequestBody TbSysConfigDTO configDTO) {
|
||||
return sysConfigService.deleteConfig(configDTO);
|
||||
}
|
||||
|
||||
@PostMapping("/page")
|
||||
@PreAuthorize("@ss.hasPermi('config:config:view')")
|
||||
@PreAuthorize("hasAuthority('config:config:view')")
|
||||
public ResultDomain<SysConfigVO> getConfigPage(@RequestBody PageRequest<SysConfigVO> pageRequest) {
|
||||
return sysConfigService.getConfigPage(pageRequest);
|
||||
}
|
||||
|
||||
@PostMapping("/list")
|
||||
@PreAuthorize("@ss.hasPermi('config:config:view')")
|
||||
@PreAuthorize("hasAuthority('config:config:view')")
|
||||
public ResultDomain<SysConfigVO> getConfigList(@RequestBody SysConfigVO filter) {
|
||||
return sysConfigService.getConfigList(filter);
|
||||
}
|
||||
|
||||
@@ -32,31 +32,31 @@ public class UserController {
|
||||
// ================= 用户相关接口 =================
|
||||
|
||||
@PostMapping
|
||||
@PreAuthorize("@ss.hasPermi('system:user:create')")
|
||||
@PreAuthorize("hasAuthority('system:user:create')")
|
||||
public ResultDomain<TbSysUserDTO> createUser(@RequestBody SysUserVO userVO) {
|
||||
return sysUserService.insertUser(userVO);
|
||||
}
|
||||
|
||||
@PutMapping
|
||||
@PreAuthorize("@ss.hasPermi('system:user:edit')")
|
||||
@PreAuthorize("hasAuthority('system:user:edit')")
|
||||
public ResultDomain<TbSysUserDTO> updateUser(@RequestBody SysUserVO userVO) {
|
||||
return sysUserService.updateUser(userVO);
|
||||
}
|
||||
|
||||
@DeleteMapping
|
||||
@PreAuthorize("@ss.hasPermi('system:user:delete')")
|
||||
@PreAuthorize("hasAuthority('system:user:delete')")
|
||||
public ResultDomain<Boolean> deleteUser(@RequestBody TbSysUserDTO userDTO) {
|
||||
return sysUserService.deleteUser(userDTO);
|
||||
}
|
||||
|
||||
@PostMapping("/page")
|
||||
@PreAuthorize("@ss.hasPermi('system:user:view')")
|
||||
@PreAuthorize("hasAuthority('system:user:view')")
|
||||
public ResultDomain<SysUserVO> getUserPage(@RequestBody PageRequest<SysUserVO> pageRequest) {
|
||||
return sysUserService.getUserPage(pageRequest);
|
||||
}
|
||||
|
||||
@PostMapping("/list")
|
||||
@PreAuthorize("@ss.hasPermi('system:user:view')")
|
||||
@PreAuthorize("hasAuthority('system:user:view')")
|
||||
public ResultDomain<SysUserVO> getUserList(@RequestBody SysUserVO filter) {
|
||||
return sysUserService.getUserList(filter);
|
||||
}
|
||||
@@ -64,13 +64,13 @@ public class UserController {
|
||||
// ================= 用户信息相关接口 ==================
|
||||
|
||||
@PutMapping("/info")
|
||||
@PreAuthorize("@ss.hasPermi('system:user:edit')")
|
||||
@PreAuthorize("hasAuthority('system:user:edit')")
|
||||
public ResultDomain<TbSysUserInfoDTO> updateUserInfo(@RequestBody TbSysUserInfoDTO userInfoDTO) {
|
||||
return sysUserService.updateUserInfo(userInfoDTO);
|
||||
}
|
||||
|
||||
@GetMapping("/info/{userId}")
|
||||
@PreAuthorize("@ss.hasPermi('system:user:view')")
|
||||
@PreAuthorize("hasAuthority('system:user:view')")
|
||||
public ResultDomain<SysUserVO> getUserInfo(@PathVariable("userId") String userId) {
|
||||
return sysUserService.getUserInfo(userId);
|
||||
}
|
||||
|
||||
@@ -28,44 +28,44 @@ public class ViewController {
|
||||
|
||||
// ================= 视图相关接口 =================
|
||||
@PostMapping
|
||||
@PreAuthorize("@ss.hasPermi('system:permission:manage')")
|
||||
@PreAuthorize("hasAuthority('system:permission:manage')")
|
||||
public ResultDomain<TbSysViewDTO> createView(@RequestBody TbSysViewDTO viewDTO) {
|
||||
return viewService.insertView(viewDTO);
|
||||
}
|
||||
|
||||
@PutMapping
|
||||
@PreAuthorize("@ss.hasPermi('system:permission:manage')")
|
||||
@PreAuthorize("hasAuthority('system:permission:manage')")
|
||||
public ResultDomain<TbSysViewDTO> updateView(@RequestBody TbSysViewDTO viewDTO) {
|
||||
return viewService.updateView(viewDTO);
|
||||
}
|
||||
|
||||
@DeleteMapping
|
||||
@PreAuthorize("@ss.hasPermi('system:permission:manage')")
|
||||
@PreAuthorize("hasAuthority('system:permission:manage')")
|
||||
public ResultDomain<Boolean> deleteView(@RequestBody TbSysViewDTO viewDTO) {
|
||||
return viewService.deleteView(viewDTO);
|
||||
}
|
||||
|
||||
@PostMapping("/page")
|
||||
@PreAuthorize("@ss.hasPermi('system:permission:view')")
|
||||
@PreAuthorize("hasAuthority('system:permission:view')")
|
||||
public ResultDomain<PermissionVO> getViewPage(@RequestBody PageRequest<PermissionVO> pageRequest) {
|
||||
return viewService.getViewPage(pageRequest);
|
||||
}
|
||||
|
||||
@PostMapping("/list")
|
||||
@PreAuthorize("@ss.hasPermi('system:permission:view')")
|
||||
@PreAuthorize("hasAuthority('system:permission:view')")
|
||||
public ResultDomain<PermissionVO> getViewList(@RequestBody PermissionVO filter) {
|
||||
return viewService.getViewList(filter);
|
||||
}
|
||||
|
||||
// ================= 视图权限相关接口 ==================
|
||||
@PostMapping("/permission/bind")
|
||||
@PreAuthorize("@ss.hasPermi('system:permission:manage')")
|
||||
@PreAuthorize("hasAuthority('system:permission:manage')")
|
||||
public ResultDomain<PermissionVO> bindViewPermission(@RequestBody PermissionVO permissionVO) {
|
||||
return viewService.setViewPermissions(permissionVO);
|
||||
}
|
||||
|
||||
@PostMapping("/permission/list")
|
||||
@PreAuthorize("@ss.hasPermi('system:permission:view')")
|
||||
@PreAuthorize("hasAuthority('system:permission:view')")
|
||||
public ResultDomain<PermissionVO> getViewPermissions(@RequestBody PermissionVO permissionVO) {
|
||||
return viewService.getViewPermissionList(permissionVO);
|
||||
}
|
||||
|
||||
@@ -46,10 +46,10 @@
|
||||
<groupId>org.xyzh.common</groupId>
|
||||
<artifactId>common-jdbc</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<!-- <dependency>
|
||||
<groupId>org.xyzh.common</groupId>
|
||||
<artifactId>common-wechat</artifactId>
|
||||
</dependency>
|
||||
</dependency> -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
@@ -78,6 +78,21 @@
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>com.alibaba.nacos</groupId>
|
||||
<artifactId>nacos-logback-adapter-12</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>com.alibaba.nacos</groupId>
|
||||
<artifactId>logback-adapter</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-boot-starter</artifactId>
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
package org.xyzh.workcase.config;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.xyzh.common.wechat.kefu.message.KefuMessageService;
|
||||
import org.xyzh.workcase.handler.WorkcaseKefuHandler;
|
||||
|
||||
import jakarta.annotation.PostConstruct;
|
||||
|
||||
/**
|
||||
* @description 工单模块的微信客服配置
|
||||
* 注册 WorkcaseKefuHandler 到消息服务
|
||||
* @filename WeChatKefuConfig.java
|
||||
* @author yslg
|
||||
* @copyright xyzh
|
||||
* @since 2025-12-19
|
||||
*/
|
||||
@Configuration
|
||||
public class WeChatKefuConfig {
|
||||
|
||||
@Autowired
|
||||
private KefuMessageService kefuMessageService;
|
||||
|
||||
@Autowired
|
||||
private WorkcaseKefuHandler workcaseKefuHandler;
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
kefuMessageService.setHandler(workcaseKefuHandler);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -21,7 +21,6 @@ import org.xyzh.common.core.domain.ResultDomain;
|
||||
import org.xyzh.common.core.page.PageRequest;
|
||||
import org.xyzh.common.utils.validation.ValidationResult;
|
||||
import org.xyzh.common.utils.validation.ValidationUtils;
|
||||
import org.xyzh.common.wechat.kefu.message.KefuMessageService;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
|
||||
@@ -46,9 +45,6 @@ public class WorkcaseChatContorller {
|
||||
@DubboReference(version = "1.0.0", group = "workcase", check = false, scope = "local")
|
||||
private WorkcaseChatService workcaseChatService;
|
||||
|
||||
@Autowired
|
||||
private KefuMessageService kefuMessageService;
|
||||
|
||||
// ========================= AI对话管理 =========================
|
||||
|
||||
@Operation(summary = "创建对话")
|
||||
@@ -166,20 +162,6 @@ public class WorkcaseChatContorller {
|
||||
return "success";
|
||||
}
|
||||
|
||||
@Operation(summary = "手动同步客服消息")
|
||||
@PostMapping("/kefu/sync")
|
||||
public ResultDomain<String> syncKefuMessages(
|
||||
@RequestParam(required = false) String cursor,
|
||||
@RequestParam(required = false) String token,
|
||||
@RequestParam(required = false, defaultValue = "100") Integer limit) {
|
||||
var response = kefuMessageService.syncMessages(cursor, token, limit);
|
||||
if (response != null && response.isSuccess()) {
|
||||
kefuMessageService.processMessages(response);
|
||||
return ResultDomain.success("同步成功", response.getNextCursor());
|
||||
}
|
||||
return ResultDomain.failure("同步失败");
|
||||
}
|
||||
|
||||
// ========================= 词云管理 =========================
|
||||
|
||||
@Operation(summary = "添加词云")
|
||||
|
||||
@@ -1,120 +0,0 @@
|
||||
package org.xyzh.workcase.handler;
|
||||
|
||||
import org.apache.dubbo.config.annotation.DubboReference;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.xyzh.api.ai.dto.TbChatMessage;
|
||||
import org.xyzh.api.workcase.dto.TbWorkcaseDTO;
|
||||
import org.xyzh.api.workcase.service.WorkcaseChatService;
|
||||
import org.xyzh.api.workcase.service.WorkcaseService;
|
||||
import org.xyzh.common.wechat.kefu.message.KefuMessageHandler;
|
||||
import org.xyzh.common.wechat.kefu.message.KefuMessageService;
|
||||
import org.xyzh.common.wechat.pojo.kefu.KefuSyncMsgResponse.KefuSyncMsg;
|
||||
|
||||
/**
|
||||
* @description 工单模块的微信客服处理器实现
|
||||
* 处理微信客服消息,同步到工单系统
|
||||
* @filename WorkcaseKefuHandler.java
|
||||
* @author yslg
|
||||
* @copyright xyzh
|
||||
* @since 2025-12-19
|
||||
*/
|
||||
@Component
|
||||
public class WorkcaseKefuHandler implements KefuMessageHandler {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(WorkcaseKefuHandler.class);
|
||||
|
||||
@Autowired
|
||||
private KefuMessageService kefuMessageService;
|
||||
|
||||
@DubboReference(version = "1.0.0", group = "workcase", check = false, scope = "local")
|
||||
private WorkcaseService workcaseService;
|
||||
|
||||
@DubboReference(version = "1.0.0", group = "workcase", check = false, scope = "local")
|
||||
private WorkcaseChatService workcaseChatService;
|
||||
|
||||
@Override
|
||||
public void onEnterSession(String openKfid, String externalUserid, String scene, String sceneParam, String welcomeCode) {
|
||||
logger.info("工单客服-用户进入会话: externalUserid={}, scene={}, sceneParam={}", externalUserid, scene, sceneParam);
|
||||
|
||||
// sceneParam 可能包含 workcaseId,用于关联工单
|
||||
if (sceneParam != null && !sceneParam.isEmpty()) {
|
||||
TbWorkcaseDTO filter = new TbWorkcaseDTO();
|
||||
filter.setWorkcaseId(sceneParam);
|
||||
var result = workcaseService.getWorkcaseById(sceneParam);
|
||||
|
||||
if (result != null && result.getSuccess() && result.getData() != null) {
|
||||
TbWorkcaseDTO workcase = result.getData();
|
||||
// 发送工单信息作为欢迎语
|
||||
String welcomeMsg = buildWelcomeMessage(workcase);
|
||||
kefuMessageService.sendWelcomeMessage(welcomeCode, welcomeMsg);
|
||||
logger.info("已发送工单欢迎语: workcaseId={}", workcase.getWorkcaseId());
|
||||
} else {
|
||||
// 发送通用欢迎语
|
||||
kefuMessageService.sendWelcomeMessage(welcomeCode, "您好,欢迎使用客服服务,请问有什么可以帮您?");
|
||||
}
|
||||
} else {
|
||||
kefuMessageService.sendWelcomeMessage(welcomeCode, "您好,欢迎使用客服服务,请问有什么可以帮您?");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextMessage(String openKfid, String externalUserid, String msgid, String content, Long sendTime) {
|
||||
logger.info("工单客服-收到文本消息: externalUserid={}, content={}", externalUserid, content);
|
||||
|
||||
// 同步消息到 tb_chat_message 表
|
||||
// TODO: 根据 externalUserid 查找关联的 chatId,然后保存消息
|
||||
TbChatMessage chatMessage = new TbChatMessage();
|
||||
chatMessage.setRole("user");
|
||||
chatMessage.setContent(content);
|
||||
// workcaseChatService.saveChatMessage(chatMessage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onImageMessage(String openKfid, String externalUserid, String msgid, String mediaId, Long sendTime) {
|
||||
logger.info("工单客服-收到图片消息: externalUserid={}, mediaId={}", externalUserid, mediaId);
|
||||
|
||||
// 下载图片并保存
|
||||
// TODO: 实现图片消息处理
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSessionStatusChange(String openKfid, String externalUserid, String changeType,
|
||||
String oldServicerUserid, String newServicerUserid) {
|
||||
logger.info("工单客服-会话状态变更: externalUserid={}, changeType={}, newServicer={}",
|
||||
externalUserid, changeType, newServicerUserid);
|
||||
|
||||
// 更新工单处理人
|
||||
// TODO: 根据 externalUserid 查找关联工单,更新 processor
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMsgSendFail(String openKfid, String externalUserid, String failMsgid, String failType) {
|
||||
logger.warn("工单客服-消息发送失败: externalUserid={}, failMsgid={}, failType={}",
|
||||
externalUserid, failMsgid, failType);
|
||||
|
||||
// 记录失败日志,可能需要重试
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOtherMessage(KefuSyncMsg msg) {
|
||||
logger.info("工单客服-收到其他消息: msgtype={}", msg.getMsgtype());
|
||||
}
|
||||
|
||||
private String buildWelcomeMessage(TbWorkcaseDTO workcase) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("您好,您的工单已创建。\n");
|
||||
sb.append("工单编号:").append(workcase.getWorkcaseId()).append("\n");
|
||||
if (workcase.getType() != null) {
|
||||
sb.append("问题类型:").append(workcase.getType()).append("\n");
|
||||
}
|
||||
if (workcase.getDevice() != null) {
|
||||
sb.append("设备:").append(workcase.getDevice()).append("\n");
|
||||
}
|
||||
sb.append("我们将尽快为您处理。");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,13 +1,12 @@
|
||||
# 小程序用户聊天和工单的产生逻辑
|
||||
接口实现方式:
|
||||
0. 用户进行微信小程序,1个IM聊天室,默认回复人员是ai
|
||||
1. WorkcaseChatServiceImpl通过ai接口进行ai回复,对话人员是来客和ai
|
||||
2. 当连续3次ai聊天后,询问是否转人工
|
||||
3. 用户触发转人工(可能是一开始,就手动触发,没有聊天记录),跳转到微信客服的功能服务
|
||||
4. 用户跳转前,必须创建工单
|
||||
5. ai根据聊天对话,自动生成部分工单信息,预填入小程序的工单创建的表单,
|
||||
6. 创建工单后,同步工单到CRM
|
||||
7. 将工单信息作为微信客服的欢迎语,进行放送,让来客和员工能看到工单的基本信息,从而实现让员工知道工单是哪一个
|
||||
<!-- 员工可前往网页查看工单,和相关的聊天记录(ai和来客的对话)以及(员工和来客的对话) -->
|
||||
8. 同步用户和员工在微信客服上的聊天记录,同步到tb_chat表里面,对话人员是来客和客服。(把ai替换成员工进行对话的续接)
|
||||
8. 员工进入聊天室和客户聊天(ai退出聊天室)的聊天记录,同步到tb_chat表里面,对话人员是来客和客服。(把ai替换成员工进行对话的续接)
|
||||
9. 员工自己更新工单状态,如果在CRM更新工单状态会触发receiveWorkcaseFromCrm,如果在本系统更新工单会触发工单同步到CRM
|
||||
10. 在工单是完成、撤销后,工单、对话进行总结,并更新词云
|
||||
@@ -322,17 +322,17 @@ const filteredTickets = computed(() => {
|
||||
let result = workcaseList.value
|
||||
// Mock模式下做本地筛选
|
||||
if (statusFilter.value !== 'all') {
|
||||
result = result.filter(t => t.status === statusFilter.value)
|
||||
result = result.filter((t: TbWorkcaseDTO) => t.status === statusFilter.value)
|
||||
}
|
||||
if (typeFilter.value) {
|
||||
result = result.filter(t => t.type === typeFilter.value)
|
||||
result = result.filter((t: TbWorkcaseDTO) => t.type === typeFilter.value)
|
||||
}
|
||||
if (urgencyFilter.value) {
|
||||
result = result.filter(t => t.emergency === urgencyFilter.value)
|
||||
result = result.filter((t: TbWorkcaseDTO) => t.emergency === urgencyFilter.value)
|
||||
}
|
||||
if (searchKeyword.value) {
|
||||
const keyword = searchKeyword.value.toLowerCase()
|
||||
result = result.filter(t =>
|
||||
result = result.filter((t: TbWorkcaseDTO) =>
|
||||
(t.optsn || '').toLowerCase().includes(keyword) ||
|
||||
(t.username || '').toLowerCase().includes(keyword) ||
|
||||
(t.device || '').toLowerCase().includes(keyword)
|
||||
|
||||
Reference in New Issue
Block a user