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

This commit is contained in:
Vanessa 2025-07-02 17:20:02 +08:00
commit 68943ed5d5
10 changed files with 99 additions and 190 deletions

View file

@ -190,6 +190,7 @@ type View struct {
LayoutType LayoutType `json:"type"` // 当前布局类型
Table *LayoutTable `json:"table,omitempty"` // 表格布局
Gallery *LayoutGallery `json:"gallery,omitempty"` // 画廊布局
ItemIDs []string `json:"itemIds,omitempty"` // 项目 ID 列表,用于维护所有项目
Groups []*View `json:"groups,omitempty"` // 分组视图列表
GroupItemIDs []string `json:"groupItemIds,omitempty"` // 分组项目 ID 列表,用于维护分组中的所有项目
@ -276,7 +277,7 @@ type Viewable interface {
func NewAttributeView(id string) (ret *AttributeView) {
view, blockKey, selectKey := NewTableViewWithBlockKey(ast.NewNodeID())
ret = &AttributeView{
Spec: 2,
Spec: 3,
ID: id,
KeyValues: []*KeyValues{{Key: blockKey}, {Key: selectKey}},
ViewID: view.ID,
@ -418,14 +419,8 @@ func SaveAttributeView(av *AttributeView) (err error) {
// 视图值去重
for _, view := range av.Views {
if nil != view.Table {
// 行去重
view.Table.RowIDs = gulu.Str.RemoveDuplicatedElem(view.Table.RowIDs)
}
if nil != view.Gallery {
// 行去重
view.Gallery.CardIDs = gulu.Str.RemoveDuplicatedElem(view.Gallery.CardIDs)
}
// 项目自定义排序去重
view.ItemIDs = gulu.Str.RemoveDuplicatedElem(view.ItemIDs)
// 分页大小
if 1 > view.PageSize {
@ -614,14 +609,13 @@ func (av *AttributeView) Clone() (ret *AttributeView) {
for _, column := range view.Table.Columns {
column.ID = keyIDMap[column.ID]
}
view.Table.RowIDs = []string{}
case LayoutTypeGallery:
view.Gallery.ID = ast.NewNodeID()
for _, cardField := range view.Gallery.CardFields {
cardField.ID = keyIDMap[cardField.ID]
}
view.Gallery.CardIDs = []string{}
}
view.ItemIDs = []string{}
}
ret.ViewID = ret.Views[0].ID

View file

@ -27,6 +27,33 @@ import (
func UpgradeSpec(av *AttributeView) {
upgradeSpec1(av)
upgradeSpec2(av)
upgradeSpec3(av)
}
func upgradeSpec3(av *AttributeView) {
if 3 <= av.Spec {
return
}
// 将 view.table.rowIds 或 view.gallery.cardIds 复制到 view.itemIds
for _, view := range av.Views {
if 0 < len(view.ItemIDs) {
continue
}
switch view.LayoutType {
case LayoutTypeTable:
if nil != view.Table {
view.ItemIDs = view.Table.RowIDs
}
case LayoutTypeGallery:
if nil != view.Gallery {
view.ItemIDs = view.Gallery.CardIDs
}
}
}
av.Spec = 3
}
func upgradeSpec2(av *AttributeView) {
@ -78,7 +105,6 @@ func upgradeSpec2(av *AttributeView) {
}
av.Spec = 2
logging.LogInfof("av [%s] upgraded to spec [%d]", av.ID, av.Spec)
}
func upgradeSpec1(av *AttributeView) {
@ -211,5 +237,4 @@ func upgradeSpec1(av *AttributeView) {
}
av.Spec = 1
logging.LogInfof("av [%s] upgraded to spec [%d]", av.ID, av.Spec)
}

View file

@ -110,13 +110,6 @@ func (baseInstanceField *BaseInstanceField) GetID() string {
return baseInstanceField.ID
}
// CollectionLayout 描述了集合布局的接口。
type CollectionLayout interface {
// GetItemIDs 返回集合中所有项目的 ID。
GetItemIDs() []string
}
// Collection 描述了一个集合的接口。
// 集合可以是表格、画廊等,包含多个项目。
type Collection interface {

View file

@ -30,12 +30,11 @@ type LayoutGallery struct {
CardSize CardSize `json:"cardSize"` // 卡片大小0小卡片1中卡片2大卡片
FitImage bool `json:"fitImage"` // 是否适应封面图片大小
CardFields []*ViewGalleryCardField `json:"fields"` // 画廊卡片字段
CardIDs []string `json:"cardIds"` // 卡片 ID用于自定义排序
}
CardFields []*ViewGalleryCardField `json:"fields"` // 画廊卡片字段
func (layoutGallery *LayoutGallery) GetItemIDs() (ret []string) {
return layoutGallery.CardIDs
// TODO CardIDs 字段已经废弃,计划于 2026 年 6 月 30 日后删除 https://github.com/siyuan-note/siyuan/issues/15194
//Deprecated
CardIDs []string `json:"cardIds"` // 卡片 ID用于自定义排序
}
func NewLayoutGallery() *LayoutGallery {

View file

@ -25,11 +25,10 @@ type LayoutTable struct {
*BaseLayout
Columns []*ViewTableColumn `json:"columns"` // 表格列
RowIDs []string `json:"rowIds"` // 行 ID用于自定义排序
}
func (layoutTable *LayoutTable) GetItemIDs() (ret []string) {
return layoutTable.RowIDs
// TODO RowIDs 字段已经废弃,计划于 2026 年 6 月 30 日后删除 https://github.com/siyuan-note/siyuan/issues/15194
//Deprecated
RowIDs []string `json:"rowIds"` // 行 ID用于自定义排序
}
func NewLayoutTable() *LayoutTable {

View file

@ -175,9 +175,6 @@ func ChangeAttrViewLayout(blockID, avID string, layout av.LayoutType) (err error
for _, field := range view.Gallery.CardFields {
view.Table.Columns = append(view.Table.Columns, &av.ViewTableColumn{BaseField: &av.BaseField{ID: field.ID}})
}
for _, cardID := range view.Gallery.CardIDs {
view.Table.RowIDs = append(view.Table.RowIDs, cardID)
}
}
case av.LayoutTypeGallery:
if view.Name == av.GetAttributeViewI18n("table") {
@ -194,9 +191,6 @@ func ChangeAttrViewLayout(blockID, avID string, layout av.LayoutType) (err error
for _, col := range view.Table.Columns {
view.Gallery.CardFields = append(view.Gallery.CardFields, &av.ViewGalleryCardField{BaseField: &av.BaseField{ID: col.ID}})
}
for _, rowID := range view.Table.RowIDs {
view.Gallery.CardIDs = append(view.Gallery.CardIDs, rowID)
}
}
}
@ -469,15 +463,8 @@ func AppendAttributeViewDetachedBlocksWithValues(avID string, blocksValues [][]*
}
for _, v := range attrView.Views {
switch v.LayoutType {
case av.LayoutTypeTable:
for _, addingBlockID := range blockIDs {
v.Table.RowIDs = append(v.Table.RowIDs, addingBlockID)
}
case av.LayoutTypeGallery:
for _, addingBlockID := range blockIDs {
v.Gallery.CardIDs = append(v.Gallery.CardIDs, addingBlockID)
}
for _, addingBlockID := range blockIDs {
v.ItemIDs = append(v.ItemIDs, addingBlockID)
}
}
@ -1441,31 +1428,16 @@ func unbindAttributeViewBlock(operation *Operation, tx *Transaction) (err error)
replacedRowID := false
for _, v := range attrView.Views {
switch v.LayoutType {
case av.LayoutTypeTable:
for i, rowID := range v.Table.RowIDs {
if rowID == operation.ID {
v.Table.RowIDs[i] = operation.NextID
replacedRowID = true
break
}
for i, itemID := range v.ItemIDs {
if itemID == operation.ID {
v.ItemIDs[i] = operation.NextID
replacedRowID = true
break
}
}
if !replacedRowID {
v.Table.RowIDs = append(v.Table.RowIDs, operation.NextID)
}
case av.LayoutTypeGallery:
for i, cardID := range v.Gallery.CardIDs {
if cardID == operation.ID {
v.Gallery.CardIDs[i] = operation.NextID
replacedRowID = true
break
}
}
if !replacedRowID {
v.Gallery.CardIDs = append(v.Gallery.CardIDs, operation.NextID)
}
if !replacedRowID {
v.ItemIDs = append(v.ItemIDs, operation.NextID)
}
}
@ -1977,7 +1949,6 @@ func (tx *Transaction) doDuplicateAttrViewView(operation *Operation) (ret *TxErr
})
}
view.Table.RowIDs = masterView.Table.RowIDs
view.Table.ShowIcon = masterView.Table.ShowIcon
view.Table.WrapField = masterView.Table.WrapField
case av.LayoutTypeGallery:
@ -1992,7 +1963,6 @@ func (tx *Transaction) doDuplicateAttrViewView(operation *Operation) (ret *TxErr
})
}
view.Gallery.CardIDs = masterView.Gallery.CardIDs
view.Gallery.CoverFrom = masterView.Gallery.CoverFrom
view.Gallery.CoverFromAssetKeyID = masterView.Gallery.CoverFromAssetKeyID
view.Gallery.CardSize = masterView.Gallery.CardSize
@ -2001,6 +1971,8 @@ func (tx *Transaction) doDuplicateAttrViewView(operation *Operation) (ret *TxErr
view.Gallery.WrapField = masterView.Gallery.WrapField
}
view.ItemIDs = masterView.ItemIDs
if err = av.SaveAttributeView(attrView); err != nil {
logging.LogErrorf("save attribute view [%s] failed: %s", avID, err)
return &TxErr{code: TxErrWriteAttributeView, msg: err.Error(), id: avID}
@ -2047,16 +2019,10 @@ func addAttrViewView(avID, viewID, blockID string, layout av.LayoutType) (err er
for _, col := range firstView.Table.Columns {
view.Table.Columns = append(view.Table.Columns, &av.ViewTableColumn{BaseField: &av.BaseField{ID: col.ID}})
}
for _, rowID := range firstView.Table.RowIDs {
view.Table.RowIDs = append(view.Table.RowIDs, rowID)
}
case av.LayoutTypeGallery:
for _, field := range firstView.Gallery.CardFields {
view.Table.Columns = append(view.Table.Columns, &av.ViewTableColumn{BaseField: &av.BaseField{ID: field.ID}})
}
for _, cardID := range firstView.Gallery.CardIDs {
view.Table.RowIDs = append(view.Table.RowIDs, cardID)
}
}
case av.LayoutTypeGallery:
view = av.NewGalleryView()
@ -2065,16 +2031,10 @@ func addAttrViewView(avID, viewID, blockID string, layout av.LayoutType) (err er
for _, col := range firstView.Table.Columns {
view.Gallery.CardFields = append(view.Gallery.CardFields, &av.ViewGalleryCardField{BaseField: &av.BaseField{ID: col.ID}})
}
for _, rowID := range firstView.Table.RowIDs {
view.Gallery.CardIDs = append(view.Gallery.CardIDs, rowID)
}
case av.LayoutTypeGallery:
for _, field := range firstView.Gallery.CardFields {
view.Gallery.CardFields = append(view.Gallery.CardFields, &av.ViewGalleryCardField{BaseField: &av.BaseField{ID: field.ID}})
}
for _, cardID := range firstView.Gallery.CardIDs {
view.Gallery.CardIDs = append(view.Gallery.CardIDs, cardID)
}
}
default:
err = av.ErrWrongLayoutType
@ -2082,6 +2042,7 @@ func addAttrViewView(avID, viewID, blockID string, layout av.LayoutType) (err er
return
}
view.ItemIDs = firstView.ItemIDs
attrView.ViewID = viewID
view.ID = viewID
attrView.Views = append(attrView.Views, view)
@ -2599,39 +2560,20 @@ func addAttributeViewBlock(now int64, avID, blockID, previousBlockID, addingBloc
}
for _, v := range attrView.Views {
switch v.LayoutType {
case av.LayoutTypeTable:
if "" != previousBlockID {
changed := false
for i, id := range v.Table.RowIDs {
if id == previousBlockID {
v.Table.RowIDs = append(v.Table.RowIDs[:i+1], append([]string{addingBlockID}, v.Table.RowIDs[i+1:]...)...)
changed = true
break
}
if "" != previousBlockID {
changed := false
for i, id := range v.ItemIDs {
if id == previousBlockID {
v.ItemIDs = append(v.ItemIDs[:i+1], append([]string{addingBlockID}, v.ItemIDs[i+1:]...)...)
changed = true
break
}
if !changed {
v.Table.RowIDs = append(v.Table.RowIDs, addingBlockID)
}
} else {
v.Table.RowIDs = append([]string{addingBlockID}, v.Table.RowIDs...)
}
case av.LayoutTypeGallery:
if "" != previousBlockID {
changed := false
for i, id := range v.Gallery.CardIDs {
if id == previousBlockID {
v.Gallery.CardIDs = append(v.Gallery.CardIDs[:i+1], append([]string{addingBlockID}, v.Gallery.CardIDs[i+1:]...)...)
changed = true
break
}
}
if !changed {
v.Gallery.CardIDs = append(v.Gallery.CardIDs, addingBlockID)
}
} else {
v.Gallery.CardIDs = append([]string{addingBlockID}, v.Gallery.CardIDs...)
if !changed {
v.ItemIDs = append(v.ItemIDs, addingBlockID)
}
} else {
v.ItemIDs = append([]string{addingBlockID}, v.ItemIDs...)
}
}
@ -2688,12 +2630,7 @@ func removeAttributeViewBlock(srcIDs []string, avID string, tx *Transaction) (er
for _, view := range attrView.Views {
for _, blockID := range srcIDs {
switch view.LayoutType {
case av.LayoutTypeTable:
view.Table.RowIDs = gulu.Str.RemoveElem(view.Table.RowIDs, blockID)
case av.LayoutTypeGallery:
view.Gallery.CardIDs = gulu.Str.RemoveElem(view.Gallery.CardIDs, blockID)
}
view.ItemIDs = gulu.Str.RemoveElem(view.ItemIDs, blockID)
}
}
@ -3082,51 +3019,27 @@ func sortAttributeViewRow(operation *Operation) (err error) {
var itemID string
var idx, previousIndex int
switch view.LayoutType {
case av.LayoutTypeTable:
for i, r := range view.Table.RowIDs {
if r == operation.ID {
itemID = r
idx = i
break
}
for i, id := range view.ItemIDs {
if id == operation.ID {
itemID = id
idx = i
break
}
if "" == itemID {
itemID = operation.ID
view.Table.RowIDs = append(view.Table.RowIDs, itemID)
idx = len(view.Table.RowIDs) - 1
}
view.Table.RowIDs = append(view.Table.RowIDs[:idx], view.Table.RowIDs[idx+1:]...)
for i, r := range view.Table.RowIDs {
if r == operation.PreviousID {
previousIndex = i + 1
break
}
}
view.Table.RowIDs = util.InsertElem(view.Table.RowIDs, previousIndex, itemID)
case av.LayoutTypeGallery:
for i, c := range view.Gallery.CardIDs {
if c == operation.ID {
itemID = c
idx = i
break
}
}
if "" == itemID {
itemID = operation.ID
view.Gallery.CardIDs = append(view.Gallery.CardIDs, itemID)
idx = len(view.Gallery.CardIDs) - 1
}
view.Gallery.CardIDs = append(view.Gallery.CardIDs[:idx], view.Gallery.CardIDs[idx+1:]...)
for i, c := range view.Gallery.CardIDs {
if c == operation.PreviousID {
previousIndex = i + 1
break
}
}
view.Gallery.CardIDs = util.InsertElem(view.Gallery.CardIDs, previousIndex, itemID)
}
if "" == itemID {
itemID = operation.ID
view.ItemIDs = append(view.ItemIDs, itemID)
idx = len(view.ItemIDs) - 1
}
view.ItemIDs = append(view.ItemIDs[:idx], view.ItemIDs[idx+1:]...)
for i, r := range view.ItemIDs {
if r == operation.PreviousID {
previousIndex = i + 1
break
}
}
view.ItemIDs = util.InsertElem(view.ItemIDs, previousIndex, itemID)
err = av.SaveAttributeView(attrView)
return
@ -3664,27 +3577,16 @@ func replaceAttributeViewBlock(operation *Operation, tx *Transaction) (err error
replacedRowID := false
for _, v := range attrView.Views {
switch v.LayoutType {
case av.LayoutTypeTable:
for i, rowID := range v.Table.RowIDs {
if rowID == operation.PreviousID {
v.Table.RowIDs[i] = operation.NextID
replacedRowID = true
break
}
for i, itemID := range v.ItemIDs {
if itemID == operation.PreviousID {
v.ItemIDs[i] = operation.NextID
replacedRowID = true
break
}
}
if !replacedRowID {
v.Table.RowIDs = append(v.Table.RowIDs, operation.NextID)
}
case av.LayoutTypeGallery:
for i, cardID := range v.Gallery.CardIDs {
if cardID == operation.PreviousID {
v.Gallery.CardIDs[i] = operation.NextID
replacedRowID = true
break
}
}
if !replacedRowID {
v.ItemIDs = append(v.ItemIDs, operation.NextID)
}
}

View file

@ -3405,9 +3405,6 @@ func getAttrViewTable(attrView *av.AttributeView, view *av.View, query string) (
for _, field := range view.Gallery.CardFields {
view.Table.Columns = append(view.Table.Columns, &av.ViewTableColumn{BaseField: &av.BaseField{ID: field.ID}})
}
for _, cardID := range view.Gallery.CardIDs {
view.Table.RowIDs = append(view.Table.RowIDs, cardID)
}
}
ret = sql.RenderAttributeViewTable(attrView, view, query)
return

View file

@ -619,16 +619,16 @@ func filterByQuery(query string, collection av.Collection) {
}
// manualSort 处理用户手动排序。
func manualSort(collectionLayout av.CollectionLayout, collection av.Collection) {
sortRowIDs := map[string]int{}
for i, itemID := range collectionLayout.GetItemIDs() {
sortRowIDs[itemID] = i
func manualSort(view *av.View, collection av.Collection) {
sortItemIDs := map[string]int{}
for i, itemID := range view.ItemIDs {
sortItemIDs[itemID] = i
}
items := collection.GetItems()
sort.Slice(items, func(i, j int) bool {
iv := sortRowIDs[items[i].GetID()]
jv := sortRowIDs[items[j].GetID()]
iv := sortItemIDs[items[i].GetID()]
jv := sortItemIDs[items[j].GetID()]
if iv == jv {
return items[i].GetID() < items[j].GetID()
}

View file

@ -143,7 +143,7 @@ func RenderAttributeViewGallery(attrView *av.AttributeView, view *av.View, query
}
filterByQuery(query, ret)
manualSort(view.Gallery, ret)
manualSort(view, ret)
return
}

View file

@ -142,6 +142,6 @@ func RenderAttributeViewTable(attrView *av.AttributeView, view *av.View, query s
}
filterByQuery(query, ret)
manualSort(view.Table, ret)
manualSort(view, ret)
return
}