Merge remote-tracking branch 'origin/dev' into dev

This commit is contained in:
Vanessa 2025-06-11 11:59:55 +08:00
commit 7fc499341f
3 changed files with 131 additions and 179 deletions

View file

@ -25,6 +25,7 @@ import (
"github.com/siyuan-note/logging"
"github.com/siyuan-note/siyuan/kernel/av"
"github.com/siyuan-note/siyuan/kernel/filesys"
"github.com/siyuan-note/siyuan/kernel/treenode"
"github.com/siyuan-note/siyuan/kernel/util"
)
@ -173,6 +174,80 @@ func RenderTemplateField(ial map[string]string, keyValues []*av.KeyValues, tplCo
return
}
func generateAttrViewItems(attrView *av.AttributeView) (ret map[string][]*av.KeyValues) {
ret = map[string][]*av.KeyValues{}
for _, keyValues := range attrView.KeyValues {
for _, val := range keyValues.Values {
values := ret[val.BlockID]
if nil == values {
values = []*av.KeyValues{{Key: keyValues.Key, Values: []*av.Value{val}}}
} else {
values = append(values, &av.KeyValues{Key: keyValues.Key, Values: []*av.Value{val}})
}
ret[val.BlockID] = values
}
}
return
}
func filterNotFoundAttrViewItems(keyValuesMap *map[string][]*av.KeyValues) {
var notFound []string
var toCheckBlockIDs []string
for blockID, keyValues := range *keyValuesMap {
blockValue := getBlockValue(keyValues)
if nil == blockValue {
notFound = append(notFound, blockID)
continue
}
if blockValue.IsDetached {
continue
}
if nil != blockValue.Block && "" == blockValue.Block.ID {
notFound = append(notFound, blockID)
continue
}
toCheckBlockIDs = append(toCheckBlockIDs, blockID)
}
checkRet := treenode.ExistBlockTrees(toCheckBlockIDs)
for blockID, exist := range checkRet {
if !exist {
notFound = append(notFound, blockID)
}
}
for _, blockID := range notFound {
delete(*keyValuesMap, blockID)
}
}
func fillAttributeViewBaseValue(baseValue *av.BaseValue, fieldID, itemID string, fieldNumberFormat av.NumberFormat, fieldTemplate string) {
switch baseValue.ValueType {
case av.KeyTypeNumber: // 格式化数字
if nil != baseValue.Value && nil != baseValue.Value.Number && baseValue.Value.Number.IsNotEmpty {
baseValue.Value.Number.Format = fieldNumberFormat
baseValue.Value.Number.FormatNumber()
}
case av.KeyTypeTemplate: // 渲染模板字段
baseValue.Value = &av.Value{ID: baseValue.ID, KeyID: fieldID, BlockID: itemID, Type: av.KeyTypeTemplate, Template: &av.ValueTemplate{Content: fieldTemplate}}
case av.KeyTypeCreated: // 填充创建时间字段值,后面再渲染
baseValue.Value = &av.Value{ID: baseValue.ID, KeyID: fieldID, BlockID: itemID, Type: av.KeyTypeCreated}
case av.KeyTypeUpdated: // 填充更新时间字段值,后面再渲染
baseValue.Value = &av.Value{ID: baseValue.ID, KeyID: fieldID, BlockID: itemID, Type: av.KeyTypeUpdated}
case av.KeyTypeRelation: // 清空关联字段值,后面再渲染 https://ld246.com/article/1703831044435
if nil != baseValue.Value && nil != baseValue.Value.Relation {
baseValue.Value.Relation.Contents = nil
}
}
if nil == baseValue.Value {
baseValue.Value = av.GetAttributeViewDefaultValue(baseValue.ID, fieldID, itemID, baseValue.ValueType)
} else {
fillAttributeViewNilValue(baseValue.Value, baseValue.ValueType)
}
}
func fillAttributeViewNilValue(value *av.Value, typ av.KeyType) {
value.Type = typ
switch typ {

View file

@ -64,50 +64,8 @@ func RenderAttributeViewGallery(attrView *av.AttributeView, view *av.View, query
})
}
// 生成卡片
cardsValues := map[string][]*av.KeyValues{}
for _, keyValues := range attrView.KeyValues {
for _, val := range keyValues.Values {
values := cardsValues[val.BlockID]
if nil == values {
values = []*av.KeyValues{{Key: keyValues.Key, Values: []*av.Value{val}}}
} else {
values = append(values, &av.KeyValues{Key: keyValues.Key, Values: []*av.Value{val}})
}
cardsValues[val.BlockID] = values
}
}
// 过滤掉不存在的卡片
var notFound []string
var toCheckBlockIDs []string
for blockID, keyValues := range cardsValues {
blockValue := getBlockValue(keyValues)
if nil == blockValue {
notFound = append(notFound, blockID)
continue
}
if blockValue.IsDetached {
continue
}
if nil != blockValue.Block && "" == blockValue.Block.ID {
notFound = append(notFound, blockID)
continue
}
toCheckBlockIDs = append(toCheckBlockIDs, blockID)
}
checkRet := treenode.ExistBlockTrees(toCheckBlockIDs)
for blockID, exist := range checkRet {
if !exist {
notFound = append(notFound, blockID)
}
}
for _, blockID := range notFound {
delete(cardsValues, blockID)
}
cardsValues := generateAttrViewItems(attrView) // 生成卡片
filterNotFoundAttrViewItems(&cardsValues) // 过滤掉不存在的卡片
// 生成卡片字段值
for cardID, cardValues := range cardsValues {
@ -136,30 +94,7 @@ func RenderAttributeViewGallery(attrView *av.AttributeView, view *av.View, query
}
galleryCard.ID = cardID
switch fieldValue.ValueType {
case av.KeyTypeNumber: // 格式化数字
if nil != fieldValue.Value && nil != fieldValue.Value.Number && fieldValue.Value.Number.IsNotEmpty {
fieldValue.Value.Number.Format = field.NumberFormat
fieldValue.Value.Number.FormatNumber()
}
case av.KeyTypeTemplate: // 渲染模板字段
fieldValue.Value = &av.Value{ID: fieldValue.ID, KeyID: field.ID, BlockID: cardID, Type: av.KeyTypeTemplate, Template: &av.ValueTemplate{Content: field.Template}}
case av.KeyTypeCreated: // 填充创建时间字段值,后面再渲染
fieldValue.Value = &av.Value{ID: fieldValue.ID, KeyID: field.ID, BlockID: cardID, Type: av.KeyTypeCreated}
case av.KeyTypeUpdated: // 填充更新时间字段值,后面再渲染
fieldValue.Value = &av.Value{ID: fieldValue.ID, KeyID: field.ID, BlockID: cardID, Type: av.KeyTypeUpdated}
case av.KeyTypeRelation: // 清空关联字段值,后面再渲染 https://ld246.com/article/1703831044435
if nil != fieldValue.Value && nil != fieldValue.Value.Relation {
fieldValue.Value.Relation.Contents = nil
}
}
if nil == fieldValue.Value {
fieldValue.Value = av.GetAttributeViewDefaultValue(fieldValue.ID, field.ID, cardID, fieldValue.ValueType)
} else {
fillAttributeViewNilValue(fieldValue.Value, fieldValue.ValueType)
}
fillAttributeViewBaseValue(fieldValue.BaseValue, field.ID, cardID, field.NumberFormat, field.Template)
galleryCard.Values = append(galleryCard.Values, fieldValue)
}
@ -406,55 +341,62 @@ func fillGalleryCardCover(attrView *av.AttributeView, view *av.View, cardValues
case av.CoverFromNone:
case av.CoverFromContentImage:
blockValue := getBlockValue(cardValues)
if !blockValue.IsDetached {
tree := loadTreeByBlockID(blockValue.BlockID)
if nil == tree {
break
}
node := treenode.GetNodeInTree(tree, blockValue.BlockID)
if nil == node {
if blockValue.IsDetached {
break
}
tree := loadTreeByBlockID(blockValue.BlockID)
if nil == tree {
break
}
node := treenode.GetNodeInTree(tree, blockValue.BlockID)
if nil == node {
break
}
if ast.NodeDocument == node.Type {
if titleImg := treenode.GetDocTitleImgPath(node); "" != titleImg {
galleryCard.CoverURL = titleImg
break
}
if titleImgCss := node.IALAttr("title-img"); strings.HasPrefix(titleImgCss, "background:") {
galleryCard.CoverURL = titleImgCss
break
}
}
ast.Walk(node, func(n *ast.Node, entering bool) ast.WalkStatus {
if !entering {
return ast.WalkContinue
}
if ast.NodeImage != n.Type {
return ast.WalkContinue
}
dest := n.ChildByType(ast.NodeLinkDest)
if nil == dest {
return ast.WalkContinue
}
galleryCard.CoverURL = dest.TokensStr()
return ast.WalkStop
})
if "" == galleryCard.CoverURL {
if ast.NodeDocument == node.Type {
if titleImg := treenode.GetDocTitleImgPath(node); "" != titleImg {
galleryCard.CoverURL = titleImg
node = node.FirstChild
}
buf := bytes.Buffer{}
for c := node; nil != c; c = c.Next {
buf.WriteString(renderBlockDOMByNode(c, luteEngine))
if 1024*4 < buf.Len() {
break
}
}
ast.Walk(node, func(n *ast.Node, entering bool) ast.WalkStatus {
if !entering {
return ast.WalkContinue
}
if ast.NodeImage != n.Type {
return ast.WalkContinue
}
dest := n.ChildByType(ast.NodeLinkDest)
if nil == dest {
return ast.WalkContinue
}
galleryCard.CoverURL = dest.TokensStr()
return ast.WalkStop
})
if "" == galleryCard.CoverURL {
if ast.NodeDocument == node.Type {
node = node.FirstChild
}
buf := bytes.Buffer{}
for c := node; nil != c; c = c.Next {
buf.WriteString(renderBlockDOMByNode(c, luteEngine))
if 1024*4 < buf.Len() {
break
}
}
galleryCard.CoverContent = buf.String()
return
}
galleryCard.CoverContent = buf.String()
return
}
case av.CoverFromAssetField:
if "" == view.Gallery.CoverFromAssetKeyID {
@ -474,6 +416,7 @@ func fillGalleryCardCover(attrView *av.AttributeView, view *av.View, cardValues
func renderBlockDOMByNode(node *ast.Node, luteEngine *lute.Lute) string {
tree := &parse.Tree{Root: &ast.Node{Type: ast.NodeDocument}, Context: &parse.Context{ParseOption: luteEngine.ParseOptions}}
blockRenderer := render.NewProtyleRenderer(tree, luteEngine.RenderOptions)
blockRenderer.Options.ProtyleContenteditable = false
ast.Walk(node, func(node *ast.Node, entering bool) ast.WalkStatus {
rendererFunc := blockRenderer.RendererFuncs[node.Type]
return rendererFunc(node, entering)

View file

@ -22,7 +22,6 @@ import (
"github.com/88250/lute/ast"
"github.com/siyuan-note/siyuan/kernel/av"
"github.com/siyuan-note/siyuan/kernel/treenode"
"github.com/siyuan-note/siyuan/kernel/util"
)
@ -72,50 +71,8 @@ func RenderAttributeViewTable(attrView *av.AttributeView, view *av.View, query s
})
}
// 生成行
rowsValues := map[string][]*av.KeyValues{}
for _, keyValues := range attrView.KeyValues {
for _, val := range keyValues.Values {
values := rowsValues[val.BlockID]
if nil == values {
values = []*av.KeyValues{{Key: keyValues.Key, Values: []*av.Value{val}}}
} else {
values = append(values, &av.KeyValues{Key: keyValues.Key, Values: []*av.Value{val}})
}
rowsValues[val.BlockID] = values
}
}
// 过滤掉不存在的行
var notFound []string
var toCheckBlockIDs []string
for blockID, keyValues := range rowsValues {
blockValue := getBlockValue(keyValues)
if nil == blockValue {
notFound = append(notFound, blockID)
continue
}
if blockValue.IsDetached {
continue
}
if nil != blockValue.Block && "" == blockValue.Block.ID {
notFound = append(notFound, blockID)
continue
}
toCheckBlockIDs = append(toCheckBlockIDs, blockID)
}
checkRet := treenode.ExistBlockTrees(toCheckBlockIDs)
for blockID, exist := range checkRet {
if !exist {
notFound = append(notFound, blockID)
}
}
for _, blockID := range notFound {
delete(rowsValues, blockID)
}
rowsValues := generateAttrViewItems(attrView) // 生成行
filterNotFoundAttrViewItems(&rowsValues) // 过滤掉不存在的行
// 生成行单元格
for rowID, rowValues := range rowsValues {
@ -144,30 +101,7 @@ func RenderAttributeViewTable(attrView *av.AttributeView, view *av.View, query s
}
tableRow.ID = rowID
switch tableCell.ValueType {
case av.KeyTypeNumber: // 格式化数字
if nil != tableCell.Value && nil != tableCell.Value.Number && tableCell.Value.Number.IsNotEmpty {
tableCell.Value.Number.Format = col.NumberFormat
tableCell.Value.Number.FormatNumber()
}
case av.KeyTypeTemplate: // 渲染模板列
tableCell.Value = &av.Value{ID: tableCell.ID, KeyID: col.ID, BlockID: rowID, Type: av.KeyTypeTemplate, Template: &av.ValueTemplate{Content: col.Template}}
case av.KeyTypeCreated: // 填充创建时间列值,后面再渲染
tableCell.Value = &av.Value{ID: tableCell.ID, KeyID: col.ID, BlockID: rowID, Type: av.KeyTypeCreated}
case av.KeyTypeUpdated: // 填充更新时间列值,后面再渲染
tableCell.Value = &av.Value{ID: tableCell.ID, KeyID: col.ID, BlockID: rowID, Type: av.KeyTypeUpdated}
case av.KeyTypeRelation: // 清空关联列值,后面再渲染 https://ld246.com/article/1703831044435
if nil != tableCell.Value && nil != tableCell.Value.Relation {
tableCell.Value.Relation.Contents = nil
}
}
if nil == tableCell.Value {
tableCell.Value = av.GetAttributeViewDefaultValue(tableCell.ID, col.ID, rowID, tableCell.ValueType)
} else {
fillAttributeViewNilValue(tableCell.Value, tableCell.ValueType)
}
fillAttributeViewBaseValue(tableCell.BaseValue, col.ID, rowID, col.NumberFormat, col.Template)
tableRow.Cells = append(tableRow.Cells, tableCell)
}
ret.Rows = append(ret.Rows, &tableRow)