feat(phase3): 备案对接/全国统计/号段管理/BFF安全化/链合约源码
- A.1 备案对接: BindFiling/QueryFiling 关联网标号+备案号 - A.2 监管上报: DailyRegulatoryReport 日报 - B.1 号段管理: ListSegments + /admin/segments - C.1/C.2 全国统计按省聚合 + 跨省协同(单一可信源天然联动) - F.2 全国监管大屏: NationalStats(按省/类目/状态) - B(遗留) 监管大屏BFF: internal/bff + cmd/console-bff, 密钥仅存后端浏览器只用会话令牌 - G 真实链合约源码: contracts/tcs_registry/registry.go (ChainMaker Go) - 新增9个API+BFF服务; 5项新测试; 端到端BFF验证 - D/E(压测/等保/HSM)/F.1(标准)/真实链部署 标注需外部环境
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/tcs-iptv/tcs/internal/macode"
|
||||
"github.com/tcs-iptv/tcs/internal/model"
|
||||
)
|
||||
|
||||
// 三期:备案对接、全国统计、号段管理、监管上报。
|
||||
|
||||
// 机构节点 → 省份映射(与发码机构号段分配一致;示例覆盖部分省)。
|
||||
var orgNodeProvince = map[string]string{
|
||||
"6101": "陕西", "4401": "广东", "3301": "浙江", "3201": "江苏",
|
||||
"1101": "北京", "3101": "上海", "5101": "四川", "4201": "湖北",
|
||||
}
|
||||
|
||||
// BindFiling 关联备案号/网标号至 MA 码(三期 A.1,对接广电总局备案系统)。
|
||||
func (s *Service) BindFiling(maCode, licenseNo, filingNo string) (model.FilingRecord, error) {
|
||||
if _, err := s.chain.QueryContent(maCode); err != nil {
|
||||
return model.FilingRecord{}, err
|
||||
}
|
||||
rec := model.FilingRecord{
|
||||
MACode: maCode, LicenseNo: licenseNo, FilingNo: filingNo,
|
||||
BoundAt: time.Now().Format(time.RFC3339),
|
||||
}
|
||||
s.mu.Lock()
|
||||
s.filings[maCode] = rec
|
||||
s.mu.Unlock()
|
||||
s.prov.Record(model.ProvenanceEvent{
|
||||
MACode: maCode, Node: model.NodeIssue, Operator: "广电总局备案系统",
|
||||
Detail: "关联网标号 " + licenseNo + " / 备案号 " + filingNo,
|
||||
})
|
||||
return rec, nil
|
||||
}
|
||||
|
||||
// QueryFiling 查询备案关联。
|
||||
func (s *Service) QueryFiling(maCode string) (model.FilingRecord, bool) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
r, ok := s.filings[maCode]
|
||||
return r, ok
|
||||
}
|
||||
|
||||
// NationalStats 全国监管统计(三期 A.2/F.2)。
|
||||
func (s *Service) NationalStats() (model.NationalStats, error) {
|
||||
all, err := s.chain.ListContents("")
|
||||
if err != nil {
|
||||
return model.NationalStats{}, err
|
||||
}
|
||||
st := model.NationalStats{
|
||||
ByStatus: map[string]int{},
|
||||
ByCategory: map[string]int{},
|
||||
ByProvince: map[string]model.ProvinceStat{},
|
||||
}
|
||||
st.TotalContents = len(all)
|
||||
for _, c := range all {
|
||||
st.ByStatus[c.Status]++
|
||||
p, perr := macode.Parse(c.MACode)
|
||||
if perr == nil {
|
||||
st.ByCategory[p.Category]++
|
||||
prov := orgNodeProvince[p.OrgNode]
|
||||
if prov == "" {
|
||||
prov = "其他(" + p.OrgNode + ")"
|
||||
}
|
||||
ps := st.ByProvince[prov]
|
||||
ps.Province = prov
|
||||
ps.OrgNode = p.OrgNode
|
||||
ps.Total++
|
||||
switch c.Status {
|
||||
case model.StatusPublished:
|
||||
ps.Published++
|
||||
case model.StatusRevoked:
|
||||
ps.Revoked++
|
||||
}
|
||||
st.ByProvince[prov] = ps
|
||||
}
|
||||
}
|
||||
return st, nil
|
||||
}
|
||||
|
||||
// ListSegments 列出已登记号段及使用情况(三期 B.1)。
|
||||
func (s *Service) ListSegments() []macode.SegmentInfo {
|
||||
return s.gen.Segments()
|
||||
}
|
||||
|
||||
// RegisterSegment 登记新号段(三期 B.1,与发码机构对接后配置)。
|
||||
func (s *Service) RegisterSegment(seg macode.Segment) error {
|
||||
return s.gen.RegisterSegment(seg)
|
||||
}
|
||||
|
||||
// DailyRegulatoryReport 生成监管数据上报日报(三期 A.2)。
|
||||
func (s *Service) DailyRegulatoryReport(date string) (model.RegulatoryReport, error) {
|
||||
all, err := s.chain.ListContents("")
|
||||
if err != nil {
|
||||
return model.RegulatoryReport{}, err
|
||||
}
|
||||
rep := model.RegulatoryReport{
|
||||
ReportType: "daily_summary", Date: date,
|
||||
LevelDist: map[string]int{},
|
||||
}
|
||||
for _, c := range all {
|
||||
rep.TotalNew++
|
||||
if p, perr := macode.Parse(c.MACode); perr == nil {
|
||||
rep.LevelDist[p.Category]++
|
||||
}
|
||||
if c.Status == model.StatusRevoked {
|
||||
rep.RevokedCnt++
|
||||
}
|
||||
}
|
||||
s.mu.Lock()
|
||||
rep.BlacklistCnt = len(s.black)
|
||||
s.mu.Unlock()
|
||||
return rep, nil
|
||||
}
|
||||
Reference in New Issue
Block a user