Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ALTER TABLE connections ADD COLUMN sort_order INTEGER NOT NULL DEFAULT 0;
1 change: 1 addition & 0 deletions crates/core/src/cloud_sync/conflict.rs
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,7 @@ mod tests {
cloud_id: Some("cloud-123".to_string()),
last_synced_at: Some(100),
last_used_at: None,
sort_order: None,
created_at: None,
updated_at: Some(200),
team_id: None,
Expand Down
1 change: 1 addition & 0 deletions crates/core/src/cloud_sync/connection_sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1130,6 +1130,7 @@ mod tests {
cloud_id: Some("cloud-1".to_string()),
last_synced_at: Some(updated_at - 10),
last_used_at: None,
sort_order: None,
created_at: Some(updated_at - 20),
updated_at: Some(updated_at),
team_id: None,
Expand Down
2 changes: 2 additions & 0 deletions crates/core/src/cloud_sync/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,7 @@ impl CloudSyncService {
cloud_id: Some(cloud_data.id.clone()),
last_synced_at: Some(cloud_data.updated_at),
last_used_at: None,
sort_order: None,
created_at: None,
updated_at: None,
team_id: cloud_data.team_id.clone(),
Expand Down Expand Up @@ -592,6 +593,7 @@ mod tests {
cloud_id: None,
last_synced_at: None,
last_used_at: None,
sort_order: None,
created_at: None,
updated_at: None,
team_id: None,
Expand Down
4 changes: 4 additions & 0 deletions crates/core/src/storage/migration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ const MIGRATIONS: &[(&str, &str)] = &[
"20260618000001",
include_str!("../../migrations/20260618000001_connection_last_used.sql"),
),
(
"20260623000001",
include_str!("../../migrations/20260623000001_connection_sort_order.sql"),
),
];

pub fn run_migrations(conn: &Connection) -> Result<()> {
Expand Down
12 changes: 11 additions & 1 deletion crates/core/src/storage/models.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,8 @@ impl ConnectionType {
pub fn all() -> Vec<ConnectionType> {
vec![
ConnectionType::All,
ConnectionType::Database,
ConnectionType::SshSftp,
ConnectionType::Database,
ConnectionType::Redis,
ConnectionType::MongoDB,
ConnectionType::ChatDB,
Expand Down Expand Up @@ -804,6 +804,9 @@ pub struct StoredConnection {
/// 最近使用时间戳,仅用于本地列表排序,不参与云同步。
#[serde(skip_serializing_if = "Option::is_none")]
pub last_used_at: Option<i64>,
/// 手动排序位序,仅用于本地列表排序,不参与云同步。
#[serde(skip_serializing_if = "Option::is_none")]
pub sort_order: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub created_at: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
Expand Down Expand Up @@ -896,6 +899,7 @@ impl StoredConnection {
cloud_id: None,
last_synced_at: None,
last_used_at: None,
sort_order: None,
created_at: None,
updated_at: None,
team_id: None,
Expand All @@ -916,6 +920,7 @@ impl StoredConnection {
cloud_id: None,
last_synced_at: None,
last_used_at: None,
sort_order: None,
created_at: None,
updated_at: None,
team_id: None,
Expand All @@ -940,6 +945,7 @@ impl StoredConnection {
cloud_id: None,
last_synced_at: None,
last_used_at: None,
sort_order: None,
created_at: None,
updated_at: None,
team_id: None,
Expand All @@ -960,6 +966,7 @@ impl StoredConnection {
cloud_id: None,
last_synced_at: None,
last_used_at: None,
sort_order: None,
created_at: None,
updated_at: None,
team_id: None,
Expand All @@ -980,6 +987,7 @@ impl StoredConnection {
cloud_id: None,
last_synced_at: None,
last_used_at: None,
sort_order: None,
created_at: None,
updated_at: None,
team_id: None,
Expand Down Expand Up @@ -1016,6 +1024,7 @@ impl StoredConnection {
cloud_id: None,
last_synced_at: None,
last_used_at: None,
sort_order: None,
created_at: None,
updated_at: None,
team_id: None,
Expand All @@ -1040,6 +1049,7 @@ impl StoredConnection {
cloud_id: None,
last_synced_at: None,
last_used_at: None,
sort_order: None,
created_at: None,
updated_at: None,
team_id: None,
Expand Down
32 changes: 24 additions & 8 deletions crates/core/src/storage/repository.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ struct ConnectionRow {
cloud_id: Option<String>,
last_synced_at: Option<i64>,
last_used_at: Option<i64>,
sort_order: Option<i32>,
created_at: i64,
updated_at: i64,
team_id: Option<String>,
Expand All @@ -46,6 +47,7 @@ impl FromSqliteRow for ConnectionRow {
cloud_id: row.get("cloud_id")?,
last_synced_at: row.get("last_synced_at")?,
last_used_at: row.get("last_used_at")?,
sort_order: row.get("sort_order").unwrap_or(Some(0)),
created_at: row.get("created_at")?,
updated_at: row.get("updated_at")?,
team_id: row.get("team_id").unwrap_or(None),
Expand All @@ -68,6 +70,7 @@ impl From<ConnectionRow> for StoredConnection {
cloud_id: row.cloud_id,
last_synced_at: row.last_synced_at,
last_used_at: row.last_used_at,
sort_order: row.sort_order,
created_at: Some(row.created_at),
updated_at: Some(row.updated_at),
team_id: row.team_id,
Expand Down Expand Up @@ -201,7 +204,7 @@ impl Repository for ConnectionRepository {
fn get(&self, id: i64) -> Result<Option<Self::Entity>> {
self.conn.with_connection(|conn| {
let mut stmt = conn.prepare(
"SELECT id, name, connection_type, params, workspace_id, selected_databases, remark, sync_enabled, cloud_id, last_synced_at, last_used_at, created_at, updated_at, team_id, owner_id FROM connections WHERE id = ?1",
"SELECT id, name, connection_type, params, workspace_id, selected_databases, remark, sync_enabled, cloud_id, last_synced_at, last_used_at, sort_order, created_at, updated_at, team_id, owner_id FROM connections WHERE id = ?1",
)?;
let mut rows = stmt.query(params![id])?;
if let Some(row) = rows.next()? {
Expand All @@ -215,7 +218,7 @@ impl Repository for ConnectionRepository {
fn list(&self) -> Result<Vec<Self::Entity>> {
self.conn.with_connection(|conn| {
let mut stmt = conn.prepare(
"SELECT id, name, connection_type, params, workspace_id, selected_databases, remark, sync_enabled, cloud_id, last_synced_at, last_used_at, created_at, updated_at, team_id, owner_id FROM connections ORDER BY COALESCE(last_used_at, updated_at, created_at) DESC, id DESC",
"SELECT id, name, connection_type, params, workspace_id, selected_databases, remark, sync_enabled, cloud_id, last_synced_at, last_used_at, sort_order, created_at, updated_at, team_id, owner_id FROM connections ORDER BY sort_order ASC, COALESCE(last_used_at, updated_at, created_at) DESC, id DESC",
)?;
let rows = stmt.query_map([], |row| ConnectionRow::from_row(row))?;
let mut results = Vec::new();
Expand Down Expand Up @@ -250,9 +253,9 @@ impl ConnectionRepository {
pub fn list_by_workspace(&self, workspace_id: Option<i64>) -> Result<Vec<StoredConnection>> {
self.conn.with_connection(|conn| {
let sql = if workspace_id.is_some() {
"SELECT id, name, connection_type, params, workspace_id, selected_databases, remark, sync_enabled, cloud_id, last_synced_at, last_used_at, created_at, updated_at, team_id, owner_id FROM connections WHERE workspace_id = ?1 ORDER BY COALESCE(last_used_at, updated_at, created_at) DESC, id DESC"
"SELECT id, name, connection_type, params, workspace_id, selected_databases, remark, sync_enabled, cloud_id, last_synced_at, last_used_at, sort_order, created_at, updated_at, team_id, owner_id FROM connections WHERE workspace_id = ?1 ORDER BY sort_order ASC, COALESCE(last_used_at, updated_at, created_at) DESC, id DESC"
} else {
"SELECT id, name, connection_type, params, workspace_id, selected_databases, remark, sync_enabled, cloud_id, last_synced_at, last_used_at, created_at, updated_at, team_id, owner_id FROM connections WHERE workspace_id IS NULL ORDER BY COALESCE(last_used_at, updated_at, created_at) DESC, id DESC"
"SELECT id, name, connection_type, params, workspace_id, selected_databases, remark, sync_enabled, cloud_id, last_synced_at, last_used_at, sort_order, created_at, updated_at, team_id, owner_id FROM connections WHERE workspace_id IS NULL ORDER BY sort_order ASC, COALESCE(last_used_at, updated_at, created_at) DESC, id DESC"
};
let mut stmt = conn.prepare(sql)?;

Expand Down Expand Up @@ -318,11 +321,24 @@ impl ConnectionRepository {
})
}

/// 批量更新连接的 sort_order(拖拽排序后持久化)
pub fn update_sort_orders(&self, orders: &[(i64, i32)]) -> Result<()> {
self.conn.with_connection(|conn| {
for (id, sort_order) in orders {
conn.execute(
"UPDATE connections SET sort_order = ?1 WHERE id = ?2",
params![sort_order, id],
)?;
}
Ok(())
})
}

/// 查询需要同步的连接(sync_enabled=true 且 cloud_id 为空或 updated_at > last_synced_at)
pub fn list_pending_sync(&self) -> Result<Vec<StoredConnection>> {
self.conn.with_connection(|conn| {
let mut stmt = conn.prepare(
"SELECT id, name, connection_type, params, workspace_id, selected_databases, remark, sync_enabled, cloud_id, last_synced_at, last_used_at, created_at, updated_at, team_id, owner_id
"SELECT id, name, connection_type, params, workspace_id, selected_databases, remark, sync_enabled, cloud_id, last_synced_at, last_used_at, sort_order, created_at, updated_at, team_id, owner_id
FROM connections
WHERE sync_enabled = 1 AND (cloud_id IS NULL OR updated_at > COALESCE(last_synced_at, 0))
ORDER BY updated_at DESC",
Expand All @@ -340,7 +356,7 @@ impl ConnectionRepository {
pub fn get_by_cloud_id(&self, cloud_id: &str) -> Result<Option<StoredConnection>> {
self.conn.with_connection(|conn| {
let mut stmt = conn.prepare(
"SELECT id, name, connection_type, params, workspace_id, selected_databases, remark, sync_enabled, cloud_id, last_synced_at, last_used_at, created_at, updated_at, team_id, owner_id
"SELECT id, name, connection_type, params, workspace_id, selected_databases, remark, sync_enabled, cloud_id, last_synced_at, last_used_at, sort_order, created_at, updated_at, team_id, owner_id
FROM connections WHERE cloud_id = ?1",
)?;
let mut rows = stmt.query(params![cloud_id])?;
Expand Down Expand Up @@ -382,7 +398,7 @@ impl ConnectionRepository {
pub fn list_by_team(&self, team_id: &str) -> Result<Vec<StoredConnection>> {
self.conn.with_connection(|conn| {
let mut stmt = conn.prepare(
"SELECT id, name, connection_type, params, workspace_id, selected_databases, remark, sync_enabled, cloud_id, last_synced_at, last_used_at, created_at, updated_at, team_id, owner_id FROM connections WHERE team_id = ?1 ORDER BY COALESCE(last_used_at, updated_at, created_at) DESC, id DESC",
"SELECT id, name, connection_type, params, workspace_id, selected_databases, remark, sync_enabled, cloud_id, last_synced_at, last_used_at, sort_order, created_at, updated_at, team_id, owner_id FROM connections WHERE team_id = ?1 ORDER BY sort_order ASC, COALESCE(last_used_at, updated_at, created_at) DESC, id DESC",
)?;
let rows = stmt.query_map(params![team_id], |row| ConnectionRow::from_row(row))?;
let mut results = Vec::new();
Expand All @@ -397,7 +413,7 @@ impl ConnectionRepository {
pub fn list_personal(&self) -> Result<Vec<StoredConnection>> {
self.conn.with_connection(|conn| {
let mut stmt = conn.prepare(
"SELECT id, name, connection_type, params, workspace_id, selected_databases, remark, sync_enabled, cloud_id, last_synced_at, last_used_at, created_at, updated_at, team_id, owner_id FROM connections WHERE team_id IS NULL ORDER BY COALESCE(last_used_at, updated_at, created_at) DESC, id DESC",
"SELECT id, name, connection_type, params, workspace_id, selected_databases, remark, sync_enabled, cloud_id, last_synced_at, last_used_at, sort_order, created_at, updated_at, team_id, owner_id FROM connections WHERE team_id IS NULL ORDER BY sort_order ASC, COALESCE(last_used_at, updated_at, created_at) DESC, id DESC",
)?;
let rows = stmt.query_map([], |row| ConnectionRow::from_row(row))?;
let mut results = Vec::new();
Expand Down
1 change: 1 addition & 0 deletions crates/core/src/storage/sftp_favorite_path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,7 @@ mod tests {
cloud_id: None,
last_synced_at: None,
last_used_at: None,
sort_order: None,
created_at: None,
updated_at: None,
team_id: None,
Expand Down
8 changes: 8 additions & 0 deletions main/locales/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,14 @@ Home:
en: Import
zh-CN: 导入
zh-HK: 導入
card_view:
en: Card View
zh-CN: 卡片视图
zh-HK: 卡片視圖
list_view:
en: List View
zh-CN: 列表视图
zh-HK: 列表視圖
refresh:
en: Refresh
zh-CN: 刷新
Expand Down
Loading
Loading