307 lines
8.4 KiB
Go
307 lines
8.4 KiB
Go
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)
|
||
}
|