diff --git a/kernel/av/filter.go b/kernel/av/filter.go index d23da4141..01d91d4c6 100644 --- a/kernel/av/filter.go +++ b/kernel/av/filter.go @@ -20,6 +20,7 @@ import ( "strings" "time" + "github.com/88250/lute/ast" "github.com/siyuan-note/siyuan/kernel/util" ) @@ -121,10 +122,20 @@ func (value *Value) Filter(filter *ViewFilter, attrView *AttributeView, rowID st return false } + destKey, _ := destAv.GetKey(key.Rollup.KeyID) + if nil == destKey { + return false + } + for _, blockID := range relVal.Relation.BlockIDs { destVal := destAv.GetValue(key.Rollup.KeyID, blockID) if nil == destVal { - continue + if destAv.ExistBlock(blockID) { // 数据库中存在行但是列值不存在是数据未初始化,这里补一个默认值 + destVal = GetAttributeViewDefaultValue(ast.NewNodeID(), key.Rollup.KeyID, blockID, destKey.Type) + } + if nil == destVal { + continue + } } if destVal.filter(filter.Value.Rollup.Contents[0], filter.RelativeDate, filter.RelativeDate2, filter.Operator) { diff --git a/kernel/av/value.go b/kernel/av/value.go index 1974f09fa..8ca108d45 100644 --- a/kernel/av/value.go +++ b/kernel/av/value.go @@ -25,6 +25,7 @@ import ( "time" "github.com/88250/gulu" + "github.com/88250/lute/ast" "github.com/siyuan-note/siyuan/kernel/util" "golang.org/x/text/language" "golang.org/x/text/message" @@ -902,3 +903,56 @@ func (r *ValueRollup) RenderContents(calc *RollupCalc, destKey *Key) { } } } + +func GetAttributeViewDefaultValue(valueID, keyID, blockID string, typ KeyType) (ret *Value) { + if "" == valueID { + valueID = ast.NewNodeID() + } + + ret = &Value{ID: valueID, KeyID: keyID, BlockID: blockID, Type: typ} + + createdStr := valueID[:len("20060102150405")] + created, parseErr := time.ParseInLocation("20060102150405", createdStr, time.Local) + if nil == parseErr { + ret.CreatedAt = created.UnixMilli() + } else { + ret.CreatedAt = time.Now().UnixMilli() + } + if 0 == ret.UpdatedAt { + ret.UpdatedAt = ret.CreatedAt + } + + switch typ { + case KeyTypeText: + ret.Text = &ValueText{} + case KeyTypeNumber: + ret.Number = &ValueNumber{} + case KeyTypeDate: + ret.Date = &ValueDate{} + case KeyTypeSelect: + ret.MSelect = []*ValueSelect{} + case KeyTypeMSelect: + ret.MSelect = []*ValueSelect{} + case KeyTypeURL: + ret.URL = &ValueURL{} + case KeyTypeEmail: + ret.Email = &ValueEmail{} + case KeyTypePhone: + ret.Phone = &ValuePhone{} + case KeyTypeMAsset: + ret.MAsset = []*ValueAsset{} + case KeyTypeTemplate: + ret.Template = &ValueTemplate{} + case KeyTypeCreated: + ret.Created = &ValueCreated{} + case KeyTypeUpdated: + ret.Updated = &ValueUpdated{} + case KeyTypeCheckbox: + ret.Checkbox = &ValueCheckbox{} + case KeyTypeRelation: + ret.Relation = &ValueRelation{} + case KeyTypeRollup: + ret.Rollup = &ValueRollup{} + } + return +} diff --git a/kernel/model/attribute_view.go b/kernel/model/attribute_view.go index 23140b370..551719b2c 100644 --- a/kernel/model/attribute_view.go +++ b/kernel/model/attribute_view.go @@ -18,6 +18,7 @@ package model import ( "bytes" + "fmt" "os" "path/filepath" "sort" @@ -398,7 +399,7 @@ func GetBlockAttributeViewKeys(blockID string) (ret []*BlockAttributeViewKeys) { keyValues = append(keyValues, kValues) } else { // 如果没有值,那么就补一个默认值 - kValues.Values = append(kValues.Values, treenode.GetAttributeViewDefaultValue(ast.NewNodeID(), kv.Key.ID, blockID, kv.Key.Type)) + kValues.Values = append(kValues.Values, av.GetAttributeViewDefaultValue(ast.NewNodeID(), kv.Key.ID, blockID, kv.Key.Type)) keyValues = append(keyValues, kValues) } } @@ -426,7 +427,7 @@ func GetBlockAttributeViewKeys(blockID string) (ret []*BlockAttributeViewKeys) { destVal := destAv.GetValue(kv.Key.Rollup.KeyID, bID) if nil == destVal { if destAv.ExistBlock(bID) { // 数据库中存在行但是列值不存在是数据未初始化,这里补一个默认值 - destVal = treenode.GetAttributeViewDefaultValue(ast.NewNodeID(), kv.Key.Rollup.KeyID, bID, destKey.Type) + destVal = av.GetAttributeViewDefaultValue(ast.NewNodeID(), kv.Key.Rollup.KeyID, bID, destKey.Type) } if nil == destVal { continue @@ -499,6 +500,7 @@ func GetBlockAttributeViewKeys(blockID string) (ret []*BlockAttributeViewKeys) { //} // 渲染模板 + var renderTemplateErr error for _, kv := range keyValues { switch kv.Key.Type { case av.KeyTypeTemplate: @@ -509,10 +511,17 @@ func GetBlockAttributeViewKeys(blockID string) (ret []*BlockAttributeViewKeys) { ial = GetBlockAttrsWithoutWaitWriting(block.BlockID) } - kv.Values[0].Template.Content = renderTemplateCol(ial, flashcard, keyValues, kv.Key.Template) + var renderErr error + kv.Values[0].Template.Content, renderErr = renderTemplateCol(ial, flashcard, keyValues, kv.Key.Template) + if nil != renderErr { + renderTemplateErr = renderErr + } } } } + if nil != renderTemplateErr { + util.PushErrMsg(fmt.Sprintf(Conf.Language(44), util.EscapeHTML(renderTemplateErr.Error())), 30000) + } // Attribute Panel - Database sort attributes by view column order https://github.com/siyuan-note/siyuan/issues/9319 viewID := attrs[av.NodeAttrView] @@ -839,7 +848,7 @@ func renderAttributeView(attrView *av.AttributeView, viewID, query string, page, return } -func renderTemplateCol(ial map[string]string, flashcard *Flashcard, rowValues []*av.KeyValues, tplContent string) string { +func renderTemplateCol(ial map[string]string, flashcard *Flashcard, rowValues []*av.KeyValues, tplContent string) (ret string, err error) { if "" == ial["id"] { block := getRowBlockValue(rowValues) if nil != block && nil != block.Block { @@ -857,10 +866,10 @@ func renderTemplateCol(ial map[string]string, flashcard *Flashcard, rowValues [] tplFuncMap := util.BuiltInTemplateFuncs() SQLTemplateFuncs(&tplFuncMap) goTpl = goTpl.Funcs(tplFuncMap) - tpl, tplErr := goTpl.Parse(tplContent) - if nil != tplErr { - logging.LogWarnf("parse template [%s] failed: %s", tplContent, tplErr) - return "" + tpl, err := goTpl.Parse(tplContent) + if nil != err { + logging.LogWarnf("parse template [%s] failed: %s", tplContent, err) + return } buf := &bytes.Buffer{} @@ -943,10 +952,12 @@ func renderTemplateCol(ial map[string]string, flashcard *Flashcard, rowValues [] } } - if err := tpl.Execute(buf, dataModel); nil != err { + if err = tpl.Execute(buf, dataModel); nil != err { logging.LogWarnf("execute template [%s] failed: %s", tplContent, err) + return } - return buf.String() + ret = buf.String() + return } func renderAttributeViewTable(attrView *av.AttributeView, view *av.View, query string) (ret *av.Table, err error) { @@ -1118,7 +1129,7 @@ func renderAttributeViewTable(attrView *av.AttributeView, view *av.View, query s destVal := destAv.GetValue(rollupKey.Rollup.KeyID, blockID) if nil == destVal { if destAv.ExistBlock(blockID) { // 数据库中存在行但是列值不存在是数据未初始化,这里补一个默认值 - destVal = treenode.GetAttributeViewDefaultValue(ast.NewNodeID(), rollupKey.Rollup.KeyID, blockID, destKey.Type) + destVal = av.GetAttributeViewDefaultValue(ast.NewNodeID(), rollupKey.Rollup.KeyID, blockID, destKey.Type) } if nil == destVal { continue @@ -1219,6 +1230,7 @@ func renderAttributeViewTable(attrView *av.AttributeView, view *av.View, query s // } //} + var renderTemplateErr error for _, row := range ret.Rows { for _, cell := range row.Cells { switch cell.ValueType { @@ -1229,11 +1241,17 @@ func renderAttributeViewTable(attrView *av.AttributeView, view *av.View, query s if nil != block && !block.IsDetached { ial = GetBlockAttrsWithoutWaitWriting(row.ID) } - content := renderTemplateCol(ial, flashcards[row.ID], keyValues, cell.Value.Template.Content) + content, renderErr := renderTemplateCol(ial, flashcards[row.ID], keyValues, cell.Value.Template.Content) cell.Value.Template.Content = content + if nil != renderErr { + renderTemplateErr = renderErr + } } } } + if nil != renderTemplateErr { + util.PushErrMsg(fmt.Sprintf(Conf.Language(44), util.EscapeHTML(renderTemplateErr.Error())), 30000) + } // 根据搜索条件过滤 query = strings.TrimSpace(query) diff --git a/kernel/treenode/node.go b/kernel/treenode/node.go index 9829087c6..5fbc14ce1 100644 --- a/kernel/treenode/node.go +++ b/kernel/treenode/node.go @@ -765,7 +765,7 @@ func renderAttributeViewTable(attrView *av.AttributeView, view *av.View) (ret *a destVal := destAv.GetValue(rollupKey.Rollup.KeyID, blockID) if nil == destVal { if destAv.ExistBlock(blockID) { // 数据库中存在行但是列值不存在是数据未初始化,这里补一个默认值 - destVal = GetAttributeViewDefaultValue(ast.NewNodeID(), rollupKey.Rollup.KeyID, blockID, destKey.Type) + destVal = av.GetAttributeViewDefaultValue(ast.NewNodeID(), rollupKey.Rollup.KeyID, blockID, destKey.Type) } if nil == destVal { continue @@ -870,7 +870,7 @@ func renderAttributeViewTable(attrView *av.AttributeView, view *av.View) (ret *a func FillAttributeViewTableCellNilValue(tableCell *av.TableCell, rowID, colID string) { if nil == tableCell.Value { - tableCell.Value = GetAttributeViewDefaultValue(tableCell.ID, colID, rowID, tableCell.ValueType) + tableCell.Value = av.GetAttributeViewDefaultValue(tableCell.ID, colID, rowID, tableCell.ValueType) return } @@ -939,59 +939,6 @@ func FillAttributeViewTableCellNilValue(tableCell *av.TableCell, rowID, colID st } } -func GetAttributeViewDefaultValue(valueID, keyID, blockID string, typ av.KeyType) (ret *av.Value) { - if "" == valueID { - valueID = ast.NewNodeID() - } - - ret = &av.Value{ID: valueID, KeyID: keyID, BlockID: blockID, Type: typ} - - createdStr := valueID[:len("20060102150405")] - created, parseErr := time.ParseInLocation("20060102150405", createdStr, time.Local) - if nil == parseErr { - ret.CreatedAt = created.UnixMilli() - } else { - ret.CreatedAt = time.Now().UnixMilli() - } - if 0 == ret.UpdatedAt { - ret.UpdatedAt = ret.CreatedAt - } - - switch typ { - case av.KeyTypeText: - ret.Text = &av.ValueText{} - case av.KeyTypeNumber: - ret.Number = &av.ValueNumber{} - case av.KeyTypeDate: - ret.Date = &av.ValueDate{} - case av.KeyTypeSelect: - ret.MSelect = []*av.ValueSelect{} - case av.KeyTypeMSelect: - ret.MSelect = []*av.ValueSelect{} - case av.KeyTypeURL: - ret.URL = &av.ValueURL{} - case av.KeyTypeEmail: - ret.Email = &av.ValueEmail{} - case av.KeyTypePhone: - ret.Phone = &av.ValuePhone{} - case av.KeyTypeMAsset: - ret.MAsset = []*av.ValueAsset{} - case av.KeyTypeTemplate: - ret.Template = &av.ValueTemplate{} - case av.KeyTypeCreated: - ret.Created = &av.ValueCreated{} - case av.KeyTypeUpdated: - ret.Updated = &av.ValueUpdated{} - case av.KeyTypeCheckbox: - ret.Checkbox = &av.ValueCheckbox{} - case av.KeyTypeRelation: - ret.Relation = &av.ValueRelation{} - case av.KeyTypeRollup: - ret.Rollup = &av.ValueRollup{} - } - return -} - func renderTemplateCol(ial map[string]string, rowValues []*av.KeyValues, tplContent string) string { if "" == ial["id"] { block := getRowBlockValue(rowValues)