From d43fbbcc3c0bb90d08c4dbb01d529a17b63bed02 Mon Sep 17 00:00:00 2001 From: marsal Date: Tue, 7 Jul 2026 18:06:59 +0800 Subject: [PATCH] =?UTF-8?q?feat(mci-server):=20Phase=201=20=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E6=A8=A1=E5=9E=8B=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 V11 媒体文件表 mci_message_media 及实体/Mapper - 新增 V12 建群任务表 mci_conversation_create_task 及实体/Mapper - 新增 V13 策略组表 mci_policy_group 及实体/Mapper/Service/Controller - V14 将 mci_flow_definition.flow_type 由 VARCHAR 迁移为 TINYINT,实体改为 Integer - FlowDefinitionService 兼容字符串/数值 flowType,FlowEngine 按数值 1 过滤入站流程 - MybatisPlusConfig 增加 message、policy 仓库扫描包 --- .../entity/ConversationCreateTask.java | 25 ++++++ .../ConversationCreateTaskMapper.java | 9 ++ .../sino/mci/config/MybatisPlusConfig.java | 2 +- .../sino/mci/flow/entity/FlowDefinition.java | 2 +- .../flow/service/FlowDefinitionService.java | 16 +++- .../sino/mci/inbound/engine/FlowEngine.java | 2 +- .../sino/mci/message/entity/MessageMedia.java | 25 ++++++ .../repository/MessageMediaMapper.java | 9 ++ .../controller/PolicyGroupController.java | 65 ++++++++++++++ .../policy/dto/CreatePolicyGroupRequest.java | 22 +++++ .../policy/dto/UpdatePolicyGroupRequest.java | 19 +++++ .../dto/UpdatePolicyGroupStatusRequest.java | 11 +++ .../sino/mci/policy/entity/PolicyGroup.java | 19 +++++ .../policy/repository/PolicyGroupMapper.java | 9 ++ .../policy/service/PolicyGroupService.java | 84 +++++++++++++++++++ .../db/migration/V11__add_message_media.sql | 20 +++++ .../V12__add_conversation_create_task.sql | 18 ++++ .../db/migration/V13__add_policy_group.sql | 14 ++++ .../V14__fix_flow_definition_flow_type.sql | 16 ++++ 19 files changed, 382 insertions(+), 5 deletions(-) create mode 100644 backend/mci-server/src/main/java/com/sino/mci/channel/entity/ConversationCreateTask.java create mode 100644 backend/mci-server/src/main/java/com/sino/mci/channel/repository/ConversationCreateTaskMapper.java create mode 100644 backend/mci-server/src/main/java/com/sino/mci/message/entity/MessageMedia.java create mode 100644 backend/mci-server/src/main/java/com/sino/mci/message/repository/MessageMediaMapper.java create mode 100644 backend/mci-server/src/main/java/com/sino/mci/policy/controller/PolicyGroupController.java create mode 100644 backend/mci-server/src/main/java/com/sino/mci/policy/dto/CreatePolicyGroupRequest.java create mode 100644 backend/mci-server/src/main/java/com/sino/mci/policy/dto/UpdatePolicyGroupRequest.java create mode 100644 backend/mci-server/src/main/java/com/sino/mci/policy/dto/UpdatePolicyGroupStatusRequest.java create mode 100644 backend/mci-server/src/main/java/com/sino/mci/policy/entity/PolicyGroup.java create mode 100644 backend/mci-server/src/main/java/com/sino/mci/policy/repository/PolicyGroupMapper.java create mode 100644 backend/mci-server/src/main/java/com/sino/mci/policy/service/PolicyGroupService.java create mode 100644 backend/mci-server/src/main/resources/db/migration/V11__add_message_media.sql create mode 100644 backend/mci-server/src/main/resources/db/migration/V12__add_conversation_create_task.sql create mode 100644 backend/mci-server/src/main/resources/db/migration/V13__add_policy_group.sql create mode 100644 backend/mci-server/src/main/resources/db/migration/V14__fix_flow_definition_flow_type.sql diff --git a/backend/mci-server/src/main/java/com/sino/mci/channel/entity/ConversationCreateTask.java b/backend/mci-server/src/main/java/com/sino/mci/channel/entity/ConversationCreateTask.java new file mode 100644 index 0000000..b51d891 --- /dev/null +++ b/backend/mci-server/src/main/java/com/sino/mci/channel/entity/ConversationCreateTask.java @@ -0,0 +1,25 @@ +package com.sino.mci.channel.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.sino.mci.shared.entity.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.time.LocalDateTime; + +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("mci_conversation_create_task") +public class ConversationCreateTask extends BaseEntity { + + private String tenantCode; + private Integer taskType; + private String channelType; + private Long accountId; + private Long conversationId; + private String participantIds; + private Integer taskStatus; + private String channelResult; + private Integer retryCount; + private LocalDateTime finishTime; +} diff --git a/backend/mci-server/src/main/java/com/sino/mci/channel/repository/ConversationCreateTaskMapper.java b/backend/mci-server/src/main/java/com/sino/mci/channel/repository/ConversationCreateTaskMapper.java new file mode 100644 index 0000000..d9ed1a2 --- /dev/null +++ b/backend/mci-server/src/main/java/com/sino/mci/channel/repository/ConversationCreateTaskMapper.java @@ -0,0 +1,9 @@ +package com.sino.mci.channel.repository; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.sino.mci.channel.entity.ConversationCreateTask; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface ConversationCreateTaskMapper extends BaseMapper { +} diff --git a/backend/mci-server/src/main/java/com/sino/mci/config/MybatisPlusConfig.java b/backend/mci-server/src/main/java/com/sino/mci/config/MybatisPlusConfig.java index 0f7a15f..2d88385 100644 --- a/backend/mci-server/src/main/java/com/sino/mci/config/MybatisPlusConfig.java +++ b/backend/mci-server/src/main/java/com/sino/mci/config/MybatisPlusConfig.java @@ -11,7 +11,7 @@ import org.springframework.context.annotation.Configuration; import javax.sql.DataSource; @Configuration -@MapperScan({"com.sino.mci.admin.repository", "com.sino.mci.channel.repository", "com.sino.mci.crm.repository", "com.sino.mci.flow.repository", "com.sino.mci.inbound.repository", "com.sino.mci.send.repository"}) +@MapperScan({"com.sino.mci.admin.repository", "com.sino.mci.channel.repository", "com.sino.mci.crm.repository", "com.sino.mci.flow.repository", "com.sino.mci.inbound.repository", "com.sino.mci.message.repository", "com.sino.mci.policy.repository", "com.sino.mci.send.repository"}) public class MybatisPlusConfig { @Bean diff --git a/backend/mci-server/src/main/java/com/sino/mci/flow/entity/FlowDefinition.java b/backend/mci-server/src/main/java/com/sino/mci/flow/entity/FlowDefinition.java index 0e205ee..2161ec1 100644 --- a/backend/mci-server/src/main/java/com/sino/mci/flow/entity/FlowDefinition.java +++ b/backend/mci-server/src/main/java/com/sino/mci/flow/entity/FlowDefinition.java @@ -13,7 +13,7 @@ public class FlowDefinition extends BaseEntity { private String tenantCode; private String flowCode; private String flowName; - private String flowType; + private Integer flowType; private String definitionJson; private Integer status; } diff --git a/backend/mci-server/src/main/java/com/sino/mci/flow/service/FlowDefinitionService.java b/backend/mci-server/src/main/java/com/sino/mci/flow/service/FlowDefinitionService.java index 61ca08c..e2a3929 100644 --- a/backend/mci-server/src/main/java/com/sino/mci/flow/service/FlowDefinitionService.java +++ b/backend/mci-server/src/main/java/com/sino/mci/flow/service/FlowDefinitionService.java @@ -32,7 +32,7 @@ public class FlowDefinitionService { flow.setTenantCode(tenantCode); flow.setFlowCode(request.getFlowCode()); flow.setFlowName(request.getFlowName()); - flow.setFlowType(request.getFlowType()); + flow.setFlowType(parseFlowType(request.getFlowType())); flow.setDefinitionJson(JsonUtils.toJson(request.getDefinitionJson())); flow.setStatus(0); flowDefinitionMapper.insert(flow); @@ -62,7 +62,7 @@ public class FlowDefinitionService { public FlowDefinition updateFlow(String tenantCode, String flowCode, CreateFlowRequest request) { FlowDefinition flow = getFlow(tenantCode, flowCode); flow.setFlowName(request.getFlowName()); - flow.setFlowType(request.getFlowType()); + flow.setFlowType(parseFlowType(request.getFlowType())); flow.setDefinitionJson(JsonUtils.toJson(request.getDefinitionJson())); flowDefinitionMapper.updateById(flow); return flow; @@ -81,4 +81,16 @@ public class FlowDefinitionService { flow.setStatus(0); flowDefinitionMapper.updateById(flow); } + + private Integer parseFlowType(String flowType) { + if (flowType == null || flowType.isBlank()) { + return 1; + } + String normalized = flowType.trim().toLowerCase(); + return switch (normalized) { + case "inbound", "1" -> 1; + case "ivr", "2" -> 2; + default -> 1; + }; + } } diff --git a/backend/mci-server/src/main/java/com/sino/mci/inbound/engine/FlowEngine.java b/backend/mci-server/src/main/java/com/sino/mci/inbound/engine/FlowEngine.java index aea5ea7..3204952 100644 --- a/backend/mci-server/src/main/java/com/sino/mci/inbound/engine/FlowEngine.java +++ b/backend/mci-server/src/main/java/com/sino/mci/inbound/engine/FlowEngine.java @@ -77,7 +77,7 @@ public class FlowEngine { List flows = flowDefinitionMapper.selectList( new LambdaQueryWrapper() .eq(FlowDefinition::getTenantCode, tenantCode) - .eq(FlowDefinition::getFlowType, "inbound") + .eq(FlowDefinition::getFlowType, 1) .eq(FlowDefinition::getStatus, 1) .orderByDesc(FlowDefinition::getUpdateTime)); return flows.isEmpty() ? null : flows.get(0); diff --git a/backend/mci-server/src/main/java/com/sino/mci/message/entity/MessageMedia.java b/backend/mci-server/src/main/java/com/sino/mci/message/entity/MessageMedia.java new file mode 100644 index 0000000..b606013 --- /dev/null +++ b/backend/mci-server/src/main/java/com/sino/mci/message/entity/MessageMedia.java @@ -0,0 +1,25 @@ +package com.sino.mci.message.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.sino.mci.shared.entity.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("mci_message_media") +public class MessageMedia extends BaseEntity { + + private String tenantCode; + private String msgid; + private String sdkfileid; + private String mediaType; + private String fileName; + private Long fileSize; + private String md5sum; + private Integer storageType; + private String bucket; + private String objectKey; + private String accessUrl; + private Integer status; +} diff --git a/backend/mci-server/src/main/java/com/sino/mci/message/repository/MessageMediaMapper.java b/backend/mci-server/src/main/java/com/sino/mci/message/repository/MessageMediaMapper.java new file mode 100644 index 0000000..db94de2 --- /dev/null +++ b/backend/mci-server/src/main/java/com/sino/mci/message/repository/MessageMediaMapper.java @@ -0,0 +1,9 @@ +package com.sino.mci.message.repository; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.sino.mci.message.entity.MessageMedia; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface MessageMediaMapper extends BaseMapper { +} diff --git a/backend/mci-server/src/main/java/com/sino/mci/policy/controller/PolicyGroupController.java b/backend/mci-server/src/main/java/com/sino/mci/policy/controller/PolicyGroupController.java new file mode 100644 index 0000000..dbfdcc4 --- /dev/null +++ b/backend/mci-server/src/main/java/com/sino/mci/policy/controller/PolicyGroupController.java @@ -0,0 +1,65 @@ +package com.sino.mci.policy.controller; + +import com.sino.mci.policy.dto.CreatePolicyGroupRequest; +import com.sino.mci.policy.dto.UpdatePolicyGroupRequest; +import com.sino.mci.policy.dto.UpdatePolicyGroupStatusRequest; +import com.sino.mci.policy.entity.PolicyGroup; +import com.sino.mci.policy.service.PolicyGroupService; +import com.sino.mci.shared.web.ApiResponse; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/api/v1/policy-group") +@RequiredArgsConstructor +public class PolicyGroupController { + + private final PolicyGroupService policyGroupService; + + @PostMapping + public ApiResponse createPolicyGroup( + @RequestHeader("X-Tenant-Code") String tenantCode, + @Valid @RequestBody CreatePolicyGroupRequest request) { + return ApiResponse.ok(policyGroupService.createPolicyGroup(tenantCode, request)); + } + + @GetMapping("/list") + public ApiResponse> listPolicyGroups( + @RequestHeader("X-Tenant-Code") String tenantCode) { + return ApiResponse.ok(policyGroupService.listPolicyGroups(tenantCode)); + } + + @GetMapping("/{groupCode}") + public ApiResponse getPolicyGroup( + @RequestHeader("X-Tenant-Code") String tenantCode, + @PathVariable("groupCode") String groupCode) { + return ApiResponse.ok(policyGroupService.getPolicyGroup(tenantCode, groupCode)); + } + + @PostMapping("/{groupCode}") + public ApiResponse updatePolicyGroup( + @RequestHeader("X-Tenant-Code") String tenantCode, + @PathVariable("groupCode") String groupCode, + @Valid @RequestBody UpdatePolicyGroupRequest request) { + return ApiResponse.ok(policyGroupService.updatePolicyGroup(tenantCode, groupCode, request)); + } + + @PostMapping("/{groupCode}/status") + public ApiResponse updatePolicyGroupStatus( + @RequestHeader("X-Tenant-Code") String tenantCode, + @PathVariable("groupCode") String groupCode, + @Valid @RequestBody UpdatePolicyGroupStatusRequest request) { + return ApiResponse.ok(policyGroupService.updatePolicyGroupStatus(tenantCode, groupCode, request.getStatus())); + } + + @PostMapping("/{groupCode}/delete") + public ApiResponse deletePolicyGroup( + @RequestHeader("X-Tenant-Code") String tenantCode, + @PathVariable("groupCode") String groupCode) { + policyGroupService.deletePolicyGroup(tenantCode, groupCode); + return ApiResponse.ok(); + } +} diff --git a/backend/mci-server/src/main/java/com/sino/mci/policy/dto/CreatePolicyGroupRequest.java b/backend/mci-server/src/main/java/com/sino/mci/policy/dto/CreatePolicyGroupRequest.java new file mode 100644 index 0000000..a3e697f --- /dev/null +++ b/backend/mci-server/src/main/java/com/sino/mci/policy/dto/CreatePolicyGroupRequest.java @@ -0,0 +1,22 @@ +package com.sino.mci.policy.dto; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.util.Map; + +@Data +public class CreatePolicyGroupRequest { + + @NotBlank + private String groupCode; + + @NotBlank + private String groupName; + + private String channelType; + + @NotNull + private Map policies; +} diff --git a/backend/mci-server/src/main/java/com/sino/mci/policy/dto/UpdatePolicyGroupRequest.java b/backend/mci-server/src/main/java/com/sino/mci/policy/dto/UpdatePolicyGroupRequest.java new file mode 100644 index 0000000..b3205df --- /dev/null +++ b/backend/mci-server/src/main/java/com/sino/mci/policy/dto/UpdatePolicyGroupRequest.java @@ -0,0 +1,19 @@ +package com.sino.mci.policy.dto; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.util.Map; + +@Data +public class UpdatePolicyGroupRequest { + + @NotBlank + private String groupName; + + private String channelType; + + @NotNull + private Map policies; +} diff --git a/backend/mci-server/src/main/java/com/sino/mci/policy/dto/UpdatePolicyGroupStatusRequest.java b/backend/mci-server/src/main/java/com/sino/mci/policy/dto/UpdatePolicyGroupStatusRequest.java new file mode 100644 index 0000000..fdcd4bf --- /dev/null +++ b/backend/mci-server/src/main/java/com/sino/mci/policy/dto/UpdatePolicyGroupStatusRequest.java @@ -0,0 +1,11 @@ +package com.sino.mci.policy.dto; + +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Data +public class UpdatePolicyGroupStatusRequest { + + @NotNull + private Integer status; +} diff --git a/backend/mci-server/src/main/java/com/sino/mci/policy/entity/PolicyGroup.java b/backend/mci-server/src/main/java/com/sino/mci/policy/entity/PolicyGroup.java new file mode 100644 index 0000000..1864463 --- /dev/null +++ b/backend/mci-server/src/main/java/com/sino/mci/policy/entity/PolicyGroup.java @@ -0,0 +1,19 @@ +package com.sino.mci.policy.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.sino.mci.shared.entity.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("mci_policy_group") +public class PolicyGroup extends BaseEntity { + + private String tenantCode; + private String groupCode; + private String groupName; + private String channelType; + private String policies; + private Integer status; +} diff --git a/backend/mci-server/src/main/java/com/sino/mci/policy/repository/PolicyGroupMapper.java b/backend/mci-server/src/main/java/com/sino/mci/policy/repository/PolicyGroupMapper.java new file mode 100644 index 0000000..d82cd21 --- /dev/null +++ b/backend/mci-server/src/main/java/com/sino/mci/policy/repository/PolicyGroupMapper.java @@ -0,0 +1,9 @@ +package com.sino.mci.policy.repository; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.sino.mci.policy.entity.PolicyGroup; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface PolicyGroupMapper extends BaseMapper { +} diff --git a/backend/mci-server/src/main/java/com/sino/mci/policy/service/PolicyGroupService.java b/backend/mci-server/src/main/java/com/sino/mci/policy/service/PolicyGroupService.java new file mode 100644 index 0000000..5488bf7 --- /dev/null +++ b/backend/mci-server/src/main/java/com/sino/mci/policy/service/PolicyGroupService.java @@ -0,0 +1,84 @@ +package com.sino.mci.policy.service; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.sino.mci.exception.BusinessException; +import com.sino.mci.policy.dto.CreatePolicyGroupRequest; +import com.sino.mci.policy.dto.UpdatePolicyGroupRequest; +import com.sino.mci.policy.entity.PolicyGroup; +import com.sino.mci.policy.repository.PolicyGroupMapper; +import com.sino.mci.shared.util.JsonUtils; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +@Service +@RequiredArgsConstructor +public class PolicyGroupService { + + private final PolicyGroupMapper policyGroupMapper; + + @Transactional + public PolicyGroup createPolicyGroup(String tenantCode, CreatePolicyGroupRequest request) { + PolicyGroup existing = policyGroupMapper.selectOne( + new LambdaQueryWrapper() + .eq(PolicyGroup::getTenantCode, tenantCode) + .eq(PolicyGroup::getGroupCode, request.getGroupCode())); + if (existing != null) { + throw new BusinessException("策略组编码已存在: " + request.getGroupCode()); + } + + PolicyGroup group = new PolicyGroup(); + group.setTenantCode(tenantCode); + group.setGroupCode(request.getGroupCode()); + group.setGroupName(request.getGroupName()); + group.setChannelType(request.getChannelType()); + group.setPolicies(JsonUtils.toJson(request.getPolicies())); + group.setStatus(1); + policyGroupMapper.insert(group); + return group; + } + + public PolicyGroup getPolicyGroup(String tenantCode, String groupCode) { + PolicyGroup group = policyGroupMapper.selectOne( + new LambdaQueryWrapper() + .eq(PolicyGroup::getTenantCode, tenantCode) + .eq(PolicyGroup::getGroupCode, groupCode)); + if (group == null) { + throw new BusinessException("策略组不存在: " + groupCode); + } + return group; + } + + public List listPolicyGroups(String tenantCode) { + return policyGroupMapper.selectList( + new LambdaQueryWrapper() + .eq(PolicyGroup::getTenantCode, tenantCode) + .orderByDesc(PolicyGroup::getCreateTime)); + } + + @Transactional + public PolicyGroup updatePolicyGroup(String tenantCode, String groupCode, UpdatePolicyGroupRequest request) { + PolicyGroup group = getPolicyGroup(tenantCode, groupCode); + group.setGroupName(request.getGroupName()); + group.setChannelType(request.getChannelType()); + group.setPolicies(JsonUtils.toJson(request.getPolicies())); + policyGroupMapper.updateById(group); + return group; + } + + @Transactional + public PolicyGroup updatePolicyGroupStatus(String tenantCode, String groupCode, Integer status) { + PolicyGroup group = getPolicyGroup(tenantCode, groupCode); + group.setStatus(status); + policyGroupMapper.updateById(group); + return group; + } + + @Transactional + public void deletePolicyGroup(String tenantCode, String groupCode) { + PolicyGroup group = getPolicyGroup(tenantCode, groupCode); + policyGroupMapper.deleteById(group.getId()); + } +} diff --git a/backend/mci-server/src/main/resources/db/migration/V11__add_message_media.sql b/backend/mci-server/src/main/resources/db/migration/V11__add_message_media.sql new file mode 100644 index 0000000..793f2e0 --- /dev/null +++ b/backend/mci-server/src/main/resources/db/migration/V11__add_message_media.sql @@ -0,0 +1,20 @@ +CREATE TABLE IF NOT EXISTS mci_message_media ( + id BIGINT AUTO_INCREMENT PRIMARY KEY, + tenant_code VARCHAR(64) NOT NULL COMMENT '所属租户', + msgid VARCHAR(128) COMMENT '关联的消息 ID', + sdkfileid VARCHAR(256) COMMENT '企微媒体文件 ID', + media_type VARCHAR(32) COMMENT '媒体类型:image / voice / video / file / emotion', + file_name VARCHAR(256) COMMENT '文件名', + file_size BIGINT COMMENT '文件大小', + md5sum VARCHAR(64) COMMENT 'MD5', + storage_type TINYINT NOT NULL DEFAULT 2 COMMENT '存储类型:2SeaweedFS', + bucket VARCHAR(128) COMMENT 'SeaweedFS bucket', + object_key VARCHAR(512) COMMENT 'SeaweedFS object key', + access_url VARCHAR(512) COMMENT '访问 URL', + status TINYINT NOT NULL DEFAULT 0 COMMENT '状态:0未下载 1下载中 2已下载 3下载失败', + create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + deleted TINYINT NOT NULL DEFAULT 0, + KEY idx_tenant_msgid (tenant_code, msgid), + KEY idx_status (status) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='媒体文件表'; diff --git a/backend/mci-server/src/main/resources/db/migration/V12__add_conversation_create_task.sql b/backend/mci-server/src/main/resources/db/migration/V12__add_conversation_create_task.sql new file mode 100644 index 0000000..c6724a5 --- /dev/null +++ b/backend/mci-server/src/main/resources/db/migration/V12__add_conversation_create_task.sql @@ -0,0 +1,18 @@ +CREATE TABLE IF NOT EXISTS mci_conversation_create_task ( + id BIGINT AUTO_INCREMENT PRIMARY KEY, + tenant_code VARCHAR(64) NOT NULL COMMENT '所属租户', + task_type TINYINT NOT NULL DEFAULT 1 COMMENT '任务类型:1创建群聊 2邀请成员', + channel_type VARCHAR(32) NOT NULL COMMENT '渠道:wecom / wechat_personal / dingtalk / feishu', + account_id BIGINT COMMENT '使用哪个账号创建', + conversation_id BIGINT COMMENT '创建成功后回填的会话 ID', + participant_ids JSON COMMENT '参与者人员 ID 列表', + task_status TINYINT NOT NULL DEFAULT 0 COMMENT '任务状态:0待执行 1执行中 2成功 3失败', + channel_result JSON COMMENT '渠道返回结果', + retry_count INT NOT NULL DEFAULT 0 COMMENT '重试次数', + finish_time DATETIME COMMENT '完成时间', + create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + deleted TINYINT NOT NULL DEFAULT 0, + KEY idx_tenant_status (tenant_code, task_status), + KEY idx_conversation_id (conversation_id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='建群任务表'; diff --git a/backend/mci-server/src/main/resources/db/migration/V13__add_policy_group.sql b/backend/mci-server/src/main/resources/db/migration/V13__add_policy_group.sql new file mode 100644 index 0000000..50b6640 --- /dev/null +++ b/backend/mci-server/src/main/resources/db/migration/V13__add_policy_group.sql @@ -0,0 +1,14 @@ +CREATE TABLE IF NOT EXISTS mci_policy_group ( + id BIGINT AUTO_INCREMENT PRIMARY KEY, + tenant_code VARCHAR(64) NOT NULL COMMENT '所属租户', + group_code VARCHAR(64) NOT NULL COMMENT '策略组编码', + group_name VARCHAR(128) NOT NULL COMMENT '策略组名称', + channel_type VARCHAR(32) COMMENT '渠道类型:wecom / wechat_personal / dingtalk / feishu', + policies JSON NOT NULL COMMENT '策略规则 JSON', + status TINYINT NOT NULL DEFAULT 1 COMMENT '状态:0禁用 1启用', + create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + deleted TINYINT NOT NULL DEFAULT 0, + UNIQUE KEY uk_tenant_group_code (tenant_code, group_code, deleted), + KEY idx_tenant_status (tenant_code, status) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='策略组表'; diff --git a/backend/mci-server/src/main/resources/db/migration/V14__fix_flow_definition_flow_type.sql b/backend/mci-server/src/main/resources/db/migration/V14__fix_flow_definition_flow_type.sql new file mode 100644 index 0000000..44df51d --- /dev/null +++ b/backend/mci-server/src/main/resources/db/migration/V14__fix_flow_definition_flow_type.sql @@ -0,0 +1,16 @@ +-- 将流程类型的字符串值安全迁移为数值,之后改为 TINYINT 以对齐架构定义 +UPDATE mci_flow_definition +SET flow_type = '1' +WHERE LOWER(flow_type) = 'inbound'; + +UPDATE mci_flow_definition +SET flow_type = '2' +WHERE LOWER(flow_type) = 'ivr'; + +-- 兜底:任何未识别的旧值统一按入站处理 +UPDATE mci_flow_definition +SET flow_type = '1' +WHERE flow_type NOT IN ('1', '2'); + +ALTER TABLE mci_flow_definition + MODIFY COLUMN flow_type TINYINT NOT NULL DEFAULT 1 COMMENT '流程类型:1入站 2IVR';