f
This commit is contained in:
@@ -260,6 +260,7 @@ func (a *Application) autoMigrate(db *gorm.DB) error {
|
|||||||
// api
|
// api
|
||||||
&apiEntities.ApiUser{},
|
&apiEntities.ApiUser{},
|
||||||
&apiEntities.ApiCall{},
|
&apiEntities.ApiCall{},
|
||||||
|
&apiEntities.Report{},
|
||||||
|
|
||||||
// 任务域
|
// 任务域
|
||||||
&taskEntities.AsyncTask{},
|
&taskEntities.AsyncTask{},
|
||||||
|
|||||||
@@ -660,6 +660,10 @@ func NewContainer() *Container {
|
|||||||
api_repo.NewGormApiCallRepository,
|
api_repo.NewGormApiCallRepository,
|
||||||
fx.As(new(domain_api_repo.ApiCallRepository)),
|
fx.As(new(domain_api_repo.ApiCallRepository)),
|
||||||
),
|
),
|
||||||
|
fx.Annotate(
|
||||||
|
api_repo.NewGormReportRepository,
|
||||||
|
fx.As(new(domain_api_repo.ReportRepository)),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
// 统计域仓储层
|
// 统计域仓储层
|
||||||
@@ -769,7 +773,8 @@ func NewContainer() *Container {
|
|||||||
api_services.NewApiUserAggregateService,
|
api_services.NewApiUserAggregateService,
|
||||||
),
|
),
|
||||||
api_services.NewApiCallAggregateService,
|
api_services.NewApiCallAggregateService,
|
||||||
api_services.NewApiRequestService,
|
// 使用带仓储注入的构造函数,支持企业报告记录持久化
|
||||||
|
api_services.NewApiRequestServiceWithRepos,
|
||||||
api_services.NewFormConfigService,
|
api_services.NewFormConfigService,
|
||||||
),
|
),
|
||||||
|
|
||||||
@@ -1284,6 +1289,8 @@ func NewContainer() *Container {
|
|||||||
) *handlers.ComponentReportOrderHandler {
|
) *handlers.ComponentReportOrderHandler {
|
||||||
return handlers.NewComponentReportOrderHandler(componentReportOrderService, purchaseOrderRepo, config, logger)
|
return handlers.NewComponentReportOrderHandler(componentReportOrderService, purchaseOrderRepo, config, logger)
|
||||||
},
|
},
|
||||||
|
// 企业全景报告页面处理器
|
||||||
|
handlers.NewQYGLReportHandler,
|
||||||
// UI组件HTTP处理器
|
// UI组件HTTP处理器
|
||||||
func(
|
func(
|
||||||
uiComponentAppService product.UIComponentApplicationService,
|
uiComponentAppService product.UIComponentApplicationService,
|
||||||
@@ -1330,6 +1337,8 @@ func NewContainer() *Container {
|
|||||||
routes.NewStatisticsRoutes,
|
routes.NewStatisticsRoutes,
|
||||||
// PDFG路由
|
// PDFG路由
|
||||||
routes.NewPDFGRoutes,
|
routes.NewPDFGRoutes,
|
||||||
|
// 企业报告页面路由
|
||||||
|
routes.NewQYGLReportRoutes,
|
||||||
),
|
),
|
||||||
|
|
||||||
// 应用生命周期
|
// 应用生命周期
|
||||||
@@ -1445,6 +1454,7 @@ func RegisterRoutes(
|
|||||||
apiRoutes *routes.ApiRoutes,
|
apiRoutes *routes.ApiRoutes,
|
||||||
statisticsRoutes *routes.StatisticsRoutes,
|
statisticsRoutes *routes.StatisticsRoutes,
|
||||||
pdfgRoutes *routes.PDFGRoutes,
|
pdfgRoutes *routes.PDFGRoutes,
|
||||||
|
qyglReportRoutes *routes.QYGLReportRoutes,
|
||||||
jwtAuth *middleware.JWTAuthMiddleware,
|
jwtAuth *middleware.JWTAuthMiddleware,
|
||||||
adminAuth *middleware.AdminAuthMiddleware,
|
adminAuth *middleware.AdminAuthMiddleware,
|
||||||
cfg *config.Config,
|
cfg *config.Config,
|
||||||
@@ -1470,6 +1480,7 @@ func RegisterRoutes(
|
|||||||
announcementRoutes.Register(router)
|
announcementRoutes.Register(router)
|
||||||
statisticsRoutes.Register(router)
|
statisticsRoutes.Register(router)
|
||||||
pdfgRoutes.Register(router)
|
pdfgRoutes.Register(router)
|
||||||
|
qyglReportRoutes.Register(router)
|
||||||
|
|
||||||
// 打印注册的路由信息
|
// 打印注册的路由信息
|
||||||
router.PrintRoutes()
|
router.PrintRoutes()
|
||||||
|
|||||||
35
internal/domains/api/entities/enterprise_report.go
Normal file
35
internal/domains/api/entities/enterprise_report.go
Normal 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"
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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)
|
||||||
|
}
|
||||||
|
|
||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
|
|
||||||
"tyapi-server/internal/application/api/commands"
|
"tyapi-server/internal/application/api/commands"
|
||||||
"tyapi-server/internal/config"
|
"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"
|
||||||
"tyapi-server/internal/domains/api/services/processors/comb"
|
"tyapi-server/internal/domains/api/services/processors/comb"
|
||||||
"tyapi-server/internal/domains/api/services/processors/dwbg"
|
"tyapi-server/internal/domains/api/services/processors/dwbg"
|
||||||
@@ -50,6 +51,8 @@ type ApiRequestService struct {
|
|||||||
processorDeps *processors.ProcessorDependencies
|
processorDeps *processors.ProcessorDependencies
|
||||||
combService *comb.CombService
|
combService *comb.CombService
|
||||||
config *config.Config
|
config *config.Config
|
||||||
|
|
||||||
|
reportRepo api_repositories.ReportRepository
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewApiRequestService(
|
func NewApiRequestService(
|
||||||
@@ -66,26 +69,76 @@ func NewApiRequestService(
|
|||||||
validator interfaces.RequestValidator,
|
validator interfaces.RequestValidator,
|
||||||
productManagementService *services.ProductManagementService,
|
productManagementService *services.ProductManagementService,
|
||||||
cfg *config.Config,
|
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 {
|
) *ApiRequestService {
|
||||||
// 创建组合包服务
|
// 创建组合包服务
|
||||||
combService := comb.NewCombService(productManagementService)
|
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)
|
registerAllProcessors(combService)
|
||||||
|
|
||||||
return &ApiRequestService{
|
return &ApiRequestService{
|
||||||
westDexService: westDexService,
|
westDexService: westDexService,
|
||||||
muziService: muziService,
|
muziService: muziService,
|
||||||
yushanService: yushanService,
|
yushanService: yushanService,
|
||||||
tianYanChaService: tianYanChaService,
|
tianYanChaService: tianYanChaService,
|
||||||
alicloudService: alicloudService,
|
alicloudService: alicloudService,
|
||||||
validator: validator,
|
validator: validator,
|
||||||
processorDeps: processorDeps,
|
processorDeps: processorDeps,
|
||||||
combService: combService,
|
combService: combService,
|
||||||
config: cfg,
|
config: cfg,
|
||||||
|
reportRepo: reportRepo,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -180,6 +233,7 @@ func registerAllProcessors(combService *comb.CombService) {
|
|||||||
"QYGLNIO8": qygl.ProcessQYGLNIO8Request, //企业基本信息
|
"QYGLNIO8": qygl.ProcessQYGLNIO8Request, //企业基本信息
|
||||||
"QYGLP0HT": qygl.ProcessQYGLP0HTRequest, //股权穿透
|
"QYGLP0HT": qygl.ProcessQYGLP0HTRequest, //股权穿透
|
||||||
"QYGL5S1I": qygl.ProcessQYGL5S1IRequest, //企业司法涉诉I
|
"QYGL5S1I": qygl.ProcessQYGL5S1IRequest, //企业司法涉诉I
|
||||||
|
"QYGLJ1U9": qygl.ProcessQYGLJ1U9Request, //企业全景报告(聚合 QYGLUY3S/QYGLJ0Q1/QYGL5S1I)
|
||||||
"QYGLJ0Q1": qygl.ProcessQYGLJ0Q1Request, //企业股权结构全景查询
|
"QYGLJ0Q1": qygl.ProcessQYGLJ0Q1Request, //企业股权结构全景查询
|
||||||
"QYGLUY3S": qygl.ProcessQYGLUY3SRequest, //企业经营状态全景查询
|
"QYGLUY3S": qygl.ProcessQYGLUY3SRequest, //企业经营状态全景查询
|
||||||
"YYSY35TA": yysy.ProcessYYSY35TARequest, //运营商归属地数卖
|
"YYSY35TA": yysy.ProcessYYSY35TARequest, //运营商归属地数卖
|
||||||
|
|||||||
@@ -2,7 +2,9 @@ package processors
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"tyapi-server/internal/application/api/commands"
|
"tyapi-server/internal/application/api/commands"
|
||||||
|
"tyapi-server/internal/domains/api/repositories"
|
||||||
"tyapi-server/internal/infrastructure/external/alicloud"
|
"tyapi-server/internal/infrastructure/external/alicloud"
|
||||||
"tyapi-server/internal/infrastructure/external/jiguang"
|
"tyapi-server/internal/infrastructure/external/jiguang"
|
||||||
"tyapi-server/internal/infrastructure/external/muzi"
|
"tyapi-server/internal/infrastructure/external/muzi"
|
||||||
@@ -42,6 +44,9 @@ type ProcessorDependencies struct {
|
|||||||
CombService CombServiceInterface // Changed to interface to break import cycle
|
CombService CombServiceInterface // Changed to interface to break import cycle
|
||||||
Options *commands.ApiCallOptions // 添加Options支持
|
Options *commands.ApiCallOptions // 添加Options支持
|
||||||
CallContext *CallContext // 添加CallApi调用上下文
|
CallContext *CallContext // 添加CallApi调用上下文
|
||||||
|
|
||||||
|
// 企业报告记录仓储,用于持久化 QYGLJ1U9 生成的企业报告
|
||||||
|
ReportRepo repositories.ReportRepository
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewProcessorDependencies 创建处理器依赖容器
|
// NewProcessorDependencies 创建处理器依赖容器
|
||||||
@@ -58,6 +63,7 @@ func NewProcessorDependencies(
|
|||||||
shumaiService *shumai.ShumaiService,
|
shumaiService *shumai.ShumaiService,
|
||||||
validator interfaces.RequestValidator,
|
validator interfaces.RequestValidator,
|
||||||
combService CombServiceInterface, // Changed to interface
|
combService CombServiceInterface, // Changed to interface
|
||||||
|
reportRepo repositories.ReportRepository,
|
||||||
) *ProcessorDependencies {
|
) *ProcessorDependencies {
|
||||||
return &ProcessorDependencies{
|
return &ProcessorDependencies{
|
||||||
WestDexService: westDexService,
|
WestDexService: westDexService,
|
||||||
@@ -74,6 +80,7 @@ func NewProcessorDependencies(
|
|||||||
CombService: combService,
|
CombService: combService,
|
||||||
Options: nil, // 初始化为nil,在调用时设置
|
Options: nil, // 初始化为nil,在调用时设置
|
||||||
CallContext: nil, // 初始化为nil,在调用时设置
|
CallContext: nil, // 初始化为nil,在调用时设置
|
||||||
|
ReportRepo: reportRepo,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 企业全量信息核验V2(QYGLUY3S)
|
||||||
|
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)
|
||||||
|
|
||||||
|
// 企业司法涉诉V2(QYGL5S1I)
|
||||||
|
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
@@ -0,0 +1,45 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"tyapi-server/internal/domains/api/entities"
|
||||||
|
"tyapi-server/internal/domains/api/repositories"
|
||||||
|
"tyapi-server/internal/shared/database"
|
||||||
|
|
||||||
|
"go.uber.org/zap"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
ReportsTable = "reports"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GormReportRepository 报告记录 GORM 仓储实现
|
||||||
|
type GormReportRepository struct {
|
||||||
|
*database.BaseRepositoryImpl
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ repositories.ReportRepository = (*GormReportRepository)(nil)
|
||||||
|
|
||||||
|
// NewGormReportRepository 创建报告记录仓储实现
|
||||||
|
func NewGormReportRepository(db *gorm.DB, logger *zap.Logger) repositories.ReportRepository {
|
||||||
|
return &GormReportRepository{
|
||||||
|
BaseRepositoryImpl: database.NewBaseRepositoryImpl(db, logger),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create 创建报告记录
|
||||||
|
func (r *GormReportRepository) Create(ctx context.Context, report *entities.Report) error {
|
||||||
|
return r.CreateEntity(ctx, report)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindByReportID 根据报告编号查询记录
|
||||||
|
func (r *GormReportRepository) FindByReportID(ctx context.Context, reportID string) (*entities.Report, error) {
|
||||||
|
var report entities.Report
|
||||||
|
if err := r.FindOneByField(ctx, &report, "report_id", reportID); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &report, nil
|
||||||
|
}
|
||||||
|
|
||||||
137
internal/infrastructure/http/handlers/qygl_report_handler.go
Normal file
137
internal/infrastructure/http/handlers/qygl_report_handler.go
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
package handlers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"html/template"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"go.uber.org/zap"
|
||||||
|
|
||||||
|
"tyapi-server/internal/application/api/commands"
|
||||||
|
"tyapi-server/internal/domains/api/dto"
|
||||||
|
api_repositories "tyapi-server/internal/domains/api/repositories"
|
||||||
|
api_services "tyapi-server/internal/domains/api/services"
|
||||||
|
"tyapi-server/internal/domains/api/services/processors"
|
||||||
|
"tyapi-server/internal/domains/api/services/processors/qygl"
|
||||||
|
)
|
||||||
|
|
||||||
|
// QYGLReportHandler 企业全景报告页面渲染处理器
|
||||||
|
// 使用 QYGLJ1U9 聚合接口生成企业报告数据,并通过模板引擎渲染 qiye.html
|
||||||
|
type QYGLReportHandler struct {
|
||||||
|
apiRequestService *api_services.ApiRequestService
|
||||||
|
logger *zap.Logger
|
||||||
|
|
||||||
|
reportRepo api_repositories.ReportRepository
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewQYGLReportHandler 创建企业报告页面处理器
|
||||||
|
func NewQYGLReportHandler(
|
||||||
|
apiRequestService *api_services.ApiRequestService,
|
||||||
|
logger *zap.Logger,
|
||||||
|
reportRepo api_repositories.ReportRepository,
|
||||||
|
) *QYGLReportHandler {
|
||||||
|
return &QYGLReportHandler{
|
||||||
|
apiRequestService: apiRequestService,
|
||||||
|
logger: logger,
|
||||||
|
reportRepo: reportRepo,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetQYGLReportPage 企业全景报告页面
|
||||||
|
// GET /reports/qygl?ent_code=xxx&ent_name=yyy&ent_reg_no=zzz
|
||||||
|
func (h *QYGLReportHandler) GetQYGLReportPage(c *gin.Context) {
|
||||||
|
// 读取查询参数
|
||||||
|
entCode := c.Query("ent_code")
|
||||||
|
entName := c.Query("ent_name")
|
||||||
|
entRegNo := c.Query("ent_reg_no")
|
||||||
|
|
||||||
|
// 组装 QYGLUY3S 入参
|
||||||
|
req := dto.QYGLUY3SReq{
|
||||||
|
EntName: entName,
|
||||||
|
EntRegno: entRegNo,
|
||||||
|
EntCode: entCode,
|
||||||
|
}
|
||||||
|
|
||||||
|
params, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
h.logger.Error("序列化企业全景报告入参失败", zap.Error(err))
|
||||||
|
c.String(http.StatusInternalServerError, "生成企业报告失败,请稍后重试")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 通过 ApiRequestService 调用 QYGLJ1U9 聚合处理器
|
||||||
|
options := &commands.ApiCallOptions{}
|
||||||
|
callCtx := &processors.CallContext{}
|
||||||
|
|
||||||
|
ctx := c.Request.Context()
|
||||||
|
respBytes, err := h.apiRequestService.PreprocessRequestApi(ctx, "QYGLJ1U9", params, options, callCtx)
|
||||||
|
if err != nil {
|
||||||
|
h.logger.Error("调用企业全景报告处理器失败", zap.Error(err))
|
||||||
|
c.String(http.StatusInternalServerError, "生成企业报告失败,请稍后重试")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var report map[string]interface{}
|
||||||
|
if err := json.Unmarshal(respBytes, &report); err != nil {
|
||||||
|
h.logger.Error("解析企业全景报告结果失败", zap.Error(err))
|
||||||
|
c.String(http.StatusInternalServerError, "生成企业报告失败,请稍后重试")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
reportJSONBytes, err := json.Marshal(report)
|
||||||
|
if err != nil {
|
||||||
|
h.logger.Error("序列化企业全景报告结果失败", zap.Error(err))
|
||||||
|
c.String(http.StatusInternalServerError, "生成企业报告失败,请稍后重试")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用 template.JS 避免在脚本中被转义,直接作为 JS 对象字面量注入
|
||||||
|
reportJSON := template.JS(reportJSONBytes)
|
||||||
|
|
||||||
|
c.HTML(http.StatusOK, "qiye.html", gin.H{
|
||||||
|
"ReportJSON": reportJSON,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetQYGLReportPageByID 通过编号查看企业全景报告页面
|
||||||
|
// GET /reports/qygl/:id
|
||||||
|
func (h *QYGLReportHandler) GetQYGLReportPageByID(c *gin.Context) {
|
||||||
|
id := c.Param("id")
|
||||||
|
if id == "" {
|
||||||
|
c.String(http.StatusBadRequest, "报告编号不能为空")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 优先从数据库中查询报告记录
|
||||||
|
if h.reportRepo != nil {
|
||||||
|
if entity, err := h.reportRepo.FindByReportID(c.Request.Context(), id); err == nil && entity != nil {
|
||||||
|
reportJSON := template.JS(entity.ReportData)
|
||||||
|
c.HTML(http.StatusOK, "qiye.html", gin.H{
|
||||||
|
"ReportJSON": reportJSON,
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 回退到进程内存缓存(兼容老的访问方式)
|
||||||
|
report, ok := qygl.GetQYGLReport(id)
|
||||||
|
if !ok {
|
||||||
|
c.String(http.StatusNotFound, "报告不存在或已过期")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
reportJSONBytes, err := json.Marshal(report)
|
||||||
|
if err != nil {
|
||||||
|
h.logger.Error("序列化企业全景报告结果失败", zap.Error(err))
|
||||||
|
c.String(http.StatusInternalServerError, "生成企业报告失败,请稍后再试")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
reportJSON := template.JS(reportJSONBytes)
|
||||||
|
|
||||||
|
c.HTML(http.StatusOK, "qiye.html", gin.H{
|
||||||
|
"ReportJSON": reportJSON,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
32
internal/infrastructure/http/routes/qygl_report_routes.go
Normal file
32
internal/infrastructure/http/routes/qygl_report_routes.go
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
package routes
|
||||||
|
|
||||||
|
import (
|
||||||
|
"tyapi-server/internal/infrastructure/http/handlers"
|
||||||
|
sharedhttp "tyapi-server/internal/shared/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
// QYGLReportRoutes 企业报告页面路由注册器
|
||||||
|
type QYGLReportRoutes struct {
|
||||||
|
handler *handlers.QYGLReportHandler
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewQYGLReportRoutes 创建企业报告页面路由注册器
|
||||||
|
func NewQYGLReportRoutes(
|
||||||
|
handler *handlers.QYGLReportHandler,
|
||||||
|
) *QYGLReportRoutes {
|
||||||
|
return &QYGLReportRoutes{
|
||||||
|
handler: handler,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register 注册企业报告页面路由
|
||||||
|
func (r *QYGLReportRoutes) Register(router *sharedhttp.GinRouter) {
|
||||||
|
engine := router.GetEngine()
|
||||||
|
|
||||||
|
// 企业全景报告页面(实时生成)
|
||||||
|
engine.GET("/reports/qygl", r.handler.GetQYGLReportPage)
|
||||||
|
|
||||||
|
// 企业全景报告页面(通过编号查看)
|
||||||
|
engine.GET("/reports/qygl/:id", r.handler.GetQYGLReportPageByID)
|
||||||
|
}
|
||||||
|
|
||||||
@@ -37,6 +37,10 @@ func NewGinRouter(cfg *config.Config, logger *zap.Logger) *GinRouter {
|
|||||||
// 创建Gin引擎
|
// 创建Gin引擎
|
||||||
engine := gin.New()
|
engine := gin.New()
|
||||||
|
|
||||||
|
// 加载HTML模板(企业报告等页面)
|
||||||
|
// 这里直接加载项目根目录下的 qiye.html,后续如有更多模板可改为 LoadHTMLGlob
|
||||||
|
engine.LoadHTMLFiles("qiye.html")
|
||||||
|
|
||||||
return &GinRouter{
|
return &GinRouter{
|
||||||
engine: engine,
|
engine: engine,
|
||||||
config: cfg,
|
config: cfg,
|
||||||
|
|||||||
Reference in New Issue
Block a user