This commit is contained in:
2026-03-10 17:28:04 +08:00
parent 9a7bda9527
commit 4cd3954574
12 changed files with 1938 additions and 11 deletions

View File

@@ -0,0 +1,35 @@
package entities
import "time"
// Report 报告记录实体
// 用于持久化存储各类报告(企业报告等),通过编号和类型区分
type Report struct {
// 报告编号,直接使用业务生成的 reportId 作为主键
ReportID string `gorm:"primaryKey;type:varchar(64)" json:"report_id"`
// 报告类型,例如 enterprise企业报告、personal 等
Type string `gorm:"type:varchar(32);not null;index" json:"type"`
// 调用来源API编码例如 QYGLJ1U9
ApiCode string `gorm:"type:varchar(32);not null;index" json:"api_code"`
// 企业名称和统一社会信用代码,便于后续检索
EntName string `gorm:"type:varchar(255);index" json:"ent_name"`
EntCode string `gorm:"type:varchar(64);index" json:"ent_code"`
// 原始请求参数JSON字符串用于审计和排错
RequestParams string `gorm:"type:text" json:"request_params"`
// 报告完整JSON内容
ReportData string `gorm:"type:text" json:"report_data"`
// 创建时间
CreatedAt time.Time `gorm:"autoCreateTime" json:"created_at"`
}
// TableName 指定数据库表名
func (Report) TableName() string {
return "reports"
}

View File

@@ -0,0 +1,17 @@
package repositories
import (
"context"
"tyapi-server/internal/domains/api/entities"
)
// ReportRepository 报告记录仓储接口
type ReportRepository interface {
// Create 创建报告记录
Create(ctx context.Context, report *entities.Report) error
// FindByReportID 根据报告编号查询记录
FindByReportID(ctx context.Context, reportID string) (*entities.Report, error)
}

View File

@@ -7,6 +7,7 @@ import (
"tyapi-server/internal/application/api/commands"
"tyapi-server/internal/config"
api_repositories "tyapi-server/internal/domains/api/repositories"
"tyapi-server/internal/domains/api/services/processors"
"tyapi-server/internal/domains/api/services/processors/comb"
"tyapi-server/internal/domains/api/services/processors/dwbg"
@@ -50,6 +51,8 @@ type ApiRequestService struct {
processorDeps *processors.ProcessorDependencies
combService *comb.CombService
config *config.Config
reportRepo api_repositories.ReportRepository
}
func NewApiRequestService(
@@ -66,26 +69,76 @@ func NewApiRequestService(
validator interfaces.RequestValidator,
productManagementService *services.ProductManagementService,
cfg *config.Config,
) *ApiRequestService {
return NewApiRequestServiceWithRepos(
westDexService,
shujubaoService,
muziService,
yushanService,
tianYanChaService,
alicloudService,
zhichaService,
xingweiService,
jiguangService,
shumaiService,
validator,
productManagementService,
cfg,
nil,
)
}
// NewApiRequestServiceWithRepos 带自定义仓储的构造函数,便于扩展(例如企业报告记录)
func NewApiRequestServiceWithRepos(
westDexService *westdex.WestDexService,
shujubaoService *shujubao.ShujubaoService,
muziService *muzi.MuziService,
yushanService *yushan.YushanService,
tianYanChaService *tianyancha.TianYanChaService,
alicloudService *alicloud.AlicloudService,
zhichaService *zhicha.ZhichaService,
xingweiService *xingwei.XingweiService,
jiguangService *jiguang.JiguangService,
shumaiService *shumai.ShumaiService,
validator interfaces.RequestValidator,
productManagementService *services.ProductManagementService,
cfg *config.Config,
reportRepo api_repositories.ReportRepository,
) *ApiRequestService {
// 创建组合包服务
combService := comb.NewCombService(productManagementService)
// 创建处理器依赖容器
processorDeps := processors.NewProcessorDependencies(westDexService, shujubaoService, muziService, yushanService, tianYanChaService, alicloudService, zhichaService, xingweiService, jiguangService, shumaiService, validator, combService)
processorDeps := processors.NewProcessorDependencies(
westDexService,
shujubaoService,
muziService,
yushanService,
tianYanChaService,
alicloudService,
zhichaService,
xingweiService,
jiguangService,
shumaiService,
validator,
combService,
reportRepo,
)
// 统一注册所有处理器
registerAllProcessors(combService)
return &ApiRequestService{
westDexService: westDexService,
muziService: muziService,
yushanService: yushanService,
tianYanChaService: tianYanChaService,
alicloudService: alicloudService,
validator: validator,
processorDeps: processorDeps,
combService: combService,
config: cfg,
westDexService: westDexService,
muziService: muziService,
yushanService: yushanService,
tianYanChaService: tianYanChaService,
alicloudService: alicloudService,
validator: validator,
processorDeps: processorDeps,
combService: combService,
config: cfg,
reportRepo: reportRepo,
}
}
@@ -180,6 +233,7 @@ func registerAllProcessors(combService *comb.CombService) {
"QYGLNIO8": qygl.ProcessQYGLNIO8Request, //企业基本信息
"QYGLP0HT": qygl.ProcessQYGLP0HTRequest, //股权穿透
"QYGL5S1I": qygl.ProcessQYGL5S1IRequest, //企业司法涉诉I
"QYGLJ1U9": qygl.ProcessQYGLJ1U9Request, //企业全景报告(聚合 QYGLUY3S/QYGLJ0Q1/QYGL5S1I
"QYGLJ0Q1": qygl.ProcessQYGLJ0Q1Request, //企业股权结构全景查询
"QYGLUY3S": qygl.ProcessQYGLUY3SRequest, //企业经营状态全景查询
"YYSY35TA": yysy.ProcessYYSY35TARequest, //运营商归属地数卖

View File

@@ -2,7 +2,9 @@ package processors
import (
"context"
"tyapi-server/internal/application/api/commands"
"tyapi-server/internal/domains/api/repositories"
"tyapi-server/internal/infrastructure/external/alicloud"
"tyapi-server/internal/infrastructure/external/jiguang"
"tyapi-server/internal/infrastructure/external/muzi"
@@ -42,6 +44,9 @@ type ProcessorDependencies struct {
CombService CombServiceInterface // Changed to interface to break import cycle
Options *commands.ApiCallOptions // 添加Options支持
CallContext *CallContext // 添加CallApi调用上下文
// 企业报告记录仓储,用于持久化 QYGLJ1U9 生成的企业报告
ReportRepo repositories.ReportRepository
}
// NewProcessorDependencies 创建处理器依赖容器
@@ -58,6 +63,7 @@ func NewProcessorDependencies(
shumaiService *shumai.ShumaiService,
validator interfaces.RequestValidator,
combService CombServiceInterface, // Changed to interface
reportRepo repositories.ReportRepository,
) *ProcessorDependencies {
return &ProcessorDependencies{
WestDexService: westDexService,
@@ -74,6 +80,7 @@ func NewProcessorDependencies(
CombService: combService,
Options: nil, // 初始化为nil在调用时设置
CallContext: nil, // 初始化为nil在调用时设置
ReportRepo: reportRepo,
}
}

View File

@@ -0,0 +1,180 @@
package qygl
import (
"context"
"crypto/rand"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"net/url"
"sync"
"time"
"tyapi-server/internal/domains/api/dto"
"tyapi-server/internal/domains/api/entities"
"tyapi-server/internal/domains/api/services/processors"
)
// ProcessQYGLJ1U9Request 企业全景报告处理器:并发调用企业全量(QYGLUY3S)、股权全景(QYGLJ0Q1)、司法涉诉(QYGL5S1I)
// 然后复用 qyglj1u9_processor_build.go 中的 buildReport / map* 逻辑生成企业报告结构
func ProcessQYGLJ1U9Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
// 复用 QYGLUY3S 的入参结构:企业名称/注册号/统一社会信用代码
var p dto.QYGLUY3SReq
if err := json.Unmarshal(params, &p); err != nil {
return nil, errors.Join(processors.ErrSystem, err)
}
if err := deps.Validator.ValidateStruct(p); err != nil {
return nil, errors.Join(processors.ErrInvalidParam, err)
}
// 并发调用三个已有处理器
type apiResult struct {
key string
data map[string]interface{}
err error
}
resultsCh := make(chan apiResult, 3)
var wg sync.WaitGroup
call := func(key string, req interface{}, fn func(context.Context, []byte, *processors.ProcessorDependencies) ([]byte, error)) {
wg.Add(1)
go func() {
defer wg.Done()
b, err := json.Marshal(req)
if err != nil {
resultsCh <- apiResult{key: key, err: err}
return
}
resp, err := fn(ctx, b, deps)
if err != nil {
resultsCh <- apiResult{key: key, err: err}
return
}
var m map[string]interface{}
if err := json.Unmarshal(resp, &m); err != nil {
resultsCh <- apiResult{key: key, err: err}
return
}
resultsCh <- apiResult{key: key, data: m}
}()
}
// 企业全量信息核验V2QYGLUY3S
call("jiguangFull", map[string]interface{}{
"ent_name": p.EntName,
"ent_reg_no": p.EntRegno,
"ent_code": p.EntCode,
}, ProcessQYGLUY3SRequest)
// 企业股权结构全景QYGLJ0Q1
call("equityPanorama", map[string]interface{}{
"ent_name": p.EntName,
"ent_code": p.EntCode,
}, ProcessQYGLJ0Q1Request)
// 企业司法涉诉V2QYGL5S1I
call("judicialCertFull", map[string]interface{}{
"ent_name": p.EntName,
"ent_code": p.EntCode,
}, ProcessQYGL5S1IRequest)
wg.Wait()
close(resultsCh)
var jiguang, judicial, equity map[string]interface{}
for r := range resultsCh {
if r.err != nil {
// 任一关键数据源异常,则返回系统错误(也可以根据需求做降级)
return nil, errors.Join(processors.ErrSystem, fmt.Errorf("%s 调用失败: %w", r.key, r.err))
}
switch r.key {
case "jiguangFull":
jiguang = r.data
case "judicialCertFull":
judicial = r.data
case "equityPanorama":
equity = r.data
}
}
if jiguang == nil {
jiguang = map[string]interface{}{}
}
if judicial == nil {
judicial = map[string]interface{}{}
}
if equity == nil {
equity = map[string]interface{}{}
}
// 复用构建逻辑生成企业报告结构
report := buildReport(jiguang, judicial, equity)
// 为报告生成唯一编号并缓存,供后续通过编号查看
reportID := saveQYGLReport(report)
report["reportId"] = reportID
// 持久化企业报告记录到数据库(忽略持久化失败,不影响接口主流程)
if deps.ReportRepo != nil {
reqJSON, _ := json.Marshal(p)
reportJSON, _ := json.Marshal(report)
_ = deps.ReportRepo.Create(ctx, &entities.Report{
ReportID: reportID,
Type: "enterprise",
ApiCode: "QYGLJ1U9",
EntName: p.EntName,
EntCode: p.EntCode,
RequestParams: string(reqJSON),
ReportData: string(reportJSON),
})
}
// 为报告补充前端查看链接,供调用方直接跳转到企业报告页面(通过编号访问)
report["reportUrl"] = buildQYGLReportURLByID(reportID)
out, err := json.Marshal(report)
if err != nil {
return nil, errors.Join(processors.ErrSystem, err)
}
return out, nil
}
// 内存中的企业报告缓存(简单实现,进程重启后清空)
var qyglReportStore = struct {
sync.RWMutex
data map[string]map[string]interface{}
}{
data: make(map[string]map[string]interface{}),
}
// saveQYGLReport 保存报告并返回生成的编号
func saveQYGLReport(report map[string]interface{}) string {
id := generateQYGLReportID()
qyglReportStore.Lock()
qyglReportStore.data[id] = report
qyglReportStore.Unlock()
return id
}
// GetQYGLReport 根据编号获取报告(供页面渲染使用)
func GetQYGLReport(id string) (map[string]interface{}, bool) {
qyglReportStore.RLock()
defer qyglReportStore.RUnlock()
r, ok := qyglReportStore.data[id]
return r, ok
}
// generateQYGLReportID 生成短编号
func generateQYGLReportID() string {
b := make([]byte, 8)
if _, err := rand.Read(b); err == nil {
return hex.EncodeToString(b)
}
// 随机数失败时退化为时间戳
return fmt.Sprintf("%d", time.Now().UnixNano())
}
// buildQYGLReportURLByID 构造企业报告前端查看链接(通过编号查看)
func buildQYGLReportURLByID(id string) string {
return "/reports/qygl/" + url.PathEscape(id)
}

File diff suppressed because it is too large Load Diff