mirror of
https://github.com/siyuan-note/siyuan.git
synced 2025-09-22 00:20:47 +02:00
Merge remote-tracking branch 'origin/dev' into dev
This commit is contained in:
commit
5f91cffc4d
22 changed files with 169 additions and 64 deletions
|
@ -1642,6 +1642,7 @@
|
|||
"262": "غدًا",
|
||||
"263": "التالي %d أيام",
|
||||
"264": "الحقل [%s] فارغ",
|
||||
"265": "خارج النطاق"
|
||||
"265": "خارج النطاق",
|
||||
"266": "Tesseract OCR غير مثبت أو غير مهيأ، يرجى الرجوع إلى دليل المستخدم - قسم ملفات الموارد لإجراء الإعداد"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1642,6 +1642,7 @@
|
|||
"262": "מחר",
|
||||
"263": "ה-%d ימים הבאים",
|
||||
"264": "השדה [%s] ריק",
|
||||
"265": "מחוץ לטווח"
|
||||
"265": "מחוץ לטווח",
|
||||
"266": "Tesseract OCR לא הותקן או הוגדר, אנא עיין במדריך למשתמש - פרק קבצי משאבים לצורך הגדרה"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1642,6 +1642,7 @@
|
|||
"262": "明日",
|
||||
"263": "次の %d 日間",
|
||||
"264": "フィールド [%s] の値が空です",
|
||||
"265": "範囲外"
|
||||
"265": "範囲外",
|
||||
"266": "Tesseract OCR がインストールされていないか、設定されていません。ユーザーガイド - リソースファイルセクションを参照して設定してください"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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ć"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1642,6 +1642,7 @@
|
|||
"262": "Завтра",
|
||||
"263": "Следующие %d дней",
|
||||
"264": "Поле [%s] имеет пустое значение",
|
||||
"265": "Вне диапазона"
|
||||
"265": "Вне диапазона",
|
||||
"266": "Tesseract OCR не установлен или не настроен, пожалуйста, обратитесь к Руководству пользователя - Раздел ресурсов для настройки"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1642,6 +1642,7 @@
|
|||
"262": "明天",
|
||||
"263": "未來 %d 天",
|
||||
"264": "字段 [%s] 值為空",
|
||||
"265": "不在範圍內"
|
||||
"265": "不在範圍內",
|
||||
"266": "Tesseract OCR 未安裝或未配置,請參考 使用者指南-資料文件 章節進行配置"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1642,6 +1642,7 @@
|
|||
"262": "明天",
|
||||
"263": "未来 %d 天",
|
||||
"264": "字段 [%s] 值为空",
|
||||
"265": "不在范围内"
|
||||
"265": "不在范围内",
|
||||
"266": "Tesseract OCR 未安装或未配置,请参考 用户指南-资源文件 章节进行配置"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 描述了属性视图属性字段的基础结构。
|
||||
|
@ -191,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 int `json:"groupHidden"` // 分组是否隐藏,0:显示,1:空白隐藏,2:手动隐藏
|
||||
}
|
||||
|
||||
// GroupCalc 描述了分组计算规则和结果的结构。
|
||||
|
@ -289,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) {
|
||||
|
|
|
@ -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 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
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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()}
|
||||
|
@ -121,13 +166,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,16 +231,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
|
||||
for _, g := range view.Groups {
|
||||
if group.HideEmpty {
|
||||
g.GroupHidden = true
|
||||
} else {
|
||||
g.GroupHidden = false
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
genAttrViewViewGroups(view, attrView)
|
||||
err = av.SaveAttributeView(attrView)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -1414,6 +1472,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 {
|
||||
|
@ -1476,7 +1535,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 {
|
||||
|
@ -1598,6 +1660,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 {
|
||||
|
@ -1611,6 +1681,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())
|
||||
}
|
||||
|
@ -1636,7 +1708,14 @@ func genAttrViewViewGroups(view *av.View, attrView *av.AttributeView) {
|
|||
}
|
||||
}
|
||||
|
||||
av.SaveAttributeView(attrView)
|
||||
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 {
|
||||
|
@ -2100,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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue