|
|
@@ -0,0 +1,218 @@
|
|
|
+package com.usky.issue.service.impl;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|
|
+import com.usky.common.core.exception.BusinessException;
|
|
|
+import com.usky.common.security.utils.SecurityUtils;
|
|
|
+import com.usky.issue.domain.IssueCloudConfig;
|
|
|
+import com.usky.issue.domain.IssueSyncStatus;
|
|
|
+import com.usky.issue.domain.IssueSyncTask;
|
|
|
+import com.usky.issue.domain.IssueTriggerEvent;
|
|
|
+import com.usky.issue.mapper.IssueCloudConfigMapper;
|
|
|
+import com.usky.issue.mapper.IssueSyncStatusMapper;
|
|
|
+import com.usky.issue.mapper.IssueSyncTaskMapper;
|
|
|
+import com.usky.issue.mapper.IssueTriggerEventMapper;
|
|
|
+import com.usky.issue.service.CloudConfigService;
|
|
|
+import com.usky.issue.service.CloudOperationLogService;
|
|
|
+import com.usky.issue.service.client.CloudPlatformClient;
|
|
|
+import com.usky.issue.service.constant.CloudIntegrationConstants;
|
|
|
+import com.usky.issue.service.enums.SyncTypeEnum;
|
|
|
+import com.usky.issue.service.enums.TaskStatusEnum;
|
|
|
+import com.usky.issue.service.enums.TriggerEventCodeEnum;
|
|
|
+import com.usky.issue.service.support.CloudEntitySupport;
|
|
|
+import com.usky.issue.service.util.AesGcmCipher;
|
|
|
+import com.usky.issue.service.util.CredentialMaskUtil;
|
|
|
+import com.usky.issue.service.vo.CloudConfigResponse;
|
|
|
+import com.usky.issue.service.vo.CloudConfigSaveRequest;
|
|
|
+import com.usky.issue.service.vo.CloudConnectionTestResponse;
|
|
|
+import com.usky.issue.service.vo.CloudDisableResponse;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
+
|
|
|
+import java.time.LocalDateTime;
|
|
|
+import java.util.Arrays;
|
|
|
+import java.util.List;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 云平台配置服务实现
|
|
|
+ *
|
|
|
+ * @author fyc
|
|
|
+ * @date 2026-05-21
|
|
|
+ */
|
|
|
+@Service
|
|
|
+public class CloudConfigServiceImpl implements CloudConfigService {
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private IssueCloudConfigMapper configMapper;
|
|
|
+ @Autowired
|
|
|
+ private IssueSyncStatusMapper syncStatusMapper;
|
|
|
+ @Autowired
|
|
|
+ private IssueTriggerEventMapper triggerEventMapper;
|
|
|
+ @Autowired
|
|
|
+ private IssueSyncTaskMapper syncTaskMapper;
|
|
|
+ @Autowired
|
|
|
+ private AesGcmCipher aesGcmCipher;
|
|
|
+ @Autowired
|
|
|
+ private CloudPlatformClient cloudPlatformClient;
|
|
|
+ @Autowired
|
|
|
+ private CloudOperationLogService operationLogService;
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public CloudConfigResponse getConfig() {
|
|
|
+ IssueCloudConfig config = findActiveConfig();
|
|
|
+ if (config == null) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ return toResponse(config);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public CloudConfigResponse saveConfig(CloudConfigSaveRequest request, String operator, String requestIp) {
|
|
|
+ IssueCloudConfig existing = findActiveConfig();
|
|
|
+ if (existing == null) {
|
|
|
+ IssueCloudConfig created = new IssueCloudConfig();
|
|
|
+ created.setTenantId(Integer.valueOf(request.getTenantId()));
|
|
|
+ created.setCredentialKey(aesGcmCipher.encrypt(request.getCredentialKey()));
|
|
|
+ created.setStatus(1);
|
|
|
+ created.setConnectionStatus(0);
|
|
|
+ created.setVersion(0);
|
|
|
+ CloudEntitySupport.fillOnInsert(created);
|
|
|
+ configMapper.insert(created);
|
|
|
+ initSyncStatusRows(created.getId());
|
|
|
+ initTriggerEvents(created.getId());
|
|
|
+ operationLogService.log(created.getId(), CloudIntegrationConstants.OPERATION_SAVE_CONFIG,
|
|
|
+ "新建配置 tenantId=" + request.getTenantId(), operator, requestIp);
|
|
|
+ return toResponse(created);
|
|
|
+ }
|
|
|
+ if (request.getVersion() != null && !request.getVersion().equals(existing.getVersion())) {
|
|
|
+ throw new BusinessException("配置版本冲突,请刷新后重试");
|
|
|
+ }
|
|
|
+ existing.setTenantId(Integer.valueOf(request.getTenantId()));
|
|
|
+ existing.setCredentialKey(aesGcmCipher.encrypt(request.getCredentialKey()));
|
|
|
+ existing.setStatus(1);
|
|
|
+ CloudEntitySupport.fillOnUpdate(existing);
|
|
|
+ int updated = configMapper.updateById(existing);
|
|
|
+ if (updated == 0) {
|
|
|
+ throw new BusinessException("配置版本冲突,请刷新后重试");
|
|
|
+ }
|
|
|
+ operationLogService.log(existing.getId(), CloudIntegrationConstants.OPERATION_SAVE_CONFIG,
|
|
|
+ "更新配置 tenantId=" + CredentialMaskUtil.mask(request.getTenantId()), operator, requestIp);
|
|
|
+ return toResponse(configMapper.selectById(existing.getId()));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public CloudConnectionTestResponse testConnection(String operator, String requestIp) {
|
|
|
+ IssueCloudConfig config = requireActiveConfig();
|
|
|
+ boolean ok = cloudPlatformClient.testConnection(config);
|
|
|
+ config.setConnectionStatus(ok ? 1 : 2);
|
|
|
+ config.setLastTestAt(LocalDateTime.now());
|
|
|
+ CloudEntitySupport.fillOnUpdate(config);
|
|
|
+ configMapper.updateById(config);
|
|
|
+ operationLogService.log(config.getId(), CloudIntegrationConstants.OPERATION_TEST_CONNECTION,
|
|
|
+ "连接测试" + (ok ? "成功" : "失败"), operator, requestIp);
|
|
|
+ CloudConnectionTestResponse response = new CloudConnectionTestResponse();
|
|
|
+ response.setSuccess(ok);
|
|
|
+ response.setConnectionStatus(config.getConnectionStatus());
|
|
|
+ response.setMessage(ok ? "连接成功" : "连接失败");
|
|
|
+ return response;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public CloudDisableResponse disable(String operator, String requestIp) {
|
|
|
+ IssueCloudConfig config = requireActiveConfig();
|
|
|
+ config.setStatus(0);
|
|
|
+ CloudEntitySupport.fillOnUpdate(config);
|
|
|
+ configMapper.updateById(config);
|
|
|
+ int affected = cancelRunningTasks(config.getId());
|
|
|
+ operationLogService.log(config.getId(), CloudIntegrationConstants.OPERATION_DISABLE,
|
|
|
+ "禁用集成,终止任务数=" + affected, operator, requestIp);
|
|
|
+ CloudDisableResponse response = new CloudDisableResponse();
|
|
|
+ response.setDisabled(true);
|
|
|
+ response.setAffectedTasks(affected);
|
|
|
+ return response;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public IssueCloudConfig requireActiveConfig() {
|
|
|
+ IssueCloudConfig config = findActiveConfig();
|
|
|
+ if (config == null) {
|
|
|
+ throw new BusinessException("云平台配置不存在,请先保存配置");
|
|
|
+ }
|
|
|
+ if (config.getStatus() != null && config.getStatus() == 0) {
|
|
|
+ throw new BusinessException("云平台集成已禁用");
|
|
|
+ }
|
|
|
+ return config;
|
|
|
+ }
|
|
|
+
|
|
|
+ private IssueCloudConfig findActiveConfig() {
|
|
|
+ return configMapper.selectOne(new QueryWrapper<IssueCloudConfig>()
|
|
|
+ .eq("deleted", 0)
|
|
|
+ .eq("tenant_id", SecurityUtils.getTenantId())
|
|
|
+ .orderByDesc("id")
|
|
|
+ .last("LIMIT 1"));
|
|
|
+ }
|
|
|
+
|
|
|
+ private int cancelRunningTasks(Long configId) {
|
|
|
+ List<IssueSyncTask> running = syncTaskMapper.selectList(new QueryWrapper<IssueSyncTask>()
|
|
|
+ .eq("config_id", configId)
|
|
|
+ .eq("deleted", 0)
|
|
|
+ .in("task_status",
|
|
|
+ TaskStatusEnum.PENDING.getCode(), TaskStatusEnum.RUNNING.getCode()));
|
|
|
+ for (IssueSyncTask task : running) {
|
|
|
+ task.setTaskStatus(TaskStatusEnum.CANCELLED.getCode());
|
|
|
+ task.setFinishedAt(LocalDateTime.now());
|
|
|
+ task.setErrorSummary("集成已禁用,任务终止");
|
|
|
+ CloudEntitySupport.fillOnUpdate(task);
|
|
|
+ syncTaskMapper.updateById(task);
|
|
|
+ }
|
|
|
+ return running.size();
|
|
|
+ }
|
|
|
+
|
|
|
+ private void initSyncStatusRows(Long configId) {
|
|
|
+ for (SyncTypeEnum type : SyncTypeEnum.values()) {
|
|
|
+ IssueSyncStatus row = new IssueSyncStatus();
|
|
|
+ row.setConfigId(configId);
|
|
|
+ row.setSyncType(type.getCode());
|
|
|
+ row.setTypeName(type.getLabel());
|
|
|
+ row.setTotalCount(0);
|
|
|
+ row.setSuccessCount(0);
|
|
|
+ row.setFailureCount(0);
|
|
|
+ row.setUnsyncedCount(0);
|
|
|
+ CloudEntitySupport.fillOnInsert(row);
|
|
|
+ syncStatusMapper.insert(row);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void initTriggerEvents(Long configId) {
|
|
|
+ Arrays.stream(TriggerEventCodeEnum.values()).forEach(code -> {
|
|
|
+ IssueTriggerEvent event = new IssueTriggerEvent();
|
|
|
+ event.setConfigId(configId);
|
|
|
+ event.setEventCode(code.getCode());
|
|
|
+ event.setEventName(code.getName());
|
|
|
+ event.setDescription(code.getDescription());
|
|
|
+ event.setEnabled(0);
|
|
|
+ CloudEntitySupport.fillOnInsert(event);
|
|
|
+ triggerEventMapper.insert(event);
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ private CloudConfigResponse toResponse(IssueCloudConfig config) {
|
|
|
+ CloudConfigResponse resp = new CloudConfigResponse();
|
|
|
+ resp.setId(config.getId());
|
|
|
+ resp.setTenantId(String.valueOf(config.getTenantId()));
|
|
|
+ try {
|
|
|
+ resp.setCredentialKeyMasked(CredentialMaskUtil.mask(aesGcmCipher.decrypt(config.getCredentialKey())));
|
|
|
+ } catch (Exception e) {
|
|
|
+ resp.setCredentialKeyMasked("****");
|
|
|
+ }
|
|
|
+ resp.setStatus(config.getStatus());
|
|
|
+ resp.setConnectionStatus(config.getConnectionStatus());
|
|
|
+ resp.setVersion(config.getVersion());
|
|
|
+ resp.setLastTestAt(config.getLastTestAt());
|
|
|
+ resp.setUpdatedAt(config.getUpdatedAt());
|
|
|
+ return resp;
|
|
|
+ }
|
|
|
+}
|