From ae880c47b2cf3adbf63f46d66b44eee98aabeb63 Mon Sep 17 00:00:00 2001 From: huangping Date: Mon, 25 May 2026 01:35:25 +0800 Subject: [PATCH] feat(m6): add BitAnswer ID mapping CRUD --- .../IntegrationCatalogController.java | 29 ++ .../PlatformBitanswerIdMapping.java | 122 +++++++++ .../PlatformBitanswerIdMappingMapper.java | 7 + .../service/IntegrationCatalogService.java | 38 ++- .../db/migration/V13__m6_id_mapping.sql | 16 ++ web/delivery-platform-ui/src/api/platform.js | 14 + web/delivery-platform-ui/src/router/index.js | 6 + .../src/views/IntegrationIdMappingView.vue | 249 ++++++++++++++++++ 8 files changed, 480 insertions(+), 1 deletion(-) create mode 100644 services/delivery-platform-api/src/main/java/cn/craftlabs/platform/api/persistence/integration/PlatformBitanswerIdMapping.java create mode 100644 services/delivery-platform-api/src/main/java/cn/craftlabs/platform/api/persistence/integration/PlatformBitanswerIdMappingMapper.java create mode 100644 services/delivery-platform-api/src/main/resources/db/migration/V13__m6_id_mapping.sql create mode 100644 web/delivery-platform-ui/src/views/IntegrationIdMappingView.vue diff --git a/services/delivery-platform-api/src/main/java/cn/craftlabs/platform/api/integration/IntegrationCatalogController.java b/services/delivery-platform-api/src/main/java/cn/craftlabs/platform/api/integration/IntegrationCatalogController.java index b597711..0766206 100644 --- a/services/delivery-platform-api/src/main/java/cn/craftlabs/platform/api/integration/IntegrationCatalogController.java +++ b/services/delivery-platform-api/src/main/java/cn/craftlabs/platform/api/integration/IntegrationCatalogController.java @@ -1,5 +1,6 @@ package cn.craftlabs.platform.api.integration; +import cn.craftlabs.platform.api.persistence.integration.PlatformBitanswerIdMapping; import cn.craftlabs.platform.api.service.IntegrationCatalogService; import cn.craftlabs.platform.api.web.dto.IntegrationEnvironmentRequest; import cn.craftlabs.platform.api.web.dto.IntegrationEnvironmentResponse; @@ -10,6 +11,9 @@ import jakarta.validation.Valid; import jakarta.validation.constraints.Max; import jakarta.validation.constraints.Min; import org.springframework.validation.annotation.Validated; + +import java.util.List; +import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -88,4 +92,29 @@ public class IntegrationCatalogController { public void deleteProductLine(@PathVariable("id") long id) { integrationCatalogService.deleteProductLine(id); } + + @GetMapping("/id-mappings") + public ResponseEntity> listIdMappings( + @RequestParam(required = false) Long productLineId, + @RequestParam(required = false) Long environmentId) { + return ResponseEntity.ok(integrationCatalogService.listIdMappings(productLineId, environmentId)); + } + + @PostMapping("/id-mappings") + public ResponseEntity createIdMapping(@RequestBody PlatformBitanswerIdMapping body) { + return ResponseEntity.ok(integrationCatalogService.createIdMapping(body)); + } + + @PutMapping("/id-mappings/{id}") + public ResponseEntity updateIdMapping( + @PathVariable Long id, @RequestBody PlatformBitanswerIdMapping body) { + PlatformBitanswerIdMapping result = integrationCatalogService.updateIdMapping(id, body); + return result != null ? ResponseEntity.ok(result) : ResponseEntity.notFound().build(); + } + + @DeleteMapping("/id-mappings/{id}") + public ResponseEntity deleteIdMapping(@PathVariable Long id) { + integrationCatalogService.deleteIdMapping(id); + return ResponseEntity.ok().build(); + } } diff --git a/services/delivery-platform-api/src/main/java/cn/craftlabs/platform/api/persistence/integration/PlatformBitanswerIdMapping.java b/services/delivery-platform-api/src/main/java/cn/craftlabs/platform/api/persistence/integration/PlatformBitanswerIdMapping.java new file mode 100644 index 0000000..c5cfdc0 --- /dev/null +++ b/services/delivery-platform-api/src/main/java/cn/craftlabs/platform/api/persistence/integration/PlatformBitanswerIdMapping.java @@ -0,0 +1,122 @@ +package cn.craftlabs.platform.api.persistence.integration; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; + +import java.time.OffsetDateTime; + +@TableName("platform_bitanswer_id_mapping") +public class PlatformBitanswerIdMapping { + + @TableId(type = IdType.AUTO) + private Long id; + + @TableField("product_line_id") + private Long productLineId; + + @TableField("environment_id") + private Long environmentId; + + @TableField("bitanswer_product_id") + private String bitanswerProductId; + + @TableField("bitanswer_template_id") + private String bitanswerTemplateId; + + @TableField("bitanswer_business_id") + private String bitanswerBusinessId; + + @TableField("feature_key") + private String featureKey; + + @TableField("bitanswer_feature_id") + private String bitanswerFeatureId; + + @TableField("created_at") + private OffsetDateTime createdAt; + + @TableField("updated_at") + private OffsetDateTime updatedAt; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Long getProductLineId() { + return productLineId; + } + + public void setProductLineId(Long productLineId) { + this.productLineId = productLineId; + } + + public Long getEnvironmentId() { + return environmentId; + } + + public void setEnvironmentId(Long environmentId) { + this.environmentId = environmentId; + } + + public String getBitanswerProductId() { + return bitanswerProductId; + } + + public void setBitanswerProductId(String bitanswerProductId) { + this.bitanswerProductId = bitanswerProductId; + } + + public String getBitanswerTemplateId() { + return bitanswerTemplateId; + } + + public void setBitanswerTemplateId(String bitanswerTemplateId) { + this.bitanswerTemplateId = bitanswerTemplateId; + } + + public String getBitanswerBusinessId() { + return bitanswerBusinessId; + } + + public void setBitanswerBusinessId(String bitanswerBusinessId) { + this.bitanswerBusinessId = bitanswerBusinessId; + } + + public String getFeatureKey() { + return featureKey; + } + + public void setFeatureKey(String featureKey) { + this.featureKey = featureKey; + } + + public String getBitanswerFeatureId() { + return bitanswerFeatureId; + } + + public void setBitanswerFeatureId(String bitanswerFeatureId) { + this.bitanswerFeatureId = bitanswerFeatureId; + } + + public OffsetDateTime getCreatedAt() { + return createdAt; + } + + public void setCreatedAt(OffsetDateTime createdAt) { + this.createdAt = createdAt; + } + + public OffsetDateTime getUpdatedAt() { + return updatedAt; + } + + public void setUpdatedAt(OffsetDateTime updatedAt) { + this.updatedAt = updatedAt; + } +} diff --git a/services/delivery-platform-api/src/main/java/cn/craftlabs/platform/api/persistence/integration/PlatformBitanswerIdMappingMapper.java b/services/delivery-platform-api/src/main/java/cn/craftlabs/platform/api/persistence/integration/PlatformBitanswerIdMappingMapper.java new file mode 100644 index 0000000..c77bdf8 --- /dev/null +++ b/services/delivery-platform-api/src/main/java/cn/craftlabs/platform/api/persistence/integration/PlatformBitanswerIdMappingMapper.java @@ -0,0 +1,7 @@ +package cn.craftlabs.platform.api.persistence.integration; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface PlatformBitanswerIdMappingMapper extends BaseMapper {} diff --git a/services/delivery-platform-api/src/main/java/cn/craftlabs/platform/api/service/IntegrationCatalogService.java b/services/delivery-platform-api/src/main/java/cn/craftlabs/platform/api/service/IntegrationCatalogService.java index e8c773b..7cd45a9 100644 --- a/services/delivery-platform-api/src/main/java/cn/craftlabs/platform/api/service/IntegrationCatalogService.java +++ b/services/delivery-platform-api/src/main/java/cn/craftlabs/platform/api/service/IntegrationCatalogService.java @@ -1,5 +1,7 @@ package cn.craftlabs.platform.api.service; +import cn.craftlabs.platform.api.persistence.integration.PlatformBitanswerIdMapping; +import cn.craftlabs.platform.api.persistence.integration.PlatformBitanswerIdMappingMapper; import cn.craftlabs.platform.api.persistence.integration.PlatformIntegrationEnvironment; import cn.craftlabs.platform.api.persistence.integration.PlatformIntegrationEnvironmentMapper; import cn.craftlabs.platform.api.persistence.integration.PlatformProductLine; @@ -24,12 +26,15 @@ public class IntegrationCatalogService { private final PlatformProductLineMapper productLineMapper; private final PlatformIntegrationEnvironmentMapper environmentMapper; + private final PlatformBitanswerIdMappingMapper idMappingMapper; public IntegrationCatalogService( PlatformProductLineMapper productLineMapper, - PlatformIntegrationEnvironmentMapper environmentMapper) { + PlatformIntegrationEnvironmentMapper environmentMapper, + PlatformBitanswerIdMappingMapper idMappingMapper) { this.productLineMapper = productLineMapper; this.environmentMapper = environmentMapper; + this.idMappingMapper = idMappingMapper; } @Transactional(readOnly = true) @@ -138,6 +143,37 @@ public class IntegrationCatalogService { environmentMapper.deleteById(id); } + public List listIdMappings(Long productLineId, Long environmentId) { + var qw = new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper(); + if (productLineId != null) qw.eq(PlatformBitanswerIdMapping::getProductLineId, productLineId); + if (environmentId != null) qw.eq(PlatformBitanswerIdMapping::getEnvironmentId, environmentId); + qw.orderByDesc(PlatformBitanswerIdMapping::getCreatedAt); + return idMappingMapper.selectList(qw); + } + + @Transactional + public PlatformBitanswerIdMapping createIdMapping(PlatformBitanswerIdMapping mapping) { + mapping.setCreatedAt(java.time.OffsetDateTime.now()); + mapping.setUpdatedAt(java.time.OffsetDateTime.now()); + idMappingMapper.insert(mapping); + return mapping; + } + + @Transactional + public PlatformBitanswerIdMapping updateIdMapping(Long id, PlatformBitanswerIdMapping mapping) { + PlatformBitanswerIdMapping existing = idMappingMapper.selectById(id); + if (existing == null) return null; + mapping.setId(id); + mapping.setUpdatedAt(java.time.OffsetDateTime.now()); + idMappingMapper.updateById(mapping); + return idMappingMapper.selectById(id); + } + + @Transactional + public void deleteIdMapping(Long id) { + idMappingMapper.deleteById(id); + } + private ProductLineResponse toProductLine(PlatformProductLine row) { ProductLineResponse r = new ProductLineResponse(); r.setId(row.getId()); diff --git a/services/delivery-platform-api/src/main/resources/db/migration/V13__m6_id_mapping.sql b/services/delivery-platform-api/src/main/resources/db/migration/V13__m6_id_mapping.sql new file mode 100644 index 0000000..ccc7aa2 --- /dev/null +++ b/services/delivery-platform-api/src/main/resources/db/migration/V13__m6_id_mapping.sql @@ -0,0 +1,16 @@ +-- V13__m6_id_mapping.sql +CREATE TABLE platform_bitanswer_id_mapping ( + id BIGSERIAL PRIMARY KEY, + product_line_id BIGINT NOT NULL REFERENCES platform_product_line(id), + environment_id BIGINT REFERENCES platform_integration_environment(id), + bitanswer_product_id VARCHAR(128), + bitanswer_template_id VARCHAR(128), + bitanswer_business_id VARCHAR(128), + feature_key VARCHAR(64), + bitanswer_feature_id VARCHAR(128), + created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP +); + +CREATE INDEX idx_id_mapping_product_line ON platform_bitanswer_id_mapping(product_line_id); +CREATE INDEX idx_id_mapping_environment ON platform_bitanswer_id_mapping(environment_id); diff --git a/web/delivery-platform-ui/src/api/platform.js b/web/delivery-platform-ui/src/api/platform.js index 7ed83c4..f2044d0 100644 --- a/web/delivery-platform-ui/src/api/platform.js +++ b/web/delivery-platform-ui/src/api/platform.js @@ -387,3 +387,17 @@ export function initiateContractChange(id, body) { export function completeContractChange(id) { return axios.post(`/api/v1/contracts/${id}/changes/complete`); } + +// —— I12 M6 比特 ID 映射 —————————————————————— +export function listIdMappings(params) { + return axios.get('/api/v1/integration/id-mappings', { params }); +} +export function createIdMapping(body) { + return axios.post('/api/v1/integration/id-mappings', body); +} +export function updateIdMapping(id, body) { + return axios.put(`/api/v1/integration/id-mappings/${id}`, body); +} +export function deleteIdMapping(id) { + return axios.delete(`/api/v1/integration/id-mappings/${id}`); +} diff --git a/web/delivery-platform-ui/src/router/index.js b/web/delivery-platform-ui/src/router/index.js index 4e5e34e..5f07081 100644 --- a/web/delivery-platform-ui/src/router/index.js +++ b/web/delivery-platform-ui/src/router/index.js @@ -80,6 +80,12 @@ const routes = [ component: () => import("../views/IntegrationProductLinesView.vue"), meta: { roles: ["SYS_ADMIN", "DEVELOPER", "OPS"], title: "产品线" }, }, + { + path: "integration/id-mappings", + name: "integration-id-mappings", + component: () => import("../views/IntegrationIdMappingView.vue"), + meta: { roles: ["SYS_ADMIN", "DEVELOPER"], title: "ID 映射" }, + }, { path: "callbacks/:id", name: "callback-inbox-detail", diff --git a/web/delivery-platform-ui/src/views/IntegrationIdMappingView.vue b/web/delivery-platform-ui/src/views/IntegrationIdMappingView.vue new file mode 100644 index 0000000..a7a80bc --- /dev/null +++ b/web/delivery-platform-ui/src/views/IntegrationIdMappingView.vue @@ -0,0 +1,249 @@ + + + + +