feat: 更新CC码监管方案业务版文档,新增摘要、UGC专项、直播专项、存量处置、误判申诉、水印嵌入、CC码生命周期、组织保障等章节;同步macode到cccode重命名及其他代码变更
This commit is contained in:
@@ -25,11 +25,11 @@ import (
|
||||
// 聚合多省标识数据,提供统一查询入口。
|
||||
type NationalCatalog struct {
|
||||
mu stdsync.RWMutex
|
||||
contents map[string]model.Content // maCode -> Content
|
||||
bindings map[string][]model.HashBinding // maCode -> bindings
|
||||
mappings map[string][]model.Mapping // maCode -> mappings
|
||||
contents map[string]model.Content // ccCode -> Content
|
||||
bindings map[string][]model.HashBinding // ccCode -> bindings
|
||||
mappings map[string][]model.Mapping // ccCode -> mappings
|
||||
provinces map[string]*ProvinceInfo // provinceCode -> 省级信息
|
||||
auditShared map[string][]model.ProvenanceEvent // maCode -> 跨省共享审核记录
|
||||
auditShared map[string][]model.ProvenanceEvent // ccCode -> 跨省共享审核记录
|
||||
}
|
||||
|
||||
// ProvinceInfo 省级节点信息。
|
||||
@@ -81,44 +81,44 @@ func (nc *NationalCatalog) ListProvinces() []ProvinceInfo {
|
||||
func (nc *NationalCatalog) UpsertContent(c model.Content) error {
|
||||
nc.mu.Lock()
|
||||
defer nc.mu.Unlock()
|
||||
if _, exists := nc.contents[c.MACode]; exists {
|
||||
if _, exists := nc.contents[c.CCCode]; exists {
|
||||
return syncpkg.ErrConflict
|
||||
}
|
||||
nc.contents[c.MACode] = c
|
||||
nc.contents[c.CCCode] = c
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpsertBinding 写入/更新哈希绑定。
|
||||
func (nc *NationalCatalog) UpsertBinding(maCode string, b model.HashBinding) error {
|
||||
func (nc *NationalCatalog) UpsertBinding(ccCode string, b model.HashBinding) error {
|
||||
nc.mu.Lock()
|
||||
defer nc.mu.Unlock()
|
||||
nc.bindings[maCode] = append(nc.bindings[maCode], b)
|
||||
nc.bindings[ccCode] = append(nc.bindings[ccCode], b)
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpsertMapping 写入/更新映射。
|
||||
func (nc *NationalCatalog) UpsertMapping(maCode string, m model.Mapping) error {
|
||||
func (nc *NationalCatalog) UpsertMapping(ccCode string, m model.Mapping) error {
|
||||
nc.mu.Lock()
|
||||
defer nc.mu.Unlock()
|
||||
nc.mappings[maCode] = append(nc.mappings[maCode], m)
|
||||
nc.mappings[ccCode] = append(nc.mappings[ccCode], m)
|
||||
return nil
|
||||
}
|
||||
|
||||
// ---- 全国统一查询 ----
|
||||
|
||||
// QueryByMA 按 MA 码查询(全国维度)。
|
||||
func (nc *NationalCatalog) QueryByMA(maCode string) (model.ContentQueryResult, error) {
|
||||
func (nc *NationalCatalog) QueryByMA(ccCode string) (model.ContentQueryResult, error) {
|
||||
nc.mu.RLock()
|
||||
defer nc.mu.RUnlock()
|
||||
c, ok := nc.contents[maCode]
|
||||
c, ok := nc.contents[ccCode]
|
||||
if !ok {
|
||||
return model.ContentQueryResult{Found: false}, fmt.Errorf("national: MA 码 %s 未找到", maCode)
|
||||
return model.ContentQueryResult{Found: false}, fmt.Errorf("national: MA 码 %s 未找到", ccCode)
|
||||
}
|
||||
return model.ContentQueryResult{
|
||||
Found: true,
|
||||
Content: c,
|
||||
Bindings: nc.bindings[maCode],
|
||||
Mappings: nc.mappings[maCode],
|
||||
Bindings: nc.bindings[ccCode],
|
||||
Mappings: nc.mappings[ccCode],
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -127,25 +127,25 @@ func (nc *NationalCatalog) QueryByHash(fileHash string) (model.ContentQueryResul
|
||||
nc.mu.RLock()
|
||||
defer nc.mu.RUnlock()
|
||||
// 先搜索 Content.FileHash(整剧主哈希)
|
||||
for maCode, c := range nc.contents {
|
||||
for ccCode, c := range nc.contents {
|
||||
if c.FileHash == fileHash {
|
||||
return model.ContentQueryResult{
|
||||
Found: true,
|
||||
Content: c,
|
||||
Bindings: nc.bindings[maCode],
|
||||
Mappings: nc.mappings[maCode],
|
||||
Bindings: nc.bindings[ccCode],
|
||||
Mappings: nc.mappings[ccCode],
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
// 再搜索 bindings 中的 HashValue(集级/转码版哈希)
|
||||
for maCode, bindings := range nc.bindings {
|
||||
for ccCode, bindings := range nc.bindings {
|
||||
for _, b := range bindings {
|
||||
if b.HashValue == fileHash {
|
||||
return model.ContentQueryResult{
|
||||
Found: true,
|
||||
Content: nc.contents[maCode],
|
||||
Content: nc.contents[ccCode],
|
||||
Bindings: bindings,
|
||||
Mappings: nc.mappings[maCode],
|
||||
Mappings: nc.mappings[ccCode],
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
@@ -157,13 +157,13 @@ func (nc *NationalCatalog) QueryByHash(fileHash string) (model.ContentQueryResul
|
||||
func (nc *NationalCatalog) QueryByProvincialCode(provincialCode string) (model.ContentQueryResult, error) {
|
||||
nc.mu.RLock()
|
||||
defer nc.mu.RUnlock()
|
||||
for maCode, mappings := range nc.mappings {
|
||||
for ccCode, mappings := range nc.mappings {
|
||||
for _, mp := range mappings {
|
||||
if mp.Party == model.PartyCP && mp.PartyID == provincialCode {
|
||||
return model.ContentQueryResult{
|
||||
Found: true,
|
||||
Content: nc.contents[maCode],
|
||||
Bindings: nc.bindings[maCode],
|
||||
Content: nc.contents[ccCode],
|
||||
Bindings: nc.bindings[ccCode],
|
||||
Mappings: mappings,
|
||||
}, nil
|
||||
}
|
||||
@@ -175,17 +175,17 @@ func (nc *NationalCatalog) QueryByProvincialCode(provincialCode string) (model.C
|
||||
// ---- 跨省审核记录共享 ----
|
||||
|
||||
// ShareAuditRecord 省级节点上报审核记录至全国中心。
|
||||
func (nc *NationalCatalog) ShareAuditRecord(maCode string, event model.ProvenanceEvent) {
|
||||
func (nc *NationalCatalog) ShareAuditRecord(ccCode string, event model.ProvenanceEvent) {
|
||||
nc.mu.Lock()
|
||||
defer nc.mu.Unlock()
|
||||
nc.auditShared[maCode] = append(nc.auditShared[maCode], event)
|
||||
nc.auditShared[ccCode] = append(nc.auditShared[ccCode], event)
|
||||
}
|
||||
|
||||
// QuerySharedAudit 查询跨省共享的审核记录。
|
||||
func (nc *NationalCatalog) QuerySharedAudit(maCode string) []model.ProvenanceEvent {
|
||||
func (nc *NationalCatalog) QuerySharedAudit(ccCode string) []model.ProvenanceEvent {
|
||||
nc.mu.RLock()
|
||||
defer nc.mu.RUnlock()
|
||||
return nc.auditShared[maCode]
|
||||
return nc.auditShared[ccCode]
|
||||
}
|
||||
|
||||
// ---- 全国统计 ----
|
||||
@@ -214,7 +214,7 @@ func (nc *NationalCatalog) Stats() NationalStats {
|
||||
st.ByStatus[c.Status]++
|
||||
st.ByCategory[c.MAType]++
|
||||
// 按机构节点统计省份
|
||||
for _, mp := range nc.mappings[c.MACode] {
|
||||
for _, mp := range nc.mappings[c.CCCode] {
|
||||
if mp.Party == model.PartyCP {
|
||||
st.ByProvince[mp.PartyName]++
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ func TestNationalCatalog_SyncFromProvince(t *testing.T) {
|
||||
// 源端发码
|
||||
srcClient := chain.NewMemoryChain()
|
||||
_, err := srcClient.IssueMA(chain.RoleRegulator, chain.IssueRequest{
|
||||
MACode: "MA.156.8531.6101/WD/20260000001", ContentTwinID: "ctid-nat-001",
|
||||
CCCode: "MA.156.8531.6101/WD/20260000001", ContentTwinID: "ctid-nat-001",
|
||||
FileHash: "fh-nat-001", MerkleRoot: "mr-nat-001",
|
||||
Episodes: []model.EpisodeHash{
|
||||
{Episode: 1, FileSHA256: "fh-nat-001-E1"},
|
||||
@@ -74,7 +74,7 @@ func TestNationalCatalog_Stats(t *testing.T) {
|
||||
|
||||
srcClient := chain.NewMemoryChain()
|
||||
_, err := srcClient.IssueMA(chain.RoleRegulator, chain.IssueRequest{
|
||||
MACode: "MA.156.8531.6101/WD/20260000002", ContentTwinID: "ctid-nat-002",
|
||||
CCCode: "MA.156.8531.6101/WD/20260000002", ContentTwinID: "ctid-nat-002",
|
||||
FileHash: "fh-nat-002", MerkleRoot: "mr-nat-002",
|
||||
Content: model.Content{Title: "统计测试剧", MAType: "WD", Issuer: "陕西局"},
|
||||
})
|
||||
@@ -98,7 +98,7 @@ func TestNationalCatalog_Stats(t *testing.T) {
|
||||
func TestNationalCatalog_ShareAuditRecord(t *testing.T) {
|
||||
nc := New()
|
||||
nc.ShareAuditRecord("MA.156.8531.6101/WD/20260000003", model.ProvenanceEvent{
|
||||
MACode: "MA.156.8531.6101/WD/20260000003",
|
||||
CCCode: "MA.156.8531.6101/WD/20260000003",
|
||||
Node: model.NodeIssue,
|
||||
Operator: "陕西局",
|
||||
Detail: "跨省审核记录",
|
||||
|
||||
Reference in New Issue
Block a user