From 441874b2cd92b1d14fcf45ea98ab7f6741d52e8a Mon Sep 17 00:00:00 2001 From: Daniel <845765@qq.com> Date: Tue, 8 Jul 2025 15:47:19 +0800 Subject: [PATCH] :art: Database grouping by field https://github.com/siyuan-note/siyuan/issues/10964 --- app/appearance/langs/ar_SA.json | 7 ++- app/appearance/langs/de_DE.json | 7 ++- app/appearance/langs/en_US.json | 7 ++- app/appearance/langs/es_ES.json | 7 ++- app/appearance/langs/fr_FR.json | 7 ++- app/appearance/langs/he_IL.json | 7 ++- app/appearance/langs/it_IT.json | 7 ++- app/appearance/langs/ja_JP.json | 7 ++- app/appearance/langs/pl_PL.json | 7 ++- app/appearance/langs/pt_BR.json | 7 ++- app/appearance/langs/ru_RU.json | 7 ++- app/appearance/langs/zh_CHT.json | 7 ++- app/appearance/langs/zh_CN.json | 7 ++- kernel/model/attribute_view.go | 100 +++++++++++++++++++------------ 14 files changed, 140 insertions(+), 51 deletions(-) diff --git a/app/appearance/langs/ar_SA.json b/app/appearance/langs/ar_SA.json index f011b84c0..ea3c7594d 100644 --- a/app/appearance/langs/ar_SA.json +++ b/app/appearance/langs/ar_SA.json @@ -1627,6 +1627,11 @@ "255": "قام الموقع المستهدف بتمكين حماية الروابط المباشرة، لذلك لا يمكن تنزيل [%d] من الموارد", "256": "المسار المحدد [%s] يحتوي على مسار مساحة عمل رئيسي [%s]", "257": "تذكرني لمدة 30 يومًا", - "258": "فشلت العملية، يرجى المحاولة مرة أخرى لاحقًا" + "258": "فشلت العملية، يرجى المحاولة مرة أخرى لاحقًا", + "259": "آخر %d أيام", + "260": "أمس", + "261": "اليوم", + "262": "غدًا", + "263": "التالي %d أيام" } } diff --git a/app/appearance/langs/de_DE.json b/app/appearance/langs/de_DE.json index 6c06c9497..de631d2c0 100644 --- a/app/appearance/langs/de_DE.json +++ b/app/appearance/langs/de_DE.json @@ -1627,6 +1627,11 @@ "255": "Die Zielseite hat den Hotlink-Schutz aktiviert, daher ist es nicht möglich, [%d] Ressourcen herunterzuladen", "256": "Der angegebene Pfad [%s] hat einen übergeordneten Arbeitsbereichspfad [%s]", "257": "Erinnere dich 30 Tage an mich", - "258": "Vorgang fehlgeschlagen, bitte versuchen Sie es später erneut" + "258": "Vorgang fehlgeschlagen, bitte versuchen Sie es später erneut", + "259": "Letzte %d Tage", + "260": "Gestern", + "261": "Heute", + "262": "Morgen", + "263": "Nächste %d Tage" } } diff --git a/app/appearance/langs/en_US.json b/app/appearance/langs/en_US.json index 5868a6891..ff71310c3 100644 --- a/app/appearance/langs/en_US.json +++ b/app/appearance/langs/en_US.json @@ -1627,6 +1627,11 @@ "255": "The target site has enabled hotlink protection, so it is not possible to download [%d] resources", "256": "The specified path [%s] has a parent workspace path [%s]", "257": "Remember me for 30 days", - "258": "Operation failed, please try again later" + "258": "Operation failed, please try again later", + "259": "Last %d days", + "260": "Yesterday", + "261": "Today", + "262": "Tomorrow", + "263": "Next %d days" } } diff --git a/app/appearance/langs/es_ES.json b/app/appearance/langs/es_ES.json index 791c3ac64..e219f4c59 100644 --- a/app/appearance/langs/es_ES.json +++ b/app/appearance/langs/es_ES.json @@ -1627,6 +1627,11 @@ "255": "El sitio de destino ha activado la protección contra hotlinking, por lo que no es posible descargar [%d] recursos", "256": "La ruta especificada [%s] tiene una ruta de espacio de trabajo padre [%s]", "257": "Recuérdame durante 30 días", - "258": "La operación falló, inténtelo de nuevo más tarde" + "258": "La operación falló, inténtelo de nuevo más tarde", + "259": "Últimos %d días", + "260": "Ayer", + "261": "Hoy", + "262": "Mañana", + "263": "Próximos %d días" } } diff --git a/app/appearance/langs/fr_FR.json b/app/appearance/langs/fr_FR.json index a9de3f59b..084b84c60 100644 --- a/app/appearance/langs/fr_FR.json +++ b/app/appearance/langs/fr_FR.json @@ -1627,6 +1627,11 @@ "255": "Le site cible a activé la protection contre le hotlinking, il est donc impossible de télécharger [%d] ressources", "256": "Le chemin spécifié [%s] contient un chemin d'espace de travail parent [%s]", "257": "Souviens-toi de moi pendant 30 jours", - "258": "Échec de l'opération, veuillez réessayer plus tard" + "258": "Échec de l'opération, veuillez réessayer plus tard", + "259": "Les %d derniers jours", + "260": "Hier", + "261": "Aujourd'hui", + "262": "Demain", + "263": "Les %d prochains jours" } } diff --git a/app/appearance/langs/he_IL.json b/app/appearance/langs/he_IL.json index a6b5c9605..441cf2a88 100644 --- a/app/appearance/langs/he_IL.json +++ b/app/appearance/langs/he_IL.json @@ -1627,6 +1627,11 @@ "255": "האתר היעד הפעיל הגנה על קישורים חמים, ולכן לא ניתן להוריד [%d] משאבים", "256": "הנתיב שצוין [%s] מכיל נתיב מרחב עבודה אב [%s]", "257": "זכור אותי למשך 30 יום", - "258": "הפעולה נכשלה, נסה שוב מאוחר יותר" + "258": "הפעולה נכשלה, נסה שוב מאוחר יותר", + "259": "ה-%d ימים האחרונים", + "260": "אתמול", + "261": "היום", + "262": "מחר", + "263": "ה-%d ימים הבאים" } } diff --git a/app/appearance/langs/it_IT.json b/app/appearance/langs/it_IT.json index 9bbefee47..1e5c829da 100644 --- a/app/appearance/langs/it_IT.json +++ b/app/appearance/langs/it_IT.json @@ -1627,6 +1627,11 @@ "255": "Il sito di destinazione ha abilitato la protezione hotlink, quindi non è possibile scaricare [%d] risorse", "256": "Il percorso specificato [%s] ha un percorso di spazio di lavoro padre [%s]", "257": "Ricordati di me per 30 giorni", - "258": "Operazione fallita, riprova più tardi" + "258": "Operazione fallita, riprova più tardi", + "259": "Ultimi %d giorni", + "260": "Ieri", + "261": "Oggi", + "262": "Domani", + "263": "Prossimi %d giorni" } } diff --git a/app/appearance/langs/ja_JP.json b/app/appearance/langs/ja_JP.json index 3a2d8f7dc..691cd0ee3 100644 --- a/app/appearance/langs/ja_JP.json +++ b/app/appearance/langs/ja_JP.json @@ -1627,6 +1627,11 @@ "255": "ターゲットサイトはホットリンク保護を有効にしているため、[%d] 個のリソースをダウンロードできません", "256": "指定されたパス [%s] の親にワークスペースパス [%s] が存在します", "257": "30日間私を覚えていてください", - "258": "操作に失敗しました。後でもう一度お試しください" + "258": "操作に失敗しました。後でもう一度お試しください", + "259": "過去 %d 日間", + "260": "昨日", + "261": "今日", + "262": "明日", + "263": "次の %d 日間" } } diff --git a/app/appearance/langs/pl_PL.json b/app/appearance/langs/pl_PL.json index c6167b2cb..44437727f 100644 --- a/app/appearance/langs/pl_PL.json +++ b/app/appearance/langs/pl_PL.json @@ -1627,6 +1627,11 @@ "255": "Docelowa strona włączyła ochronę przed hotlinkowaniem, [%d] zasobów nie można pobrać", "256": "Określona ścieżka [%s] ma nadrzędną ścieżkę przestrzeni roboczej [%s]", "257": "Zapamiętaj mnie na 30 dni", - "258": "Operacja nie powiodła się, spróbuj ponownie później" + "258": "Operacja nie powiodła się, spróbuj ponownie później", + "259": "Ostatnie %d dni", + "260": "Wczoraj", + "261": "Dzisiaj", + "262": "Jutro", + "263": "Następne %d dni" } } diff --git a/app/appearance/langs/pt_BR.json b/app/appearance/langs/pt_BR.json index 7f2a7c600..1a4279646 100644 --- a/app/appearance/langs/pt_BR.json +++ b/app/appearance/langs/pt_BR.json @@ -1627,6 +1627,11 @@ "255": "O site de destino ativou proteção contra hotlinking, portanto não é possível baixar [%d] recursos", "256": "O caminho especificado [%s] tem um caminho de espaço de trabalho pai [%s]", "257": "Lembre-se de mim por 30 dias", - "258": "A operação falhou, tente novamente mais tarde" + "258": "A operação falhou, tente novamente mais tarde", + "259": "Últimos %d dias", + "260": "Ontem", + "261": "Hoje", + "262": "Amanhã", + "263": "Próximos %d dias" } } diff --git a/app/appearance/langs/ru_RU.json b/app/appearance/langs/ru_RU.json index b5873e368..8836010fc 100644 --- a/app/appearance/langs/ru_RU.json +++ b/app/appearance/langs/ru_RU.json @@ -1627,6 +1627,11 @@ "255": "Целевой сайт включил защиту от хотлинков, [%d] ресурсов невозможно скачать", "256": "Указанный путь [%s] имеет родительский путь рабочей области [%s]", "257": "Запомнить меня на 30 дней", - "258": "Операция не удалась, попробуйте позже" + "258": "Операция не удалась, попробуйте позже", + "259": "Прошедшие %d дней", + "260": "Вчера", + "261": "Сегодня", + "262": "Завтра", + "263": "Следующие %d дней" } } diff --git a/app/appearance/langs/zh_CHT.json b/app/appearance/langs/zh_CHT.json index a7366eb0a..122758b09 100644 --- a/app/appearance/langs/zh_CHT.json +++ b/app/appearance/langs/zh_CHT.json @@ -1627,6 +1627,11 @@ "255": "目標站點啟用了防盜鏈,[%d] 個資源無法下載", "256": "指定的路徑 [%s] 父級存在工作空間路徑 [%s]", "257": "記住我 30 天", - "258": "操作失敗,請稍後再試" + "258": "操作失敗,請稍後再試", + "259": "過去 %d 天", + "260": "昨天", + "261": "今天", + "262": "明天", + "263": "未來 %d 天" } } diff --git a/app/appearance/langs/zh_CN.json b/app/appearance/langs/zh_CN.json index dd4ec71ce..afb061186 100644 --- a/app/appearance/langs/zh_CN.json +++ b/app/appearance/langs/zh_CN.json @@ -1627,6 +1627,11 @@ "255": "目标站点启用了防盗链,[%d] 个资源无法下载", "256": "指定的路径 [%s] 父级存在工作空间路径 [%s]", "257": "记住我 30 天", - "258": "操作失败,请稍后再试" + "258": "操作失败,请稍后再试", + "259": "过去 %d 天", + "260": "昨天", + "261": "今天", + "262": "明天", + "263": "未来 %d 天" } } diff --git a/kernel/model/attribute_view.go b/kernel/model/attribute_view.go index 88dae2279..db747f600 100644 --- a/kernel/model/attribute_view.go +++ b/kernel/model/attribute_view.go @@ -195,46 +195,70 @@ func SetAttributeViewGroup(avID, blockID string, group *av.ViewGroup) (err error value := item.GetValue(group.Field) if value.IsEmpty() { groupName = defaultGroupName - } else { + groupItemsMap[groupName] = append(groupItemsMap[groupName], item) + continue + } + + switch group.Method { + case av.GroupMethodValue: + groupName = value.String(false) + case av.GroupMethodRangeNum: + if group.Range.NumStart > value.Number.Content || group.Range.NumEnd < value.Number.Content { + groupName = notInRange + break + } + + for rangeEnd <= group.Range.NumEnd && rangeEnd < value.Number.Content { + rangeStart += group.Range.NumStep + rangeEnd += group.Range.NumStep + } + + if rangeStart <= value.Number.Content && rangeEnd >= value.Number.Content { + groupName = fmt.Sprintf("%s - %s", strconv.FormatFloat(rangeStart, 'f', -1, 64), strconv.FormatFloat(rangeEnd, 'f', -1, 64)) + } + case av.GroupMethodDateDay, av.GroupMethodDateWeek, av.GroupMethodDateMonth, av.GroupMethodDateYear, av.GroupMethodDateRelative: + var contentTime time.Time + switch value.Type { + case av.KeyTypeDate: + contentTime = time.UnixMilli(value.Date.Content) + case av.KeyTypeCreated: + contentTime = time.UnixMilli(value.Created.Content) + case av.KeyTypeUpdated: + contentTime = time.UnixMilli(value.Updated.Content) + } switch group.Method { - case av.GroupMethodValue: - groupName = value.String(false) - case av.GroupMethodRangeNum: - if group.Range.NumStart > value.Number.Content || group.Range.NumEnd < value.Number.Content { - groupName = notInRange - break - } - - for rangeEnd <= group.Range.NumEnd && rangeEnd < value.Number.Content { - rangeStart += group.Range.NumStep - rangeEnd += group.Range.NumStep - } - - if rangeStart <= value.Number.Content && rangeEnd >= value.Number.Content { - groupName = fmt.Sprintf("%s - %s", strconv.FormatFloat(rangeStart, 'f', -1, 64), strconv.FormatFloat(rangeEnd, 'f', -1, 64)) - } - case av.GroupMethodDateDay, av.GroupMethodDateWeek, av.GroupMethodDateMonth, av.GroupMethodDateYear, av.GroupMethodDateRelative: - var contentTime time.Time - switch value.Type { - case av.KeyTypeDate: - contentTime = time.UnixMilli(value.Date.Content) - case av.KeyTypeCreated: - contentTime = time.UnixMilli(value.Created.Content) - case av.KeyTypeUpdated: - contentTime = time.UnixMilli(value.Updated.Content) - } - switch group.Method { - case av.GroupMethodDateDay: - groupName = contentTime.Format("2006-01-02") - case av.GroupMethodDateWeek: - year, week := contentTime.ISOWeek() - groupName = fmt.Sprintf("%d-W%02d", year, week) - case av.GroupMethodDateMonth: + case av.GroupMethodDateDay: + groupName = contentTime.Format("2006-01-02") + case av.GroupMethodDateWeek: + year, week := contentTime.ISOWeek() + groupName = fmt.Sprintf("%d-W%02d", year, week) + case av.GroupMethodDateMonth: + groupName = contentTime.Format("2006-01") + case av.GroupMethodDateYear: + groupName = contentTime.Format("2006") + case av.GroupMethodDateRelative: + // 过去 30 天之前的按月分组 + // 过去 30 天、过去 7 天、昨天、今天、明天、未来 7 天、未来 30 天 + // 未来 30 天之后的按月分组 + now := time.Now() + if contentTime.Before(now.AddDate(0, 0, -30)) { + groupName = contentTime.Format("2006-01") + } else if contentTime.Before(now.AddDate(0, 0, -7)) { + groupName = fmt.Sprintf(Conf.language(259), 30) + } else if contentTime.Before(now.AddDate(0, 0, -1)) { + groupName = fmt.Sprintf(Conf.language(259), 7) + } else if contentTime.Equal(now.AddDate(0, 0, -1)) { + groupName = Conf.language(260) + } else if contentTime.Equal(now) { + groupName = Conf.language(261) + } else if contentTime.Equal(now.AddDate(0, 0, 1)) { + groupName = Conf.language(262) + } else if contentTime.Before(now.AddDate(0, 0, 7)) { + groupName = fmt.Sprintf(Conf.language(263), 7) + } else if contentTime.Before(now.AddDate(0, 0, 30)) { + groupName = fmt.Sprintf(Conf.language(263), 30) + } else { groupName = contentTime.Format("2006-01") - case av.GroupMethodDateYear: - groupName = contentTime.Format("2006") - case av.GroupMethodDateRelative: - } } }