From 49cc87381cbb162561c0a502e7fd0d5a237a694a Mon Sep 17 00:00:00 2001 From: Daniel <845765@qq.com> Date: Fri, 25 Jul 2025 15:20:56 +0800 Subject: [PATCH 1/8] :art: Database grouping by field https://github.com/siyuan-note/siyuan/issues/10964 --- kernel/av/av.go | 35 +++++++++++++++++----------------- kernel/av/sort.go | 2 +- kernel/av/value.go | 4 ++-- kernel/model/attribute_view.go | 8 ++++++++ 4 files changed, 29 insertions(+), 20 deletions(-) diff --git a/kernel/av/av.go b/kernel/av/av.go index d084675a5..ef3b46720 100644 --- a/kernel/av/av.go +++ b/kernel/av/av.go @@ -79,26 +79,27 @@ func GetKeyBlockValue(blockKeyValues []*KeyValues) (ret *Value) { return } +// KeyType 描述了属性视图属性字段的类型。 type KeyType string const ( - KeyTypeBlock KeyType = "block" - KeyTypeText KeyType = "text" - KeyTypeNumber KeyType = "number" - KeyTypeDate KeyType = "date" - KeyTypeSelect KeyType = "select" - KeyTypeMSelect KeyType = "mSelect" - KeyTypeURL KeyType = "url" - KeyTypeEmail KeyType = "email" - KeyTypePhone KeyType = "phone" - KeyTypeMAsset KeyType = "mAsset" - KeyTypeTemplate KeyType = "template" - KeyTypeCreated KeyType = "created" - KeyTypeUpdated KeyType = "updated" - KeyTypeCheckbox KeyType = "checkbox" - KeyTypeRelation KeyType = "relation" - KeyTypeRollup KeyType = "rollup" - KeyTypeLineNumber KeyType = "lineNumber" + KeyTypeBlock KeyType = "block" // 主键 + KeyTypeText KeyType = "text" // 文本 + KeyTypeNumber KeyType = "number" // 数字 + KeyTypeDate KeyType = "date" // 日期 + KeyTypeSelect KeyType = "select" // 单选 + KeyTypeMSelect KeyType = "mSelect" // 多选 + KeyTypeURL KeyType = "url" // URL + KeyTypeEmail KeyType = "email" // Email + KeyTypePhone KeyType = "phone" // 电话 + KeyTypeMAsset KeyType = "mAsset" // 资源 + KeyTypeTemplate KeyType = "template" // 模板 + KeyTypeCreated KeyType = "created" // 创建时间 + KeyTypeUpdated KeyType = "updated" // 更新时间 + KeyTypeCheckbox KeyType = "checkbox" // 复选框 + KeyTypeRelation KeyType = "relation" // 关联 + KeyTypeRollup KeyType = "rollup" // 汇总 + KeyTypeLineNumber KeyType = "lineNumber" // 行号 ) // Key 描述了属性视图属性字段的基础结构。 diff --git a/kernel/av/sort.go b/kernel/av/sort.go index 1dac261fc..28af345f0 100644 --- a/kernel/av/sort.go +++ b/kernel/av/sort.go @@ -67,7 +67,7 @@ func Sort(viewable Viewable, attrView *AttributeView) { val := items[i].GetValues()[fieldIndexSort.Index] if KeyTypeCheckbox == val.Type { if block := item.GetBlockValue(); nil != block && block.IsEdited() { - // 如果主键编辑过,则勾选框也算作编辑过,参与排序 https://github.com/siyuan-note/siyuan/issues/11016 + // 如果主键编辑过,则复选框也算作编辑过,参与排序 https://github.com/siyuan-note/siyuan/issues/11016 editedValItems[item.GetID()] = true break } diff --git a/kernel/av/value.go b/kernel/av/value.go index 082ea97e4..a86354695 100644 --- a/kernel/av/value.go +++ b/kernel/av/value.go @@ -210,7 +210,7 @@ func (value *Value) IsEdited() bool { } if KeyTypeCheckbox == value.Type { - // 勾选框不会为空,即使勾选框未勾选,也不算是空,所以不能用下面的 IsEmpty 判断,这里使用更新时间判断是否编辑过 https://github.com/siyuan-note/siyuan/issues/11016 + // 复选框不会为空,即使复选框未勾选,也不算是空,所以不能用下面的 IsEmpty 判断,这里使用更新时间判断是否编辑过 https://github.com/siyuan-note/siyuan/issues/11016 return value.CreatedAt != value.UpdatedAt } @@ -289,7 +289,7 @@ func (value *Value) IsEmpty() bool { if nil == value.Checkbox { return true } - return false // 勾选框不会为空 + return false // 复选框不会为空 case KeyTypeRelation: return 1 > len(value.Relation.Contents) case KeyTypeRollup: diff --git a/kernel/model/attribute_view.go b/kernel/model/attribute_view.go index fb61cd577..b46e8bfbd 100644 --- a/kernel/model/attribute_view.go +++ b/kernel/model/attribute_view.go @@ -1598,6 +1598,14 @@ func genAttrViewViewGroups(view *av.View, attrView *av.AttributeView) { groupItemsMap[groupName] = append(groupItemsMap[groupName], item) } + if av.KeyTypeSelect == groupKey.Type || av.KeyTypeMSelect == groupKey.Type { + for _, o := range groupKey.Options { + if _, ok := groupItemsMap[o.Name]; !ok { + groupItemsMap[o.Name] = []av.Item{} + } + } + } + for name, groupItems := range groupItemsMap { var v *av.View switch view.LayoutType { From 33a1bedb4109cce3ab0aa23af68cc244d4317bc3 Mon Sep 17 00:00:00 2001 From: Daniel <845765@qq.com> Date: Fri, 25 Jul 2025 16:34:30 +0800 Subject: [PATCH 2/8] :art: Database grouping by field https://github.com/siyuan-note/siyuan/issues/10964 --- kernel/model/attribute_view.go | 2 ++ kernel/sql/av.go | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/kernel/model/attribute_view.go b/kernel/model/attribute_view.go index b46e8bfbd..2c41c3ea3 100644 --- a/kernel/model/attribute_view.go +++ b/kernel/model/attribute_view.go @@ -1619,6 +1619,8 @@ func genAttrViewViewGroups(view *av.View, attrView *av.AttributeView) { logging.LogWarnf("unknown layout type [%s] for group view", view.LayoutType) return } + + v.GroupItemIDs = []string{} for _, item := range groupItems { v.GroupItemIDs = append(v.GroupItemIDs, item.GetID()) } diff --git a/kernel/sql/av.go b/kernel/sql/av.go index 9ad4f8aa5..53afb0198 100644 --- a/kernel/sql/av.go +++ b/kernel/sql/av.go @@ -202,7 +202,7 @@ func generateAttrViewItems(attrView *av.AttributeView, view *av.View) (ret map[s } // 如果是分组视图,则需要过滤掉不在分组中的项目 - if 0 < len(view.GroupItemIDs) { + if nil != view.GroupItemIDs { tmp := map[string][]*av.KeyValues{} for _, groupItemID := range view.GroupItemIDs { if _, ok := ret[groupItemID]; ok { From 06139eb3cc5c4eeeb13c67debc62c252cd0b0718 Mon Sep 17 00:00:00 2001 From: Daniel <845765@qq.com> Date: Fri, 25 Jul 2025 16:47:17 +0800 Subject: [PATCH 3/8] :art: Database grouping by field https://github.com/siyuan-note/siyuan/issues/10964 --- kernel/av/av.go | 16 ++++++++-------- kernel/av/layout.go | 10 +++++----- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/kernel/av/av.go b/kernel/av/av.go index ef3b46720..f2ba48aa9 100644 --- a/kernel/av/av.go +++ b/kernel/av/av.go @@ -192,14 +192,14 @@ type View struct { Gallery *LayoutGallery `json:"gallery,omitempty"` // 卡片布局 ItemIDs []string `json:"itemIds,omitempty"` // 项目 ID 列表,用于维护所有项目 - Group *ViewGroup `json:"group,omitempty"` // 分组规则 - GroupUpdated int64 `json:"groupUpdated"` // 分组规则更新时间戳 - Groups []*View `json:"groups,omitempty"` // 分组视图列表 - GroupItemIDs []string `json:"groupItemIds,omitempty"` // 分组项目 ID 列表,用于维护分组中的所有项目 - GroupCalc *GroupCalc `json:"groupCalc,omitempty"` // 分组计算规则 - GroupName string `json:"groupName,omitempty"` // 分组名称 - GroupFolded bool `json:"groupFolded"` // 分组是否折叠 - GroupHidden bool `json:"groupHidden"` // 分组是否隐藏 + Group *ViewGroup `json:"group,omitempty"` // 分组规则 + GroupUpdated int64 `json:"groupUpdated"` // 分组规则更新时间戳 + Groups []*View `json:"groups,omitempty"` // 分组视图列表 + GroupItemIDs []string `json:"groupItemIds"` // 分组项目 ID 列表,用于维护分组中的所有项目 + GroupCalc *GroupCalc `json:"groupCalc,omitempty"` // 分组计算规则 + GroupName string `json:"groupName,omitempty"` // 分组名称 + GroupFolded bool `json:"groupFolded"` // 分组是否折叠 + GroupHidden bool `json:"groupHidden"` // 分组是否隐藏 } // GroupCalc 描述了分组计算规则和结果的结构。 diff --git a/kernel/av/layout.go b/kernel/av/layout.go index 6c0b9f3f0..fee969078 100644 --- a/kernel/av/layout.go +++ b/kernel/av/layout.go @@ -64,11 +64,11 @@ type BaseInstance struct { ShowIcon bool `json:"showIcon"` // 是否显示字段图标 WrapField bool `json:"wrapField"` // 是否换行字段内容 - Groups []Viewable `json:"groups,omitempty"` // 分组实例列表 - GroupCalc *GroupCalc `json:"groupCalc,omitempty"` // 分组计算规则和结果 - GroupName string `json:"groupName,omitempty"` // 分组名称 - GroupFolded bool `json:"groupFolded,omitempty"` // 分组是否折叠 - GroupHidden bool `json:"groupHidden,omitempty"` // 分组是否隐藏 + Groups []Viewable `json:"groups,omitempty"` // 分组实例列表 + GroupCalc *GroupCalc `json:"groupCalc,omitempty"` // 分组计算规则和结果 + GroupName string `json:"groupName,omitempty"` // 分组名称 + GroupFolded bool `json:"groupFolded"` // 分组是否折叠 + GroupHidden bool `json:"groupHidden"` // 分组是否隐藏 } func NewViewBaseInstance(view *View) *BaseInstance { From e7a8a9906e1b364b44d2e0c1d5cea85e84a7ff20 Mon Sep 17 00:00:00 2001 From: Daniel <845765@qq.com> Date: Fri, 25 Jul 2025 17:01:38 +0800 Subject: [PATCH 4/8] :art: Database grouping by field https://github.com/siyuan-note/siyuan/issues/10964 --- kernel/model/attribute_view.go | 8 -------- 1 file changed, 8 deletions(-) diff --git a/kernel/model/attribute_view.go b/kernel/model/attribute_view.go index 2c41c3ea3..8cda25666 100644 --- a/kernel/model/attribute_view.go +++ b/kernel/model/attribute_view.go @@ -187,14 +187,6 @@ func SetAttributeViewGroup(avID, blockID string, group *av.ViewGroup) (err error } view.Group = group - for _, g := range view.Groups { - if group.HideEmpty { - g.GroupHidden = true - } else { - g.GroupHidden = false - } - } - genAttrViewViewGroups(view, attrView) return } From 0e8ce9ddf91fb741f3c564c6aeec4a0fb953f447 Mon Sep 17 00:00:00 2001 From: Daniel <845765@qq.com> Date: Fri, 25 Jul 2025 17:57:51 +0800 Subject: [PATCH 5/8] :art: Database grouping by field https://github.com/siyuan-note/siyuan/issues/10964 --- kernel/av/av.go | 5 +++-- kernel/av/layout.go | 4 ++-- kernel/model/attribute_view.go | 33 ++++++++++++++++++++++++++++----- 3 files changed, 33 insertions(+), 9 deletions(-) diff --git a/kernel/av/av.go b/kernel/av/av.go index f2ba48aa9..b536c3f45 100644 --- a/kernel/av/av.go +++ b/kernel/av/av.go @@ -199,7 +199,7 @@ type View struct { GroupCalc *GroupCalc `json:"groupCalc,omitempty"` // 分组计算规则 GroupName string `json:"groupName,omitempty"` // 分组名称 GroupFolded bool `json:"groupFolded"` // 分组是否折叠 - GroupHidden bool `json:"groupHidden"` // 分组是否隐藏 + GroupHidden int `json:"groupHidden"` // 分组是否隐藏,0:显示,1:空白隐藏,2:手动隐藏 } // GroupCalc 描述了分组计算规则和结果的结构。 @@ -290,7 +290,8 @@ type Viewable interface { SetGroupFolded(folded bool) // SetGroupHidden 设置分组是否隐藏。 - SetGroupHidden(hidden bool) + // hidden 0:显示,1:空白隐藏,2:手动隐藏 + SetGroupHidden(hidden int) } func NewAttributeView(id string) (ret *AttributeView) { diff --git a/kernel/av/layout.go b/kernel/av/layout.go index fee969078..2bf4d8dd3 100644 --- a/kernel/av/layout.go +++ b/kernel/av/layout.go @@ -68,7 +68,7 @@ type BaseInstance struct { GroupCalc *GroupCalc `json:"groupCalc,omitempty"` // 分组计算规则和结果 GroupName string `json:"groupName,omitempty"` // 分组名称 GroupFolded bool `json:"groupFolded"` // 分组是否折叠 - GroupHidden bool `json:"groupHidden"` // 分组是否隐藏 + GroupHidden int `json:"groupHidden"` // 分组是否隐藏,0:显示,1:空白隐藏,2:手动隐藏 } func NewViewBaseInstance(view *View) *BaseInstance { @@ -127,7 +127,7 @@ func (baseInstance *BaseInstance) SetGroupFolded(folded bool) { baseInstance.GroupFolded = folded } -func (baseInstance *BaseInstance) SetGroupHidden(hidden bool) { +func (baseInstance *BaseInstance) SetGroupHidden(hidden int) { baseInstance.GroupHidden = hidden } diff --git a/kernel/model/attribute_view.go b/kernel/model/attribute_view.go index 8cda25666..22c9428ae 100644 --- a/kernel/model/attribute_view.go +++ b/kernel/model/attribute_view.go @@ -121,13 +121,13 @@ func syncAttrViewTableColWidth(operation *Operation) (err error) { } func (tx *Transaction) doHideAttrViewGroup(operation *Operation) (ret *TxErr) { - if err := hideAttributeViewGroup(operation.AvID, operation.BlockID, operation.ID, operation.Data.(bool)); nil != err { + if err := hideAttributeViewGroup(operation.AvID, operation.BlockID, operation.ID, int(operation.Data.(float64))); nil != err { return &TxErr{code: TxErrHandleAttributeView, id: operation.AvID, msg: err.Error()} } return } -func hideAttributeViewGroup(avID, blockID, groupID string, hidden bool) (err error) { +func hideAttributeViewGroup(avID, blockID, groupID string, hidden int) (err error) { attrView, err := av.ParseAttributeView(avID) if err != nil { return err @@ -186,8 +186,29 @@ func SetAttributeViewGroup(avID, blockID string, group *av.ViewGroup) (err error return err } + oldHideEmpty := false + if nil != view.Group { + oldHideEmpty = view.Group.HideEmpty + } + view.Group = group genAttrViewViewGroups(view, attrView) + + if view.Group.HideEmpty != oldHideEmpty { + for _, g := range view.Groups { + if view.Group.HideEmpty { + if 2 != g.GroupHidden && 1 > len(g.GroupItemIDs) { + g.GroupHidden = 1 + } + } else { + if 2 != g.GroupHidden { + g.GroupHidden = 0 + } + } + } + } + + err = av.SaveAttributeView(attrView) return } @@ -1406,6 +1427,7 @@ func renderAttributeView(attrView *av.AttributeView, blockID, viewID, query stri updatedDate := time.UnixMilli(view.GroupUpdated).Format("2006-01-02") if time.Now().Format("2006-01-02") != updatedDate { genAttrViewViewGroups(view, attrView) + av.SaveAttributeView(attrView) } for _, groupView := range view.Groups { @@ -1468,7 +1490,10 @@ func genAttrViewViewGroups(view *av.View, attrView *av.AttributeView) { } // 如果是按日期分组,则需要记录每个分组视图的一些状态字段,以便后面重新计算分组后可以恢复这些状态 - type GroupState struct{ Folded, Hidden bool } + type GroupState struct { + Folded bool + Hidden int + } groupStates := map[string]*GroupState{} if isGroupByDate(view) { for _, groupView := range view.Groups { @@ -1637,8 +1662,6 @@ func genAttrViewViewGroups(view *av.View, attrView *av.AttributeView) { } } } - - av.SaveAttributeView(attrView) } func isGroupByDate(view *av.View) bool { From b15489a4cf237a42e65758c19f59698618512720 Mon Sep 17 00:00:00 2001 From: Daniel <845765@qq.com> Date: Fri, 25 Jul 2025 19:06:38 +0800 Subject: [PATCH 6/8] :art: Database grouping by field https://github.com/siyuan-note/siyuan/issues/10964 --- kernel/model/attribute_view.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/kernel/model/attribute_view.go b/kernel/model/attribute_view.go index 22c9428ae..0616dba48 100644 --- a/kernel/model/attribute_view.go +++ b/kernel/model/attribute_view.go @@ -1662,6 +1662,15 @@ func genAttrViewViewGroups(view *av.View, attrView *av.AttributeView) { } } } + + if av.GroupOrderMan != view.Group.Order { + sort.SliceStable(view.Groups, func(i, j int) bool { + if av.GroupOrderAsc == view.Group.Order { + return view.Groups[i].Name < view.Groups[j].Name + } + return view.Groups[i].Name > view.Groups[j].Name + }) + } } func isGroupByDate(view *av.View) bool { From 7787ac6e1dbf006b6e1d7f5157d2d9ae018741e4 Mon Sep 17 00:00:00 2001 From: Daniel <845765@qq.com> Date: Fri, 25 Jul 2025 19:17:58 +0800 Subject: [PATCH 7/8] :art: Database grouping by field https://github.com/siyuan-note/siyuan/issues/10964 --- kernel/model/attribute_view.go | 48 +++++++++++++++++++++++++++++++--- kernel/model/transaction.go | 2 ++ 2 files changed, 47 insertions(+), 3 deletions(-) diff --git a/kernel/model/attribute_view.go b/kernel/model/attribute_view.go index 0616dba48..4a8c8285f 100644 --- a/kernel/model/attribute_view.go +++ b/kernel/model/attribute_view.go @@ -44,6 +44,51 @@ import ( "github.com/xrash/smetrics" ) +func (tx *Transaction) doSortAttrViewGroup(operation *Operation) (ret *TxErr) { + if err := sortAttributeViewGroup(operation.AvID, operation.BlockID, operation.PreviousID, operation.ID); nil != err { + return &TxErr{code: TxErrHandleAttributeView, id: operation.AvID, msg: err.Error()} + } + return +} + +func sortAttributeViewGroup(avID, blockID, previousGroupID, groupID string) (err error) { + attrView, err := av.ParseAttributeView(avID) + if err != nil { + logging.LogErrorf("parse attribute view [%s] failed: %s", avID, err) + return + } + + view, err := getAttrViewViewByBlockID(attrView, blockID) + if err != nil { + return err + } + + var group *av.View + var index, previousIndex int + for i, g := range view.Groups { + if g.ID == groupID { + group = g + index = i + break + } + } + if nil == group { + return + } + + view.Groups = append(view.Groups[:index], view.Groups[index+1:]...) + for i, g := range group.Groups { + if g.ID == previousGroupID { + previousIndex = i + 1 + break + } + } + view.Groups = util.InsertElem(view.Groups, previousIndex, group) + + err = av.SaveAttributeView(attrView) + return +} + func (tx *Transaction) doRemoveAttrViewGroup(operation *Operation) (ret *TxErr) { if err := removeAttributeViewGroup(operation.AvID, operation.BlockID); nil != err { return &TxErr{code: TxErrHandleAttributeView, id: operation.AvID, msg: err.Error()} @@ -2134,9 +2179,6 @@ func (tx *Transaction) doSortAttrViewView(operation *Operation) (ret *TxErr) { break } } - if nil == view { - return - } attrView.Views = append(attrView.Views[:index], attrView.Views[index+1:]...) for i, v := range attrView.Views { diff --git a/kernel/model/transaction.go b/kernel/model/transaction.go index 89fec1826..c48273021 100644 --- a/kernel/model/transaction.go +++ b/kernel/model/transaction.go @@ -305,6 +305,8 @@ func performTx(tx *Transaction) (ret *TxErr) { ret = tx.doSyncAttrViewTableColWidth(op) case "removeAttrViewGroup": ret = tx.doRemoveAttrViewGroup(op) + case "sortAttrViewGroup": + ret = tx.doSortAttrViewGroup(op) } if nil != ret { From 70741fffcc61fd9a46596dcb91dad8bf8d610c77 Mon Sep 17 00:00:00 2001 From: Daniel <845765@qq.com> Date: Fri, 25 Jul 2025 19:34:35 +0800 Subject: [PATCH 8/8] :art: `Re OCR` popup prompt when Tesseract is not enabled https://github.com/siyuan-note/siyuan/issues/15367 --- app/appearance/langs/ar_SA.json | 3 ++- app/appearance/langs/de_DE.json | 3 ++- app/appearance/langs/en_US.json | 3 ++- app/appearance/langs/es_ES.json | 3 ++- app/appearance/langs/fr_FR.json | 3 ++- app/appearance/langs/he_IL.json | 3 ++- app/appearance/langs/it_IT.json | 3 ++- app/appearance/langs/ja_JP.json | 3 ++- app/appearance/langs/pl_PL.json | 3 ++- app/appearance/langs/pt_BR.json | 3 ++- app/appearance/langs/ru_RU.json | 3 ++- app/appearance/langs/zh_CHT.json | 3 ++- app/appearance/langs/zh_CN.json | 3 ++- kernel/api/asset.go | 9 ++++++++- kernel/util/ocr.go | 7 ++++++- 15 files changed, 40 insertions(+), 15 deletions(-) diff --git a/app/appearance/langs/ar_SA.json b/app/appearance/langs/ar_SA.json index 7fca87a12..1bbb7afdd 100644 --- a/app/appearance/langs/ar_SA.json +++ b/app/appearance/langs/ar_SA.json @@ -1642,6 +1642,7 @@ "262": "غدًا", "263": "التالي %d أيام", "264": "الحقل [%s] فارغ", - "265": "خارج النطاق" + "265": "خارج النطاق", + "266": "Tesseract OCR غير مثبت أو غير مهيأ، يرجى الرجوع إلى دليل المستخدم - قسم ملفات الموارد لإجراء الإعداد" } } diff --git a/app/appearance/langs/de_DE.json b/app/appearance/langs/de_DE.json index 3d3f03a9c..47f75f90f 100644 --- a/app/appearance/langs/de_DE.json +++ b/app/appearance/langs/de_DE.json @@ -1642,6 +1642,7 @@ "262": "Morgen", "263": "Nächste %d Tage", "264": "Das Feld [%s] ist leer", - "265": "Außerhalb des Bereichs" + "265": "Außerhalb des Bereichs", + "266": "Tesseract OCR ist nicht installiert oder konfiguriert, bitte lesen Sie das Benutzerhandbuch - Abschnitt Ressourcen-Dateien zur Konfiguration" } } diff --git a/app/appearance/langs/en_US.json b/app/appearance/langs/en_US.json index f0b540463..9e821ddd4 100644 --- a/app/appearance/langs/en_US.json +++ b/app/appearance/langs/en_US.json @@ -1642,6 +1642,7 @@ "262": "Tomorrow", "263": "Next %d days", "264": "Field [%s] is empty", - "265": "Out of range" + "265": "Out of range", + "266": "Tesseract OCR is not installed or configured, please refer to the User Guide - Assets section for configuration" } } diff --git a/app/appearance/langs/es_ES.json b/app/appearance/langs/es_ES.json index 0268c882c..383e9d0c8 100644 --- a/app/appearance/langs/es_ES.json +++ b/app/appearance/langs/es_ES.json @@ -1642,6 +1642,7 @@ "262": "Mañana", "263": "Próximos %d días", "264": "El campo [%s] está vacío", - "265": "Fuera de rango" + "265": "Fuera de rango", + "266": "Tesseract OCR no está instalado o configurado, consulte la Guía del Usuario - Sección de archivos de recursos para la configuración" } } diff --git a/app/appearance/langs/fr_FR.json b/app/appearance/langs/fr_FR.json index 134c2d530..982d32481 100644 --- a/app/appearance/langs/fr_FR.json +++ b/app/appearance/langs/fr_FR.json @@ -1642,6 +1642,7 @@ "262": "Demain", "263": "Les %d prochains jours", "264": "Le champ [%s] est vide", - "265": "Hors de portée" + "265": "Hors de portée", + "266": "Tesseract OCR n'est pas installé ou configuré, veuillez consulter le Guide de l'utilisateur - Section des fichiers de ressources pour la configuration" } } diff --git a/app/appearance/langs/he_IL.json b/app/appearance/langs/he_IL.json index b69bb0489..5b7274fb1 100644 --- a/app/appearance/langs/he_IL.json +++ b/app/appearance/langs/he_IL.json @@ -1642,6 +1642,7 @@ "262": "מחר", "263": "ה-%d ימים הבאים", "264": "השדה [%s] ריק", - "265": "מחוץ לטווח" + "265": "מחוץ לטווח", + "266": "Tesseract OCR לא הותקן או הוגדר, אנא עיין במדריך למשתמש - פרק קבצי משאבים לצורך הגדרה" } } diff --git a/app/appearance/langs/it_IT.json b/app/appearance/langs/it_IT.json index fa3d8219f..d811d2bfe 100644 --- a/app/appearance/langs/it_IT.json +++ b/app/appearance/langs/it_IT.json @@ -1642,6 +1642,7 @@ "262": "Domani", "263": "Prossimi %d giorni", "264": "Il campo [%s] è vuoto", - "265": "Fuori intervallo" + "265": "Fuori intervallo", + "266": "Tesseract OCR non è installato o configurato, fare riferimento alla Guida utente - Sezione file di risorse per la configurazione" } } diff --git a/app/appearance/langs/ja_JP.json b/app/appearance/langs/ja_JP.json index 99d26871e..830dd3edb 100644 --- a/app/appearance/langs/ja_JP.json +++ b/app/appearance/langs/ja_JP.json @@ -1642,6 +1642,7 @@ "262": "明日", "263": "次の %d 日間", "264": "フィールド [%s] の値が空です", - "265": "範囲外" + "265": "範囲外", + "266": "Tesseract OCR がインストールされていないか、設定されていません。ユーザーガイド - リソースファイルセクションを参照して設定してください" } } diff --git a/app/appearance/langs/pl_PL.json b/app/appearance/langs/pl_PL.json index dc13d5dbd..092d8ff85 100644 --- a/app/appearance/langs/pl_PL.json +++ b/app/appearance/langs/pl_PL.json @@ -1642,6 +1642,7 @@ "262": "Jutro", "263": "Następne %d dni", "264": "Pole [%s] jest puste", - "265": "Poza zakresem" + "265": "Poza zakresem", + "266": "Tesseract OCR nie jest zainstalowany lub skonfigurowany, zapoznaj się z Podręcznikiem użytkownika - Sekcja plików zasobów, aby skonfigurować" } } diff --git a/app/appearance/langs/pt_BR.json b/app/appearance/langs/pt_BR.json index 562a94c4c..dceafde79 100644 --- a/app/appearance/langs/pt_BR.json +++ b/app/appearance/langs/pt_BR.json @@ -1642,6 +1642,7 @@ "262": "Amanhã", "263": "Próximos %d dias", "264": "O campo [%s] está vazio", - "265": "Fora do intervalo" + "265": "Fora do intervalo", + "266": "Tesseract OCR não está instalado ou configurado, consulte o Guia do Usuário - Seção de Arquivos de Recursos para configuração" } } diff --git a/app/appearance/langs/ru_RU.json b/app/appearance/langs/ru_RU.json index 4695eb594..674a42eab 100644 --- a/app/appearance/langs/ru_RU.json +++ b/app/appearance/langs/ru_RU.json @@ -1642,6 +1642,7 @@ "262": "Завтра", "263": "Следующие %d дней", "264": "Поле [%s] имеет пустое значение", - "265": "Вне диапазона" + "265": "Вне диапазона", + "266": "Tesseract OCR не установлен или не настроен, пожалуйста, обратитесь к Руководству пользователя - Раздел ресурсов для настройки" } } diff --git a/app/appearance/langs/zh_CHT.json b/app/appearance/langs/zh_CHT.json index 31b1365e3..7329141da 100644 --- a/app/appearance/langs/zh_CHT.json +++ b/app/appearance/langs/zh_CHT.json @@ -1642,6 +1642,7 @@ "262": "明天", "263": "未來 %d 天", "264": "字段 [%s] 值為空", - "265": "不在範圍內" + "265": "不在範圍內", + "266": "Tesseract OCR 未安裝或未配置,請參考 使用者指南-資料文件 章節進行配置" } } diff --git a/app/appearance/langs/zh_CN.json b/app/appearance/langs/zh_CN.json index d536d748c..310492d55 100644 --- a/app/appearance/langs/zh_CN.json +++ b/app/appearance/langs/zh_CN.json @@ -1642,6 +1642,7 @@ "262": "明天", "263": "未来 %d 天", "264": "字段 [%s] 值为空", - "265": "不在范围内" + "265": "不在范围内", + "266": "Tesseract OCR 未安装或未配置,请参考 用户指南-资源文件 章节进行配置" } } diff --git a/kernel/api/asset.go b/kernel/api/asset.go index f67c7ad0a..446906560 100644 --- a/kernel/api/asset.go +++ b/kernel/api/asset.go @@ -153,7 +153,14 @@ func ocr(c *gin.Context) { path := arg["path"].(string) - ocrJSON := util.OcrAsset(path) + ocrJSON, err := util.OcrAsset(path) + if nil != err { + ret.Code = -1 + ret.Msg = err.Error() + ret.Data = map[string]interface{}{"closeTimeout": 7000} + return + } + ret.Data = map[string]interface{}{ "text": util.GetOcrJsonText(ocrJSON), "ocrJSON": ocrJSON, diff --git a/kernel/util/ocr.go b/kernel/util/ocr.go index 7aabfc7e5..6dd817fff 100644 --- a/kernel/util/ocr.go +++ b/kernel/util/ocr.go @@ -149,7 +149,12 @@ func ExistsAssetText(asset string) (ret bool) { return } -func OcrAsset(asset string) (ret []map[string]interface{}) { +func OcrAsset(asset string) (ret []map[string]interface{}, err error) { + if !TesseractEnabled { + err = fmt.Errorf(Langs[Lang][266]) + return + } + assetsPath := GetDataAssetsAbsPath() assetAbsPath := strings.TrimPrefix(asset, "assets") assetAbsPath = filepath.Join(assetsPath, assetAbsPath)