feat: 格式从分组下沉到条目(v21)
- entry 新增 format(apps/posters/articles),老数据按根分组 view_mode 回填;seed 按分区写入 - 分组管理移除格式字段/显示,根分组只作容器 - 内容弹窗新增逐条格式选择,列表增加格式列;ItemEditor 保存时保留原格式 - 前台按 entry.format 渲染:卡片/分组页支持同组混合格式,详情按条目格式选模板 - 迁移后 live 20 应用 / 13 海报;cargo test 59 passed;Playwright 验证混合展示
This commit is contained in:
+30
-5
@@ -66,6 +66,7 @@ CREATE TABLE IF NOT EXISTS entry (
|
||||
node_key TEXT NOT NULL REFERENCES node(key) ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
-- 直接所属容器:应用是分组,海报/图文是分区本身
|
||||
-- 所属分区不单独存:由 node_key 推导(分组看它的 parent_key)
|
||||
format TEXT NOT NULL DEFAULT 'apps', -- 条目自身的展示格式:apps / posters / articles
|
||||
name TEXT NOT NULL, -- 名称:网站名 / 电影名 / 文章标题
|
||||
description TEXT, -- 一句话简介,列表卡片的副标题
|
||||
icon TEXT, -- 字符图标(封面缺失时的占位)
|
||||
@@ -217,6 +218,23 @@ const V20_SQL: &str = r#"
|
||||
ALTER TABLE node ADD COLUMN enabled INTEGER NOT NULL DEFAULT 1;
|
||||
"#;
|
||||
|
||||
/// v20 → v21:格式从分组下沉到条目;老数据按所属根分组的 view_mode 回填。
|
||||
const V21_SQL: &str = r#"
|
||||
ALTER TABLE entry ADD COLUMN format TEXT NOT NULL DEFAULT 'apps';
|
||||
|
||||
WITH RECURSIVE roots(key, root_key, view_mode) AS (
|
||||
SELECT key, key, view_mode FROM node WHERE parent_key IS NULL
|
||||
UNION ALL
|
||||
SELECT n.key, r.root_key, r.view_mode
|
||||
FROM node n JOIN roots r ON n.parent_key = r.key
|
||||
)
|
||||
UPDATE entry
|
||||
SET format = COALESCE(
|
||||
(SELECT view_mode FROM roots WHERE roots.key = entry.node_key),
|
||||
'apps'
|
||||
);
|
||||
"#;
|
||||
|
||||
/// v18 → v19:首页卡片改为「卡片 + 勾选分组」。
|
||||
const V19_SQL: &str = r#"
|
||||
CREATE TABLE IF NOT EXISTS card (
|
||||
@@ -276,7 +294,7 @@ pub struct SeedReport {
|
||||
///
|
||||
/// 从 v16 起有了第一套迁移:`migrate` 会把老库逐级升上来,
|
||||
/// 只有「比程序更新」或「没有迁移路径」的版本才拒绝启动。
|
||||
pub const SCHEMA_VERSION: i64 = 20;
|
||||
pub const SCHEMA_VERSION: i64 = 21;
|
||||
|
||||
fn current_version(conn: &Connection) -> Result<i64, StashError> {
|
||||
conn.pragma_query_value(None, "user_version", |row| row.get(0))
|
||||
@@ -336,6 +354,11 @@ pub fn migrate(conn: &Connection) -> Result<i64, StashError> {
|
||||
version = 20;
|
||||
}
|
||||
|
||||
if version == 20 {
|
||||
conn.execute_batch(V21_SQL).map_err(map_error)?;
|
||||
version = 21;
|
||||
}
|
||||
|
||||
conn.pragma_update(None, "user_version", version)
|
||||
.map_err(map_error)?;
|
||||
|
||||
@@ -415,13 +438,13 @@ pub fn seed(conn: &mut Connection) -> Result<SeedReport, StashError> {
|
||||
report.groups += 1;
|
||||
|
||||
for (index, entry) in group.entries.iter().enumerate() {
|
||||
insert_entry(&tx, &group.key, index, entry, &mut report)?;
|
||||
insert_entry(&tx, &group.key, §ion.view, index, entry, &mut report)?;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 海报与图文没有分组,直接挂在分区上(node_key 就是分区自己)
|
||||
for (index, entry) in section.entries.iter().enumerate() {
|
||||
insert_entry(&tx, §ion.key, index, entry, &mut report)?;
|
||||
insert_entry(&tx, §ion.key, §ion.view, index, entry, &mut report)?;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -459,18 +482,20 @@ pub fn seed(conn: &mut Connection) -> Result<SeedReport, StashError> {
|
||||
fn insert_entry(
|
||||
tx: &rusqlite::Transaction<'_>,
|
||||
node_key: &str,
|
||||
format: &str,
|
||||
index: usize,
|
||||
entry: &SeedEntry,
|
||||
report: &mut SeedReport,
|
||||
) -> Result<(), StashError> {
|
||||
tx.execute(
|
||||
"INSERT INTO entry (
|
||||
key, node_key, name, description, icon, href, cover,
|
||||
key, node_key, format, name, description, icon, href, cover,
|
||||
banner, badge, comment, summary, body, hot, views, likes, sort
|
||||
) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14, ?15, ?16)",
|
||||
) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14, ?15, ?16, ?17)",
|
||||
params![
|
||||
entry.key,
|
||||
node_key,
|
||||
format,
|
||||
entry.name,
|
||||
entry.description,
|
||||
entry.icon,
|
||||
|
||||
Reference in New Issue
Block a user