From 568ffde0ceaf7f06a51b92c40936a8526723fcbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E6=96=8C?= <259278618@qq.com> Date: Thu, 13 Aug 2026 13:46:11 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=86=85=E5=AE=B9=E8=A1=A8=20*=5Fpinyi?= =?UTF-8?q?n=20=E5=88=97=E8=BF=81=E7=A7=BB=EF=BC=88=E5=B9=82=E7=AD=89=20En?= =?UTF-8?q?sureColumn=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.7 --- biz/dao/dao_element.go | 4 ++++ biz/dao/dao_level.go | 2 ++ biz/dao/dao_node_option.go | 8 ++++++++ biz/dao/dao_scene_node.go | 2 ++ biz/dao/dao_strategy.go | 16 ++++++++++++---- common/migrate.go | 28 ++++++++++++++++++++++++++++ 6 files changed, 56 insertions(+), 4 deletions(-) create mode 100644 common/migrate.go diff --git a/biz/dao/dao_element.go b/biz/dao/dao_element.go index dad67d3..fab0bec 100644 --- a/biz/dao/dao_element.go +++ b/biz/dao/dao_element.go @@ -19,12 +19,16 @@ CREATE TABLE IF NOT EXISTS element ( id INTEGER PRIMARY KEY AUTOINCREMENT, e_type INTEGER NOT NULL, name TEXT NOT NULL, + name_pinyin TEXT, image TEXT, audio TEXT, description TEXT, + description_pinyin TEXT, status INTEGER NOT NULL DEFAULT 1, sort_order INTEGER NOT NULL DEFAULT 1 ); CREATE INDEX IF NOT EXISTS idx_element_type ON element(e_type);`) + common.EnsureColumn(ctx, consts.TableElement, "name_pinyin", "TEXT") + common.EnsureColumn(ctx, consts.TableElement, "description_pinyin", "TEXT") return err } diff --git a/biz/dao/dao_level.go b/biz/dao/dao_level.go index 41ba415..52b40b8 100644 --- a/biz/dao/dao_level.go +++ b/biz/dao/dao_level.go @@ -21,6 +21,7 @@ CREATE TABLE IF NOT EXISTS level ( title TEXT NOT NULL, scene_id INTEGER, scene_content TEXT NOT NULL, + scene_content_pinyin TEXT, scene_image TEXT, scene_audio TEXT, age_group TEXT NOT NULL DEFAULT '4-6', @@ -29,5 +30,6 @@ CREATE TABLE IF NOT EXISTS level ( status INTEGER NOT NULL DEFAULT 1 ); CREATE INDEX IF NOT EXISTS idx_level_strategy ON level(strategy_id, sort_order);`) + common.EnsureColumn(ctx, consts.TableLevel, "scene_content_pinyin", "TEXT") return err } diff --git a/biz/dao/dao_node_option.go b/biz/dao/dao_node_option.go index 7f6e157..0109695 100644 --- a/biz/dao/dao_node_option.go +++ b/biz/dao/dao_node_option.go @@ -19,14 +19,22 @@ CREATE TABLE IF NOT EXISTS node_option ( id INTEGER PRIMARY KEY AUTOINCREMENT, node_id INTEGER NOT NULL, text TEXT NOT NULL, + text_pinyin TEXT, prop_id INTEGER, audio TEXT, next_node_id INTEGER, feedback TEXT NOT NULL, + feedback_pinyin TEXT, + feedback_pros TEXT, -- 对比点评:好处 + feedback_cons TEXT, -- 对比点评:不足/错过的更好选择 feedback_audio TEXT, sort_order INTEGER NOT NULL DEFAULT 1, status INTEGER NOT NULL DEFAULT 1 ); CREATE INDEX IF NOT EXISTS idx_option_node ON node_option(node_id);`) + common.EnsureColumn(ctx, consts.TableNodeOption, "text_pinyin", "TEXT") + common.EnsureColumn(ctx, consts.TableNodeOption, "feedback_pinyin", "TEXT") + common.EnsureColumn(ctx, consts.TableNodeOption, "feedback_pros", "TEXT") + common.EnsureColumn(ctx, consts.TableNodeOption, "feedback_cons", "TEXT") return err } diff --git a/biz/dao/dao_scene_node.go b/biz/dao/dao_scene_node.go index 495aafb..2228fcc 100644 --- a/biz/dao/dao_scene_node.go +++ b/biz/dao/dao_scene_node.go @@ -21,6 +21,7 @@ CREATE TABLE IF NOT EXISTS scene_node ( title TEXT, character_id INTEGER, content TEXT NOT NULL, + content_pinyin TEXT, image TEXT, audio TEXT, node_type INTEGER NOT NULL DEFAULT 1, @@ -32,5 +33,6 @@ CREATE TABLE IF NOT EXISTS scene_node ( status INTEGER NOT NULL DEFAULT 1 ); CREATE INDEX IF NOT EXISTS idx_node_level ON scene_node(level_id);`) + common.EnsureColumn(ctx, consts.TableSceneNode, "content_pinyin", "TEXT") return err } diff --git a/biz/dao/dao_strategy.go b/biz/dao/dao_strategy.go index 91af543..109c65c 100644 --- a/biz/dao/dao_strategy.go +++ b/biz/dao/dao_strategy.go @@ -21,12 +21,16 @@ CREATE TABLE IF NOT EXISTS strategy ( pinyin TEXT NOT NULL, group_no INTEGER NOT NULL, group_name TEXT NOT NULL, - meaning TEXT NOT NULL, - teach_content TEXT, + meaning TEXT NOT NULL, -- 儿童语言释义 + meaning_pinyin TEXT, -- 释义拼音(逐字对齐 JSON) + teach_content TEXT, -- 计策学堂:儿童化讲解(名称/释义/使用时机) + teach_content_pinyin TEXT, teach_image TEXT, teach_audio TEXT, - summary_q TEXT, - summary_options TEXT, + summary_q TEXT, -- 智慧总结反思题 + summary_q_pinyin TEXT, + summary_options TEXT, -- 反思题选项 JSON(含正确答案) + summary_options_pinyin TEXT, summary_audio TEXT, icon TEXT, sort_order INTEGER NOT NULL, @@ -34,5 +38,9 @@ CREATE TABLE IF NOT EXISTS strategy ( status INTEGER NOT NULL DEFAULT 1 ); CREATE INDEX IF NOT EXISTS idx_strategy_group ON strategy(group_no, sort_order);`) + common.EnsureColumn(ctx, consts.TableStrategy, "meaning_pinyin", "TEXT") + common.EnsureColumn(ctx, consts.TableStrategy, "teach_content_pinyin", "TEXT") + common.EnsureColumn(ctx, consts.TableStrategy, "summary_q_pinyin", "TEXT") + common.EnsureColumn(ctx, consts.TableStrategy, "summary_options_pinyin", "TEXT") return err } diff --git a/common/migrate.go b/common/migrate.go new file mode 100644 index 0000000..82b5bf2 --- /dev/null +++ b/common/migrate.go @@ -0,0 +1,28 @@ +package common + +import ( + "context" + "fmt" + + "github.com/gogf/gf/v2/frame/g" +) + +// EnsureColumn 幂等加列:PRAGMA 查列不存在则 ALTER TABLE ADD COLUMN。 +// 失败只记警告,不阻断启动(列缺失时后续查询只会取到空值)。 +func EnsureColumn(ctx context.Context, table, col, sqlType string) { + cols, err := g.DB().GetAll(ctx, fmt.Sprintf("PRAGMA table_info(%s)", table)) + if err != nil { + g.Log().Warningf(ctx, "migrate: %s 表结构读取失败: %v", table, err) + return + } + for _, c := range cols { + if c["name"].String() == col { + return + } + } + if _, err := g.DB().Exec(ctx, fmt.Sprintf("ALTER TABLE %s ADD COLUMN %s %s", table, col, sqlType)); err != nil { + g.Log().Warningf(ctx, "migrate: %s.%s 加列失败: %v", table, col, err) + return + } + g.Log().Infof(ctx, "migrate: %s.%s 已添加", table, col) +}