feat: 搜索框下滚动、本地服务卡片排序、拖拽末位修复
- 恢复内容区内部滚动:页头/搜索框固定,滚动区域从搜索框下方开始;侧栏跟随内容滚动,侧栏滚轮驱动内容区 - v22:本地服务以 card 行 local-service 参与排序;首页按卡片顺序渲染,后台可拖动排序 - 本地服务卡片后端禁止删除/改名/配置分组 - 修复向下拖动时插到目标之后,倒数第二项可拖到最后 - 验证:搜索框位置固定、侧栏 scrollTop 跟随、本地服务与倒数第二拖末位均落库、首页顺序一致
This commit is contained in:
+31
-5
@@ -117,16 +117,23 @@ pub fn create(conn: &mut Connection, new: NewCard) -> Result<i64, StashError> {
|
||||
}
|
||||
|
||||
pub fn update(conn: &mut Connection, id: i64, patch: UpdateCard) -> Result<(), StashError> {
|
||||
let current: Option<(String, i64)> = conn
|
||||
.query_row("SELECT title, sort FROM card WHERE id = ?1", [id], |row| {
|
||||
Ok((row.get(0)?, row.get(1)?))
|
||||
})
|
||||
let current: Option<(String, String, i64)> = conn
|
||||
.query_row(
|
||||
"SELECT key, title, sort FROM card WHERE id = ?1",
|
||||
[id],
|
||||
|row| Ok((row.get(0)?, row.get(1)?, row.get(2)?)),
|
||||
)
|
||||
.optional()
|
||||
.map_err(map_error)?;
|
||||
|
||||
let Some((current_title, current_sort)) = current else {
|
||||
let Some((current_key, current_title, current_sort)) = current else {
|
||||
return Err(StashError::NotFound(format!("卡片不存在: {id}")));
|
||||
};
|
||||
if current_key == "local-service" && patch.title.is_some() {
|
||||
return Err(StashError::InvalidDirectory(
|
||||
"本地服务卡片由系统生成,不能改名".into(),
|
||||
));
|
||||
}
|
||||
|
||||
let title = match patch.title {
|
||||
Some(title) => {
|
||||
@@ -152,6 +159,15 @@ pub fn update(conn: &mut Connection, id: i64, patch: UpdateCard) -> Result<(), S
|
||||
}
|
||||
|
||||
pub fn remove(conn: &Connection, id: i64) -> Result<(), StashError> {
|
||||
let key: Option<String> = conn
|
||||
.query_row("SELECT key FROM card WHERE id = ?1", [id], |row| row.get(0))
|
||||
.optional()
|
||||
.map_err(map_error)?;
|
||||
if key.as_deref() == Some("local-service") {
|
||||
return Err(StashError::InvalidDirectory(
|
||||
"本地服务卡片由系统生成,不能删除".into(),
|
||||
));
|
||||
}
|
||||
let removed = conn
|
||||
.execute("DELETE FROM card WHERE id = ?1", [id])
|
||||
.map_err(map_error)?;
|
||||
@@ -168,6 +184,16 @@ pub fn set_groups(
|
||||
id: i64,
|
||||
groups: Vec<CardGroupInput>,
|
||||
) -> Result<(), StashError> {
|
||||
let key: Option<String> = conn
|
||||
.query_row("SELECT key FROM card WHERE id = ?1", [id], |row| row.get(0))
|
||||
.optional()
|
||||
.map_err(map_error)?;
|
||||
if key.as_deref() == Some("local-service") {
|
||||
return Err(StashError::InvalidDirectory(
|
||||
"本地服务卡片由系统生成,不能配置分组".into(),
|
||||
));
|
||||
}
|
||||
|
||||
let exists: i64 = conn
|
||||
.query_row("SELECT COUNT(*) FROM card WHERE id = ?1", [id], |row| row.get(0))
|
||||
.map_err(map_error)?;
|
||||
|
||||
+14
-1
@@ -182,6 +182,9 @@ FROM section_block b
|
||||
JOIN node n ON n.key = b.node_key
|
||||
LEFT JOIN node p ON p.key = n.parent_key
|
||||
JOIN card c ON c.key = 'card-' || COALESCE(p.key, n.key);
|
||||
|
||||
-- 本地服务是运行时卡片,但用一行 card 记录它的位置,参与首页排序
|
||||
INSERT OR IGNORE INTO card (key, title, sort) VALUES ('local-service', '本地服务', -1);
|
||||
"#;
|
||||
|
||||
/// v16 → v17:条目加 `updated_at`(乐观锁),新增审计表。
|
||||
@@ -218,6 +221,11 @@ const V20_SQL: &str = r#"
|
||||
ALTER TABLE node ADD COLUMN enabled INTEGER NOT NULL DEFAULT 1;
|
||||
"#;
|
||||
|
||||
/// v21 → v22:本地服务卡片入库,用 card.sort 参与首页排序(内容仍来自运行时项目)。
|
||||
const V22_SQL: &str = r#"
|
||||
INSERT OR IGNORE INTO card (key, title, sort) VALUES ('local-service', '本地服务', -1);
|
||||
"#;
|
||||
|
||||
/// v20 → v21:格式从分组下沉到条目;老数据按所属根分组的 view_mode 回填。
|
||||
const V21_SQL: &str = r#"
|
||||
ALTER TABLE entry ADD COLUMN format TEXT NOT NULL DEFAULT 'apps';
|
||||
@@ -294,7 +302,7 @@ pub struct SeedReport {
|
||||
///
|
||||
/// 从 v16 起有了第一套迁移:`migrate` 会把老库逐级升上来,
|
||||
/// 只有「比程序更新」或「没有迁移路径」的版本才拒绝启动。
|
||||
pub const SCHEMA_VERSION: i64 = 21;
|
||||
pub const SCHEMA_VERSION: i64 = 22;
|
||||
|
||||
fn current_version(conn: &Connection) -> Result<i64, StashError> {
|
||||
conn.pragma_query_value(None, "user_version", |row| row.get(0))
|
||||
@@ -359,6 +367,11 @@ pub fn migrate(conn: &Connection) -> Result<i64, StashError> {
|
||||
version = 21;
|
||||
}
|
||||
|
||||
if version == 21 {
|
||||
conn.execute_batch(V22_SQL).map_err(map_error)?;
|
||||
version = 22;
|
||||
}
|
||||
|
||||
conn.pragma_update(None, "user_version", version)
|
||||
.map_err(map_error)?;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user