Dockerfile
This commit is contained in:
306
service/mapping/data_mapping_service.go
Normal file
306
service/mapping/data_mapping_service.go
Normal file
@@ -0,0 +1,306 @@
|
||||
package mapping
|
||||
|
||||
import (
|
||||
consts "cid/consts/mapping"
|
||||
dao "cid/dao/mapping"
|
||||
dto "cid/model/dto/mapping"
|
||||
entity "cid/model/entity/mapping"
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
)
|
||||
|
||||
type dataMappingService struct{}
|
||||
|
||||
// DataMapping 数据映射服务
|
||||
var DataMapping = new(dataMappingService)
|
||||
|
||||
// Create 创建数据映射
|
||||
func (s *dataMappingService) Create(ctx context.Context, req *dto.CreateDataMappingReq) (res *dto.CreateDataMappingRes, err error) {
|
||||
// 检查接口是否存在
|
||||
// TODO: 这里需要调用data层的ApiInterface服务,暂时跳过
|
||||
|
||||
// 检查同一接口下目标字段是否重复
|
||||
existing, err := dao.DataMapping.GetByInterfaceIdAndTargetField(ctx, req.InterfaceId, req.TargetField)
|
||||
if err == nil && existing != nil {
|
||||
return nil, errors.New("该接口下目标字段已存在")
|
||||
}
|
||||
|
||||
// 插入数据库
|
||||
id, err := dao.DataMapping.Insert(ctx, req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
res = &dto.CreateDataMappingRes{
|
||||
Id: id,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// BatchCreate 批量创建数据映射
|
||||
func (s *dataMappingService) BatchCreate(ctx context.Context, req *dto.BatchCreateDataMappingReq) (res *dto.BatchCreateDataMappingRes, err error) {
|
||||
var ids []int64
|
||||
successCount := 0
|
||||
failedCount := 0
|
||||
|
||||
for _, mappingReq := range req.Mappings {
|
||||
// 设置平台和接口ID
|
||||
mappingReq.PlatformId = req.PlatformId
|
||||
mappingReq.InterfaceId = req.InterfaceId
|
||||
|
||||
createRes, err := s.Create(ctx, &mappingReq)
|
||||
if err != nil {
|
||||
failedCount++
|
||||
g.Log().Error(ctx, "批量创建映射失败", g.Map{
|
||||
"sourceField": mappingReq.SourceField,
|
||||
"targetField": mappingReq.TargetField,
|
||||
"error": err.Error(),
|
||||
})
|
||||
} else {
|
||||
successCount++
|
||||
ids = append(ids, createRes.Id)
|
||||
}
|
||||
}
|
||||
|
||||
return &dto.BatchCreateDataMappingRes{
|
||||
SuccessCount: successCount,
|
||||
FailedCount: failedCount,
|
||||
Ids: ids,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// List 获取数据映射列表
|
||||
func (s *dataMappingService) List(ctx context.Context, req *dto.ListDataMappingReq) (res *dto.ListDataMappingRes, err error) {
|
||||
mappingList, total, err := dao.DataMapping.List(ctx, req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// 获取平台和接口ID列表
|
||||
platformIds := make([]int64, 0)
|
||||
interfaceIds := make([]int64, 0)
|
||||
for _, item := range mappingList {
|
||||
if item.PlatformId > 0 {
|
||||
platformIds = append(platformIds, item.PlatformId)
|
||||
}
|
||||
if item.InterfaceId > 0 {
|
||||
interfaceIds = append(interfaceIds, item.InterfaceId)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: 批量获取平台和接口信息(需要调用data层服务)
|
||||
platformMap := make(map[int64]string)
|
||||
interfaceMap := make(map[int64]string)
|
||||
|
||||
// 组装响应数据
|
||||
list := make([]dto.DataMappingItem, 0, len(mappingList))
|
||||
for _, item := range mappingList {
|
||||
platformName := ""
|
||||
if name, ok := platformMap[item.PlatformId]; ok {
|
||||
platformName = name
|
||||
}
|
||||
interfaceName := ""
|
||||
if name, ok := interfaceMap[item.InterfaceId]; ok {
|
||||
interfaceName = name
|
||||
}
|
||||
|
||||
list = append(list, dto.DataMappingItem{
|
||||
Id: item.Id,
|
||||
PlatformId: item.PlatformId,
|
||||
PlatformName: platformName,
|
||||
InterfaceId: item.InterfaceId,
|
||||
InterfaceName: interfaceName,
|
||||
SourceField: item.SourceField,
|
||||
TargetField: item.TargetField,
|
||||
FieldType: item.FieldType,
|
||||
DefaultValue: item.DefaultValue,
|
||||
TransformRule: item.TransformRule,
|
||||
Priority: item.Priority,
|
||||
Status: item.Status,
|
||||
StatusName: s.getStatusName(item.Status),
|
||||
CreatedAt: item.CreatedAt.Unix(),
|
||||
UpdatedAt: item.UpdatedAt.Unix(),
|
||||
})
|
||||
}
|
||||
|
||||
res = &dto.ListDataMappingRes{
|
||||
List: list,
|
||||
Total: total,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// GetOne 获取单个数据映射
|
||||
func (s *dataMappingService) GetOne(ctx context.Context, req *dto.GetDataMappingReq) (res *dto.GetDataMappingRes, err error) {
|
||||
mapping, err := dao.DataMapping.GetOne(ctx, req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// TODO: 获取平台和接口名称
|
||||
platformName := ""
|
||||
interfaceName := ""
|
||||
|
||||
return &dto.GetDataMappingRes{
|
||||
DataMapping: mapping,
|
||||
PlatformName: platformName,
|
||||
InterfaceName: interfaceName,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Update 更新数据映射
|
||||
func (s *dataMappingService) Update(ctx context.Context, req *dto.UpdateDataMappingReq) (err error) {
|
||||
// 检查映射是否存在
|
||||
exist, err := dao.DataMapping.GetOne(ctx, &dto.GetDataMappingReq{Id: req.Id})
|
||||
if err != nil || exist == nil {
|
||||
return errors.New("映射不存在")
|
||||
}
|
||||
|
||||
// 如果修改了目标字段,检查是否重复
|
||||
if req.TargetField != "" && req.TargetField != exist.TargetField {
|
||||
interfaceId := req.InterfaceId
|
||||
if interfaceId == 0 {
|
||||
interfaceId = exist.InterfaceId
|
||||
}
|
||||
existing, err := dao.DataMapping.GetByInterfaceIdAndTargetField(ctx, interfaceId, req.TargetField)
|
||||
if err == nil && existing != nil && existing.Id != req.Id {
|
||||
return errors.New("该接口下目标字段已存在")
|
||||
}
|
||||
}
|
||||
|
||||
_, err = dao.DataMapping.Update(ctx, req)
|
||||
return
|
||||
}
|
||||
|
||||
// Delete 删除数据映射
|
||||
func (s *dataMappingService) Delete(ctx context.Context, req *dto.DeleteDataMappingReq) (err error) {
|
||||
_, err = dao.DataMapping.Delete(ctx, req)
|
||||
return
|
||||
}
|
||||
|
||||
// Execute 执行数据映射
|
||||
func (s *dataMappingService) Execute(ctx context.Context, req *dto.ExecuteDataMappingReq) (res *dto.ExecuteDataMappingRes, err error) {
|
||||
// 获取接口的所有映射规则
|
||||
mappings, err := dao.DataMapping.GetByInterfaceId(ctx, req.InterfaceId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(mappings) == 0 {
|
||||
return &dto.ExecuteDataMappingRes{
|
||||
TargetData: map[string]interface{}{},
|
||||
AppliedRules: []string{},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// 初始化目标数据
|
||||
targetData := make(map[string]interface{})
|
||||
appliedRules := make([]string, 0)
|
||||
|
||||
// 遍历映射规则进行转换
|
||||
for _, mapping := range mappings {
|
||||
if mapping.Status != consts.MappingStatusActive {
|
||||
continue
|
||||
}
|
||||
|
||||
// 获取源数据值
|
||||
sourceValue, exists := req.SourceData[mapping.SourceField]
|
||||
|
||||
// 应用转换规则
|
||||
targetValue := s.applyTransformRule(ctx, sourceValue, exists, mapping)
|
||||
|
||||
// 设置目标数据
|
||||
targetData[mapping.TargetField] = targetValue
|
||||
|
||||
appliedRules = append(appliedRules, gconv.String(mapping.SourceField)+" -> "+gconv.String(mapping.TargetField))
|
||||
}
|
||||
|
||||
return &dto.ExecuteDataMappingRes{
|
||||
TargetData: targetData,
|
||||
AppliedRules: appliedRules,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// applyTransformRule 应用转换规则
|
||||
func (s *dataMappingService) applyTransformRule(ctx context.Context, sourceValue interface{}, exists bool, mapping entity.DataMapping) interface{} {
|
||||
// 如果源字段不存在,使用默认值
|
||||
if !exists {
|
||||
if mapping.DefaultValue != "" {
|
||||
return mapping.DefaultValue
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 如果没有转换规则,直接返回源值
|
||||
if mapping.TransformRule == nil || len(mapping.TransformRule) == 0 {
|
||||
return sourceValue
|
||||
}
|
||||
|
||||
// 获取转换类型
|
||||
transformType := ""
|
||||
if t, ok := mapping.TransformRule["type"].(string); ok {
|
||||
transformType = t
|
||||
}
|
||||
|
||||
// 根据转换类型应用不同的转换逻辑
|
||||
switch consts.TransformType(transformType) {
|
||||
case consts.TransformTypeFixed:
|
||||
// 固定值
|
||||
if v, ok := mapping.TransformRule["rule"].(string); ok {
|
||||
return v
|
||||
}
|
||||
case consts.TransformTypeMapping:
|
||||
// 值映射
|
||||
if mappingMap, ok := mapping.TransformRule["mappingMap"].(map[string]interface{}); ok {
|
||||
if sourceKey := gconv.String(sourceValue); sourceKey != "" {
|
||||
if v, ok := mappingMap[sourceKey]; ok {
|
||||
return v
|
||||
}
|
||||
}
|
||||
}
|
||||
case consts.TransformTypeRegex:
|
||||
// 正则转换
|
||||
if regex, ok := mapping.TransformRule["regex"].(string); ok {
|
||||
// TODO: 实现正则替换逻辑
|
||||
g.Log().Warning(ctx, "正则转换暂未实现", g.Map{
|
||||
"regex": regex,
|
||||
"sourceValue": sourceValue,
|
||||
})
|
||||
}
|
||||
case consts.TransformTypeFunction:
|
||||
// 函数转换
|
||||
if functionName, ok := mapping.TransformRule["functionName"].(string); ok {
|
||||
// TODO: 实现函数调用逻辑
|
||||
g.Log().Warning(ctx, "函数转换暂未实现", g.Map{
|
||||
"function": functionName,
|
||||
"sourceValue": sourceValue,
|
||||
})
|
||||
}
|
||||
case consts.TransformTypeScript:
|
||||
// 脚本转换
|
||||
if script, ok := mapping.TransformRule["script"].(string); ok {
|
||||
// TODO: 实现脚本执行逻辑
|
||||
g.Log().Warning(ctx, "脚本转换暂未实现", g.Map{
|
||||
"script": script,
|
||||
"sourceValue": sourceValue,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 默认返回源值
|
||||
return sourceValue
|
||||
}
|
||||
|
||||
// getStatusName 获取状态名称
|
||||
func (s *dataMappingService) getStatusName(status consts.MappingStatus) string {
|
||||
statusNames := map[consts.MappingStatus]string{
|
||||
consts.MappingStatusActive: "启用",
|
||||
consts.MappingStatusInactive: "停用",
|
||||
}
|
||||
if name, ok := statusNames[status]; ok {
|
||||
return name
|
||||
}
|
||||
return string(status)
|
||||
}
|
||||
Reference in New Issue
Block a user