diff --git a/internal/infrastructure/wecom/approval_form.go b/internal/infrastructure/wecom/approval_form.go index 25e66fb6..70efedbd 100644 --- a/internal/infrastructure/wecom/approval_form.go +++ b/internal/infrastructure/wecom/approval_form.go @@ -101,7 +101,7 @@ func buildApprovalForm(ctx context.Context, businessType string, applicationID, attachmentCount := 0 for _, mapping := range mappings { raw, exists := lookupSnapshotValue(snapshot, mapping.BusinessField) - if !exists || raw == nil { + if !exists || raw == nil || isEmptyFileValue(mapping, raw) { if requiredControls[mapping.ControlID] { return approvalFormBuildResult{}, errors.New(errors.CodeInvalidStatus, "审批业务快照缺少模板必填字段: "+mapping.BusinessField) } @@ -125,6 +125,23 @@ func buildApprovalForm(ctx context.Context, businessType string, applicationID, return approvalFormBuildResult{Contents: contents}, nil } +// isEmptyFileValue 判断附件控件的快照值是否为空列表;空列表按未填写处理,由模板必填与业务必填规则决定是否拦截。 +func isEmptyFileValue(mapping dto.WeComControlMappingItem, raw any) bool { + if !strings.EqualFold(strings.TrimSpace(mapping.ControlType), "file") { + return false + } + switch value := raw.(type) { + case []any: + return len(value) == 0 + case []string: + return len(value) == 0 + case string: + return strings.TrimSpace(value) == "" + default: + return false + } +} + // lookupSnapshotValue 支持用点分路径读取嵌套业务快照,避免模板映射绑定具体 DTO。 func lookupSnapshotValue(snapshot map[string]any, path string) (any, bool) { segments := strings.Split(strings.TrimSpace(path), ".")