feat: 更新CC码监管方案业务版文档,新增摘要、UGC专项、直播专项、存量处置、误判申诉、水印嵌入、CC码生命周期、组织保障等章节;同步macode到cccode重命名及其他代码变更
This commit is contained in:
@@ -40,9 +40,9 @@ func (p *PersistentChain) IssueMA(role Role, req IssueRequest) (string, error) {
|
||||
if err != nil {
|
||||
return tx, err
|
||||
}
|
||||
c, _ := p.MemoryChain.QueryContent(req.MACode)
|
||||
c, _ := p.MemoryChain.QueryContent(req.CCCode)
|
||||
p.persistContent(c)
|
||||
for _, b := range p.snapshotBindings(req.MACode) {
|
||||
for _, b := range p.snapshotBindings(req.CCCode) {
|
||||
p.persistBinding(b)
|
||||
}
|
||||
p.persistTx(req.ContentTwinID, tx, "issueMA")
|
||||
@@ -86,48 +86,48 @@ func (p *PersistentChain) RecordVersionChange(vc model.VersionChange) (string, e
|
||||
}
|
||||
|
||||
// Revoke 整剧下架:镜像内容状态。
|
||||
func (p *PersistentChain) Revoke(role Role, maCode, reason string) (MappingsResult, error) {
|
||||
res, err := p.MemoryChain.Revoke(role, maCode, reason)
|
||||
func (p *PersistentChain) Revoke(role Role, ccCode, reason string) (MappingsResult, error) {
|
||||
res, err := p.MemoryChain.Revoke(role, ccCode, reason)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
p.updateStatus(maCode, model.StatusRevoked)
|
||||
p.updateStatus(ccCode, model.StatusRevoked)
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// Restore 整剧恢复上架:镜像内容状态。
|
||||
func (p *PersistentChain) Restore(role Role, maCode string) error {
|
||||
if err := p.MemoryChain.Restore(role, maCode); err != nil {
|
||||
func (p *PersistentChain) Restore(role Role, ccCode string) error {
|
||||
if err := p.MemoryChain.Restore(role, ccCode); err != nil {
|
||||
return err
|
||||
}
|
||||
p.updateStatus(maCode, model.StatusPublished)
|
||||
p.updateStatus(ccCode, model.StatusPublished)
|
||||
return nil
|
||||
}
|
||||
|
||||
// RevokeEpisode 集级下架:镜像该集 revoked 标记。
|
||||
func (p *PersistentChain) RevokeEpisode(role Role, maCode string, episode int, reason string) error {
|
||||
if err := p.MemoryChain.RevokeEpisode(role, maCode, episode, reason); err != nil {
|
||||
func (p *PersistentChain) RevokeEpisode(role Role, ccCode string, episode int, reason string) error {
|
||||
if err := p.MemoryChain.RevokeEpisode(role, ccCode, episode, reason); err != nil {
|
||||
return err
|
||||
}
|
||||
p.updateEpisodeRevoked(maCode, episode, true, reason)
|
||||
p.updateEpisodeRevoked(ccCode, episode, true, reason)
|
||||
return nil
|
||||
}
|
||||
|
||||
// RestoreEpisode 集级恢复:镜像该集 revoked 标记。
|
||||
func (p *PersistentChain) RestoreEpisode(role Role, maCode string, episode int) error {
|
||||
if err := p.MemoryChain.RestoreEpisode(role, maCode, episode); err != nil {
|
||||
func (p *PersistentChain) RestoreEpisode(role Role, ccCode string, episode int) error {
|
||||
if err := p.MemoryChain.RestoreEpisode(role, ccCode, episode); err != nil {
|
||||
return err
|
||||
}
|
||||
p.updateEpisodeRevoked(maCode, episode, false, "")
|
||||
p.updateEpisodeRevoked(ccCode, episode, false, "")
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetContentStatus 状态流转(入库/发布等):镜像内容状态。
|
||||
func (p *PersistentChain) SetContentStatus(maCode, status string) error {
|
||||
if err := p.MemoryChain.SetContentStatus(maCode, status); err != nil {
|
||||
func (p *PersistentChain) SetContentStatus(ccCode, status string) error {
|
||||
if err := p.MemoryChain.SetContentStatus(ccCode, status); err != nil {
|
||||
return err
|
||||
}
|
||||
p.updateStatus(maCode, status)
|
||||
p.updateStatus(ccCode, status)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -138,14 +138,14 @@ func (p *PersistentChain) MergeMA(role Role, req model.MergeRequest) (model.Merg
|
||||
return res, err
|
||||
}
|
||||
// 被合并的 MA 码状态标记为 merged
|
||||
for _, secMA := range req.SecondaryMACodes {
|
||||
for _, secMA := range req.SecondaryCCCodes {
|
||||
p.updateStatus(secMA, model.StatusMerged)
|
||||
}
|
||||
// 主 MA 码的绑定和映射已在内存中追加,写穿最新状态
|
||||
for _, b := range p.snapshotBindings(req.PrimaryMACode) {
|
||||
for _, b := range p.snapshotBindings(req.PrimaryCCCode) {
|
||||
p.persistBinding(b)
|
||||
}
|
||||
p.persistTx(req.PrimaryMACode, res.TxID, "mergeMA")
|
||||
p.persistTx(req.PrimaryCCCode, res.TxID, "mergeMA")
|
||||
return res, nil
|
||||
}
|
||||
|
||||
@@ -156,9 +156,9 @@ func (p *PersistentChain) SplitMA(role Role, req model.SplitRequest) (model.Spli
|
||||
return res, err
|
||||
}
|
||||
// 源 MA 码状态标记为 split
|
||||
p.updateStatus(req.SourceMACode, model.StatusSplit)
|
||||
p.updateStatus(req.SourceCCCode, model.StatusSplit)
|
||||
// 新 MA 码的内容记录和绑定写穿
|
||||
for _, newMA := range res.NewMACodes {
|
||||
for _, newMA := range res.NewCCCodes {
|
||||
c, _ := p.MemoryChain.QueryContent(newMA)
|
||||
p.persistContent(c)
|
||||
for _, b := range p.snapshotBindings(newMA) {
|
||||
@@ -168,7 +168,7 @@ func (p *PersistentChain) SplitMA(role Role, req model.SplitRequest) (model.Spli
|
||||
p.persistMapping(mp)
|
||||
}
|
||||
}
|
||||
p.persistTx(req.SourceMACode, res.TxID, "splitMA")
|
||||
p.persistTx(req.SourceCCCode, res.TxID, "splitMA")
|
||||
return res, nil
|
||||
}
|
||||
|
||||
@@ -189,7 +189,7 @@ func (p *PersistentChain) persistContent(c model.Content) {
|
||||
(content_twin_id, ma_code, ma_type, title, episode_count, status, issuer, issue_date, created_at)
|
||||
VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9)
|
||||
ON CONFLICT (content_twin_id) DO UPDATE SET status=EXCLUDED.status, updated_at=NOW()`,
|
||||
c.ContentTwinID, c.MACode, c.MAType, c.Title, c.EpisodeCount, c.Status, c.Issuer, issueDate, c.CreatedAt)
|
||||
c.ContentTwinID, c.CCCode, c.MAType, c.Title, c.EpisodeCount, c.Status, c.Issuer, issueDate, c.CreatedAt)
|
||||
}
|
||||
|
||||
func (p *PersistentChain) persistBinding(b model.HashBinding) {
|
||||
@@ -214,32 +214,32 @@ func (p *PersistentChain) persistTx(ctid, txID, method string) {
|
||||
ctid, txID, method)
|
||||
}
|
||||
|
||||
func (p *PersistentChain) updateStatus(maCode, status string) {
|
||||
p.exec(`UPDATE content_registry SET status=$1, updated_at=NOW() WHERE ma_code=$2`, status, maCode)
|
||||
func (p *PersistentChain) updateStatus(ccCode, status string) {
|
||||
p.exec(`UPDATE content_registry SET status=$1, updated_at=NOW() WHERE ma_code=$2`, status, ccCode)
|
||||
}
|
||||
|
||||
func (p *PersistentChain) updateEpisodeRevoked(maCode string, episode int, revoked bool, reason string) {
|
||||
func (p *PersistentChain) updateEpisodeRevoked(ccCode string, episode int, revoked bool, reason string) {
|
||||
p.exec(`UPDATE hash_binding hb SET revoked=$1, revoked_reason=$2
|
||||
FROM content_registry cr
|
||||
WHERE hb.content_twin_id = cr.content_twin_id AND cr.ma_code=$3 AND hb.episode=$4`,
|
||||
revoked, reason, maCode, episode)
|
||||
revoked, reason, ccCode, episode)
|
||||
}
|
||||
|
||||
// snapshotBindings 复制某 MA 码当前的内存绑定(同包访问,读锁保护)。
|
||||
func (p *PersistentChain) snapshotBindings(maCode string) []model.HashBinding {
|
||||
func (p *PersistentChain) snapshotBindings(ccCode string) []model.HashBinding {
|
||||
p.mu.RLock()
|
||||
defer p.mu.RUnlock()
|
||||
src := p.bindings[maCode]
|
||||
src := p.bindings[ccCode]
|
||||
out := make([]model.HashBinding, len(src))
|
||||
copy(out, src)
|
||||
return out
|
||||
}
|
||||
|
||||
// snapshotMappings 复制某 MA 码当前的内存映射(同包访问,读锁保护)。
|
||||
func (p *PersistentChain) snapshotMappings(maCode string) []model.Mapping {
|
||||
func (p *PersistentChain) snapshotMappings(ccCode string) []model.Mapping {
|
||||
p.mu.RLock()
|
||||
defer p.mu.RUnlock()
|
||||
src := p.mappings[maCode]
|
||||
src := p.mappings[ccCode]
|
||||
out := make([]model.Mapping, len(src))
|
||||
copy(out, src)
|
||||
return out
|
||||
@@ -248,7 +248,7 @@ func (p *PersistentChain) snapshotMappings(maCode string) []model.Mapping {
|
||||
// ---- 启动水合:从 PG 镜像恢复内存状态 ----
|
||||
|
||||
func (p *PersistentChain) hydrate() error {
|
||||
// 1) 内容主表 + 建立 ctid -> maCode 映射
|
||||
// 1) 内容主表 + 建立 ctid -> ccCode 映射
|
||||
ctidToMA := map[string]string{}
|
||||
rows, err := p.db.Query(`SELECT content_twin_id, ma_code, COALESCE(ma_type,''), title,
|
||||
COALESCE(episode_count,1), status, COALESCE(issuer,''),
|
||||
@@ -259,13 +259,13 @@ func (p *PersistentChain) hydrate() error {
|
||||
n := 0
|
||||
for rows.Next() {
|
||||
var c model.Content
|
||||
if err := rows.Scan(&c.ContentTwinID, &c.MACode, &c.MAType, &c.Title,
|
||||
if err := rows.Scan(&c.ContentTwinID, &c.CCCode, &c.MAType, &c.Title,
|
||||
&c.EpisodeCount, &c.Status, &c.Issuer, &c.IssueDate, &c.CreatedAt); err != nil {
|
||||
rows.Close()
|
||||
return err
|
||||
}
|
||||
p.contents[c.MACode] = c
|
||||
ctidToMA[c.ContentTwinID] = c.MACode
|
||||
p.contents[c.CCCode] = c
|
||||
ctidToMA[c.ContentTwinID] = c.CCCode
|
||||
n++
|
||||
}
|
||||
rows.Close()
|
||||
|
||||
Reference in New Issue
Block a user