diff --git a/biz/service/seed/annotate.go b/biz/service/seed/annotate.go new file mode 100644 index 0000000..089c94f --- /dev/null +++ b/biz/service/seed/annotate.go @@ -0,0 +1,49 @@ +package seed + +import ( + "context" + + "github.com/gogf/gf/v2/database/gdb" + "github.com/gogf/gf/v2/frame/g" + + "36wisdom/biz/consts" + "36wisdom/common" +) + +// annotateAll 拼音补标:对 *_pinyin 为空的记录按原文标注。 +// 启动维护一次性(约 500 行),单事务内逐行 UPDATE,失败告警不阻断。 +// 注意:迁移补列的历史记录为 NULL,须同时匹配 '' 与 NULL。 +func annotateAll(ctx context.Context) { + type target struct{ table, pinyinCol, textCol string } + targets := []target{ + {consts.TableStrategy, "meaning_pinyin", "meaning"}, + {consts.TableStrategy, "teach_content_pinyin", "teach_content"}, + {consts.TableStrategy, "summary_q_pinyin", "summary_q"}, + {consts.TableStrategy, "summary_options_pinyin", "summary_options"}, + {consts.TableLevel, "scene_content_pinyin", "scene_content"}, + {consts.TableSceneNode, "content_pinyin", "content"}, + {consts.TableNodeOption, "text_pinyin", "text"}, + {consts.TableNodeOption, "feedback_pinyin", "feedback"}, + {consts.TableElement, "name_pinyin", "name"}, + {consts.TableElement, "description_pinyin", "description"}, + } + if err := g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) error { + for _, t := range targets { + recs, err := tx.Model(t.table).Ctx(ctx).Where(t.pinyinCol, "").WhereOr(t.pinyinCol, nil).Fields("id," + t.textCol).All() + if err != nil { + return err + } + for _, rec := range recs { + if _, err := tx.Model(t.table).Ctx(ctx).WherePri(rec["id"].Int64()). + Data(g.Map{t.pinyinCol: common.AnnotatePinyin(rec[t.textCol].String())}).Update(); err != nil { + return err + } + } + } + return nil + }); err != nil { + g.Log().Warningf(ctx, "seed: 拼音补标失败: %v", err) + return + } + g.Log().Info(ctx, "seed: 拼音补标完成") +} diff --git a/biz/service/seed/seed.go b/biz/service/seed/seed.go index feacaa0..683175a 100644 --- a/biz/service/seed/seed.go +++ b/biz/service/seed/seed.go @@ -16,6 +16,7 @@ import ( "36wisdom/biz/consts" "36wisdom/biz/dao" + "36wisdom/common" ) //go:embed seed_36_ji/*.json @@ -122,12 +123,14 @@ func EnsureSeeded(ctx context.Context) { } if count > 0 { g.Log().Info(ctx, "seed: 数据已存在,跳过种子导入") - return + } else { + if err := doSeed(ctx); err != nil { + g.Log().Fatal(ctx, err) + } + g.Log().Info(ctx, "seed: 种子数据导入完成") } - if err := doSeed(ctx); err != nil { - g.Log().Fatal(ctx, err) - } - g.Log().Info(ctx, "seed: 种子数据导入完成") + annotateAll(ctx) + // ensureInteractions(ctx) // Task 4 打开 } func doSeed(ctx context.Context) (err error) { @@ -206,8 +209,10 @@ func insertElement(ctx context.Context, tx gdb.TX, ids map[string]int64, el seed return nil } res, err := tx.Model(consts.TableElement).Ctx(ctx).Data(g.Map{ - "e_type": el.EType, "name": el.Name, "image": el.Image, "audio": el.Audio, - "description": el.Description, "status": consts.StatusEnabled, + "e_type": el.EType, "name": el.Name, "name_pinyin": common.AnnotatePinyin(el.Name), + "image": el.Image, "audio": el.Audio, + "description": el.Description, "description_pinyin": common.AnnotatePinyin(el.Description), + "status": consts.StatusEnabled, }).Insert() if err != nil { return err @@ -235,8 +240,11 @@ func insertStrategy(ctx context.Context, tx gdb.TX, elementIds map[string]int64, unlockBefore := gconv.Int64(s.UnlockBefore) data := g.Map{ "name": s.Name, "pinyin": s.Pinyin, "group_no": s.GroupNo, "group_name": s.GroupName, - "meaning": s.Meaning, "teach_content": s.TeachContent, "teach_image": s.TeachImage, - "teach_audio": s.TeachAudio, "summary_q": s.SummaryQ, "summary_options": s.SummaryOptions, + "meaning": s.Meaning, "meaning_pinyin": common.AnnotatePinyin(s.Meaning), + "teach_content": s.TeachContent, "teach_content_pinyin": common.AnnotatePinyin(s.TeachContent), + "teach_image": s.TeachImage, + "teach_audio": s.TeachAudio, "summary_q": s.SummaryQ, "summary_q_pinyin": common.AnnotatePinyin(s.SummaryQ), + "summary_options": s.SummaryOptions, "summary_options_pinyin": common.AnnotatePinyin(s.SummaryOptions), "summary_audio": s.SummaryAudio, "icon": s.Icon, "sort_order": s.SortOrder, "status": consts.StatusEnabled, } @@ -279,7 +287,8 @@ func insertLevel(ctx context.Context, tx gdb.TX, elementIds map[string]int64, st } res, err := tx.Model(consts.TableLevel).Ctx(ctx).Data(g.Map{ "strategy_id": strategyId, "title": lv.Title, "scene_id": sceneId, - "scene_content": lv.SceneContent, "scene_image": lv.SceneImage, "scene_audio": lv.SceneAudio, + "scene_content": lv.SceneContent, "scene_content_pinyin": common.AnnotatePinyin(lv.SceneContent), + "scene_image": lv.SceneImage, "scene_audio": lv.SceneAudio, "age_group": ageGroup, "content_version": 1, "sort_order": sortOrder, "status": consts.StatusEnabled, }).Insert() @@ -334,8 +343,10 @@ func insertLevel(ctx context.Context, tx gdb.TX, elementIds map[string]int64, st nextNodeId = nodeIds[opt.NextIndex] } if _, err := tx.Model(consts.TableNodeOption).Ctx(ctx).Data(g.Map{ - "node_id": nodeIds[i], "text": opt.Text, "prop_id": propId, + "node_id": nodeIds[i], "text": opt.Text, "text_pinyin": common.AnnotatePinyin(opt.Text), + "prop_id": propId, "audio": opt.Audio, "next_node_id": nextNodeId, "feedback": opt.Feedback, + "feedback_pinyin": common.AnnotatePinyin(opt.Feedback), "feedback_audio": opt.FeedbackAudio, "sort_order": oi + 1, "status": consts.StatusEnabled, }).Insert(); err != nil {