Skip to content

Commit 4af6157

Browse files
committed
feat: 支持移动端底部导航自定义与更多收纳
1 parent 914eefa commit 4af6157

11 files changed

Lines changed: 670 additions & 182 deletions

File tree

scripts/tauri-dev.cjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ async function main() {
3434
const port = await findAvailablePort(START_PORT)
3535
const overrideConfig = {
3636
build: {
37-
beforeDevCommand: `npm run dev -- --host --port ${port} --strictPort`,
37+
beforeDevCommand: `npm run dev -- --host --port ${port}`,
3838
devUrl: `http://localhost:${port}`,
3939
},
4040
}

src-tauri/src/commands/database.rs

Lines changed: 193 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -828,139 +828,227 @@ async fn db_sync_apply_internal(
828828
};
829829

830830
let local_students = load_students(&local_conn).await?;
831+
let remote_students = load_students(&remote_conn).await?;
831832
let local_reasons = load_reasons(&local_conn).await?;
833+
let remote_reasons = load_reasons(&remote_conn).await?;
832834
let local_tags = load_tags(&local_conn).await?;
835+
let remote_tags = load_tags(&remote_conn).await?;
833836
let local_events = load_events(&local_conn).await?;
837+
let remote_events = load_events(&remote_conn).await?;
834838
let local_reward_settings = load_reward_settings(&local_conn).await?;
839+
let remote_reward_settings = load_reward_settings(&remote_conn).await?;
835840
let local_reward_redemptions = load_reward_redemptions(&local_conn).await?;
841+
let remote_reward_redemptions = load_reward_redemptions(&remote_conn).await?;
836842
let local_pairs = load_student_tag_pairs(&local_conn).await?;
837843
let remote_pairs = load_student_tag_pairs(&remote_conn).await?;
838844

839-
let (preferred, target) = if strategy == ConflictStrategy::KeepLocal {
840-
(&local_conn, &remote_conn)
841-
} else {
842-
(&remote_conn, &local_conn)
843-
};
844-
845845
let mut synced_records = 0usize;
846846
let mut resolved_conflicts = 0usize;
847847

848-
for student in local_students.values() {
849-
if upsert_student(&remote_conn, student).await? {
850-
synced_records += 1;
851-
}
852-
}
853-
let remote_students_after = load_students(&remote_conn).await?;
854-
for student in remote_students_after.values() {
855-
if upsert_student(&local_conn, student).await? {
856-
synced_records += 1;
857-
}
858-
}
859-
for reason in local_reasons.values() {
860-
if upsert_reason(&remote_conn, reason).await? {
861-
synced_records += 1;
862-
}
863-
}
864-
let remote_reasons_after = load_reasons(&remote_conn).await?;
865-
for reason in remote_reasons_after.values() {
866-
if upsert_reason(&local_conn, reason).await? {
867-
synced_records += 1;
868-
}
869-
}
870-
for tag in local_tags.values() {
871-
if upsert_tag(&remote_conn, tag).await? {
872-
synced_records += 1;
873-
}
874-
}
875-
let remote_tags_after = load_tags(&remote_conn).await?;
876-
for tag in remote_tags_after.values() {
877-
if upsert_tag(&local_conn, tag).await? {
878-
synced_records += 1;
879-
}
880-
}
881-
for event in local_events.values() {
882-
if upsert_event(&remote_conn, event).await? {
883-
synced_records += 1;
848+
// Deterministic per-key merge:
849+
// 1) local_only => remote
850+
// 2) remote_only => local
851+
// 3) conflict => resolve by strategy (winner -> loser)
852+
let student_keys: std::collections::HashSet<String> = local_students
853+
.keys()
854+
.chain(remote_students.keys())
855+
.cloned()
856+
.collect();
857+
for key in student_keys {
858+
match (local_students.get(&key), remote_students.get(&key)) {
859+
(Some(local), Some(remote)) if local != remote => {
860+
let changed = if strategy == ConflictStrategy::KeepLocal {
861+
upsert_student(&remote_conn, local).await?
862+
} else {
863+
upsert_student(&local_conn, remote).await?
864+
};
865+
if changed {
866+
resolved_conflicts += 1;
867+
}
868+
}
869+
(Some(local), None) => {
870+
if upsert_student(&remote_conn, local).await? {
871+
synced_records += 1;
872+
}
873+
}
874+
(None, Some(remote)) => {
875+
if upsert_student(&local_conn, remote).await? {
876+
synced_records += 1;
877+
}
878+
}
879+
_ => {}
884880
}
885881
}
886-
let remote_events_after = load_events(&remote_conn).await?;
887-
for event in remote_events_after.values() {
888-
if upsert_event(&local_conn, event).await? {
889-
synced_records += 1;
882+
883+
let reason_keys: std::collections::HashSet<String> = local_reasons
884+
.keys()
885+
.chain(remote_reasons.keys())
886+
.cloned()
887+
.collect();
888+
for key in reason_keys {
889+
match (local_reasons.get(&key), remote_reasons.get(&key)) {
890+
(Some(local), Some(remote)) if local != remote => {
891+
let changed = if strategy == ConflictStrategy::KeepLocal {
892+
upsert_reason(&remote_conn, local).await?
893+
} else {
894+
upsert_reason(&local_conn, remote).await?
895+
};
896+
if changed {
897+
resolved_conflicts += 1;
898+
}
899+
}
900+
(Some(local), None) => {
901+
if upsert_reason(&remote_conn, local).await? {
902+
synced_records += 1;
903+
}
904+
}
905+
(None, Some(remote)) => {
906+
if upsert_reason(&local_conn, remote).await? {
907+
synced_records += 1;
908+
}
909+
}
910+
_ => {}
890911
}
891912
}
892-
for reward in local_reward_settings.values() {
893-
if upsert_reward_setting(&remote_conn, reward).await? {
894-
synced_records += 1;
913+
914+
let tag_keys: std::collections::HashSet<String> = local_tags
915+
.keys()
916+
.chain(remote_tags.keys())
917+
.cloned()
918+
.collect();
919+
for key in tag_keys {
920+
match (local_tags.get(&key), remote_tags.get(&key)) {
921+
(Some(local), Some(remote)) if local != remote => {
922+
let changed = if strategy == ConflictStrategy::KeepLocal {
923+
upsert_tag(&remote_conn, local).await?
924+
} else {
925+
upsert_tag(&local_conn, remote).await?
926+
};
927+
if changed {
928+
resolved_conflicts += 1;
929+
}
930+
}
931+
(Some(local), None) => {
932+
if upsert_tag(&remote_conn, local).await? {
933+
synced_records += 1;
934+
}
935+
}
936+
(None, Some(remote)) => {
937+
if upsert_tag(&local_conn, remote).await? {
938+
synced_records += 1;
939+
}
940+
}
941+
_ => {}
895942
}
896943
}
897-
let remote_reward_settings_after = load_reward_settings(&remote_conn).await?;
898-
for reward in remote_reward_settings_after.values() {
899-
if upsert_reward_setting(&local_conn, reward).await? {
900-
synced_records += 1;
944+
945+
let event_keys: std::collections::HashSet<String> = local_events
946+
.keys()
947+
.chain(remote_events.keys())
948+
.cloned()
949+
.collect();
950+
for key in event_keys {
951+
match (local_events.get(&key), remote_events.get(&key)) {
952+
(Some(local), Some(remote)) if local != remote => {
953+
let changed = if strategy == ConflictStrategy::KeepLocal {
954+
upsert_event(&remote_conn, local).await?
955+
} else {
956+
upsert_event(&local_conn, remote).await?
957+
};
958+
if changed {
959+
resolved_conflicts += 1;
960+
}
961+
}
962+
(Some(local), None) => {
963+
if upsert_event(&remote_conn, local).await? {
964+
synced_records += 1;
965+
}
966+
}
967+
(None, Some(remote)) => {
968+
if upsert_event(&local_conn, remote).await? {
969+
synced_records += 1;
970+
}
971+
}
972+
_ => {}
901973
}
902974
}
903-
for redemption in local_reward_redemptions.values() {
904-
if upsert_reward_redemption(&remote_conn, redemption).await? {
905-
synced_records += 1;
975+
976+
let reward_setting_keys: std::collections::HashSet<String> = local_reward_settings
977+
.keys()
978+
.chain(remote_reward_settings.keys())
979+
.cloned()
980+
.collect();
981+
for key in reward_setting_keys {
982+
match (
983+
local_reward_settings.get(&key),
984+
remote_reward_settings.get(&key),
985+
) {
986+
(Some(local), Some(remote)) if local != remote => {
987+
let changed = if strategy == ConflictStrategy::KeepLocal {
988+
upsert_reward_setting(&remote_conn, local).await?
989+
} else {
990+
upsert_reward_setting(&local_conn, remote).await?
991+
};
992+
if changed {
993+
resolved_conflicts += 1;
994+
}
995+
}
996+
(Some(local), None) => {
997+
if upsert_reward_setting(&remote_conn, local).await? {
998+
synced_records += 1;
999+
}
1000+
}
1001+
(None, Some(remote)) => {
1002+
if upsert_reward_setting(&local_conn, remote).await? {
1003+
synced_records += 1;
1004+
}
1005+
}
1006+
_ => {}
9061007
}
9071008
}
908-
let remote_reward_redemptions_after = load_reward_redemptions(&remote_conn).await?;
909-
for redemption in remote_reward_redemptions_after.values() {
910-
if upsert_reward_redemption(&local_conn, redemption).await? {
911-
synced_records += 1;
1009+
1010+
let redemption_keys: std::collections::HashSet<String> = local_reward_redemptions
1011+
.keys()
1012+
.chain(remote_reward_redemptions.keys())
1013+
.cloned()
1014+
.collect();
1015+
for key in redemption_keys {
1016+
match (
1017+
local_reward_redemptions.get(&key),
1018+
remote_reward_redemptions.get(&key),
1019+
) {
1020+
(Some(local), Some(remote)) if local != remote => {
1021+
let changed = if strategy == ConflictStrategy::KeepLocal {
1022+
upsert_reward_redemption(&remote_conn, local).await?
1023+
} else {
1024+
upsert_reward_redemption(&local_conn, remote).await?
1025+
};
1026+
if changed {
1027+
resolved_conflicts += 1;
1028+
}
1029+
}
1030+
(Some(local), None) => {
1031+
if upsert_reward_redemption(&remote_conn, local).await? {
1032+
synced_records += 1;
1033+
}
1034+
}
1035+
(None, Some(remote)) => {
1036+
if upsert_reward_redemption(&local_conn, remote).await? {
1037+
synced_records += 1;
1038+
}
1039+
}
1040+
_ => {}
9121041
}
9131042
}
9141043

915-
for pair in local_pairs.union(&remote_pairs) {
916-
if ensure_student_tag_pair(&local_conn, pair).await? {
917-
synced_records += 1;
918-
}
1044+
for pair in local_pairs.difference(&remote_pairs) {
9191045
if ensure_student_tag_pair(&remote_conn, pair).await? {
9201046
synced_records += 1;
9211047
}
9221048
}
923-
924-
let preferred_students = load_students(preferred).await?;
925-
for student in preferred_students.values() {
926-
if upsert_student(target, student).await? {
927-
resolved_conflicts += 1;
928-
}
929-
}
930-
let preferred_reasons = load_reasons(preferred).await?;
931-
for reason in preferred_reasons.values() {
932-
if upsert_reason(target, reason).await? {
933-
resolved_conflicts += 1;
934-
}
935-
}
936-
let preferred_tags = load_tags(preferred).await?;
937-
for tag in preferred_tags.values() {
938-
if upsert_tag(target, tag).await? {
939-
resolved_conflicts += 1;
940-
}
941-
}
942-
let preferred_events = load_events(preferred).await?;
943-
for event in preferred_events.values() {
944-
if upsert_event(target, event).await? {
945-
resolved_conflicts += 1;
946-
}
947-
}
948-
let preferred_reward_settings = load_reward_settings(preferred).await?;
949-
for reward in preferred_reward_settings.values() {
950-
if upsert_reward_setting(target, reward).await? {
951-
resolved_conflicts += 1;
952-
}
953-
}
954-
let preferred_reward_redemptions = load_reward_redemptions(preferred).await?;
955-
for redemption in preferred_reward_redemptions.values() {
956-
if upsert_reward_redemption(target, redemption).await? {
957-
resolved_conflicts += 1;
958-
}
959-
}
960-
let preferred_pairs = load_student_tag_pairs(preferred).await?;
961-
for pair in &preferred_pairs {
962-
if ensure_student_tag_pair(target, pair).await? {
963-
resolved_conflicts += 1;
1049+
for pair in remote_pairs.difference(&local_pairs) {
1050+
if ensure_student_tag_pair(&local_conn, pair).await? {
1051+
synced_records += 1;
9641052
}
9651053
}
9661054

0 commit comments

Comments
 (0)