diff --git a/kernel/api/av.go b/kernel/api/av.go index 53db6a8a3..54e7d24c1 100644 --- a/kernel/api/av.go +++ b/kernel/api/av.go @@ -600,14 +600,6 @@ func renderAttrView(avID, viewID, query string, page, pageSize int) (ret *gulu.R var views []map[string]interface{} for _, v := range attrView.Views { - pSize := 10 - switch v.LayoutType { - case av.LayoutTypeTable: - pSize = v.Table.PageSize - case av.LayoutTypeGallery: - pSize = v.Gallery.PageSize - } - view := map[string]interface{}{ "id": v.ID, "icon": v.Icon, @@ -615,7 +607,7 @@ func renderAttrView(avID, viewID, query string, page, pageSize int) (ret *gulu.R "desc": v.Desc, "hideAttrViewName": v.HideAttrViewName, "type": v.LayoutType, - "pageSize": pSize, + "pageSize": v.PageSize, } views = append(views, view) diff --git a/kernel/av/av.go b/kernel/av/av.go index cce658ac0..4b8ecab48 100644 --- a/kernel/av/av.go +++ b/kernel/av/av.go @@ -178,37 +178,20 @@ type SelectOption struct { // View 描述了视图的结构。 type View struct { - ID string `json:"id"` // 视图 ID - Icon string `json:"icon"` // 视图图标 - Name string `json:"name"` // 视图名称 - HideAttrViewName bool `json:"hideAttrViewName"` // 是否隐藏属性视图名称 - Desc string `json:"desc"` // 视图描述 + ID string `json:"id"` // 视图 ID + Icon string `json:"icon"` // 视图图标 + Name string `json:"name"` // 视图名称 + HideAttrViewName bool `json:"hideAttrViewName"` // 是否隐藏属性视图名称 + Desc string `json:"desc"` // 视图描述 + Filters []*ViewFilter `json:"filters"` // 过滤规则 + Sorts []*ViewSort `json:"sorts"` // 排序规则 + PageSize int `json:"pageSize"` // 每页条目数 LayoutType LayoutType `json:"type"` // 当前布局类型 Table *LayoutTable `json:"table,omitempty"` // 表格布局 Gallery *LayoutGallery `json:"gallery,omitempty"` // 画廊布局 } -func (view *View) GetFilters() (ret []*ViewFilter) { - switch view.LayoutType { - case LayoutTypeTable: - return view.Table.Filters - case LayoutTypeGallery: - return view.Gallery.Filters - } - return -} - -func (view *View) GetSorts() (ret []*ViewSort) { - switch view.LayoutType { - case LayoutTypeTable: - return view.Table.Sorts - case LayoutTypeGallery: - return view.Gallery.Sorts - } - return -} - // LayoutType 描述了视图布局类型。 type LayoutType string @@ -218,8 +201,7 @@ const ( ) const ( - TableViewDefaultPageSize = 50 // 表格视图默认分页大小 - GalleryViewDefaultPageSize = 50 // 画廊视图默认分页大小 + ViewDefaultPageSize = 50 // 视图默认分页大小 ) func NewTableView() (ret *View) { @@ -252,6 +234,9 @@ func NewGalleryView() (ret *View) { ret = &View{ ID: ast.NewNodeID(), Name: GetAttributeViewI18n("gallery"), + Filters: []*ViewFilter{}, + Sorts: []*ViewSort{}, + PageSize: ViewDefaultPageSize, LayoutType: LayoutTypeGallery, Gallery: NewLayoutGallery(), } @@ -416,18 +401,15 @@ func SaveAttributeView(av *AttributeView) (err error) { if nil != view.Table { // 行去重 view.Table.RowIDs = gulu.Str.RemoveDuplicatedElem(view.Table.RowIDs) - // 分页大小 - if 1 > view.Table.PageSize { - view.Table.PageSize = TableViewDefaultPageSize - } } if nil != view.Gallery { // 行去重 view.Gallery.CardIDs = gulu.Str.RemoveDuplicatedElem(view.Gallery.CardIDs) - // 分页大小 - if 1 > view.Gallery.PageSize { - view.Gallery.PageSize = GalleryViewDefaultPageSize - } + } + + // 分页大小 + if 1 > view.PageSize { + view.Table.PageSize = ViewDefaultPageSize } } @@ -595,31 +577,25 @@ func (av *AttributeView) Clone() (ret *AttributeView) { for _, view := range ret.Views { view.ID = ast.NewNodeID() view.Table.ID = ast.NewNodeID() + + for _, f := range view.Filters { + f.Column = keyIDMap[f.Column] + } + for _, s := range view.Sorts { + s.Column = keyIDMap[s.Column] + } + switch view.LayoutType { case LayoutTypeTable: for _, column := range view.Table.Columns { column.ID = keyIDMap[column.ID] } view.Table.RowIDs = []string{} - - for _, f := range view.Table.Filters { - f.Column = keyIDMap[f.Column] - } - for _, s := range view.Table.Sorts { - s.Column = keyIDMap[s.Column] - } case LayoutTypeGallery: for _, cardField := range view.Gallery.CardFields { cardField.ID = keyIDMap[cardField.ID] } view.Gallery.CardIDs = []string{} - - for _, f := range view.Gallery.Filters { - f.Column = keyIDMap[f.Column] - } - for _, s := range view.Gallery.Sorts { - s.Column = keyIDMap[s.Column] - } } } ret.ViewID = ret.Views[0].ID diff --git a/kernel/av/av_fix.go b/kernel/av/av_fix.go index 54f0044c1..8d0c4e40f 100644 --- a/kernel/av/av_fix.go +++ b/kernel/av/av_fix.go @@ -17,14 +17,69 @@ package av import ( + "time" + "github.com/88250/lute/ast" "github.com/siyuan-note/logging" "github.com/siyuan-note/siyuan/kernel/util" - "time" ) func UpgradeSpec(av *AttributeView) { upgradeSpec1(av) + upgradeSpec2(av) +} + +func upgradeSpec2(av *AttributeView) { + if 2 <= av.Spec { + return + } + + // 如果存在 view.table.filters/sorts/pageSize 则复制覆盖到 view.filters/sorts/pageSize 下后置空 + for _, view := range av.Views { + if 1 > len(view.Filters) { + view.Filters = []*ViewFilter{} + } + if 1 > len(view.Sorts) { + view.Sorts = []*ViewSort{} + } + if 1 > view.PageSize { + view.PageSize = ViewDefaultPageSize + } + + if nil != view.Table { + if 0 < len(view.Table.Filters) { + view.Filters = append(view.Filters, view.Table.Filters...) + view.Table.Filters = nil + } + if 0 < len(view.Table.Sorts) { + view.Sorts = append(view.Sorts, view.Table.Sorts...) + view.Table.Sorts = nil + } + if 0 < view.Table.PageSize { + view.PageSize = view.Table.PageSize + view.Table.PageSize = 0 + } + } + + // 清理过滤和排序规则中不存在的键 + tmpFilters := []*ViewFilter{} + for _, f := range view.Filters { + if k, _ := av.GetKey(f.Column); nil != k { + tmpFilters = append(tmpFilters, f) + } + } + view.Filters = tmpFilters + + tmpSorts := []*ViewSort{} + for _, s := range view.Sorts { + if k, _ := av.GetKey(s.Column); nil != k { + tmpSorts = append(tmpSorts, s) + } + } + view.Sorts = tmpSorts + } + + av.Spec = 2 } func upgradeSpec1(av *AttributeView) { diff --git a/kernel/av/layout.go b/kernel/av/layout.go index 4abde544a..01ace0680 100644 --- a/kernel/av/layout.go +++ b/kernel/av/layout.go @@ -20,11 +20,13 @@ import "sort" // BaseLayout 描述了布局的基础结构。 type BaseLayout struct { - Spec int `json:"spec"` // 布局格式版本 - ID string `json:"id"` // 布局 ID - Filters []*ViewFilter `json:"filters"` // 过滤规则 - Sorts []*ViewSort `json:"sorts"` // 排序规则 - PageSize int `json:"pageSize"` // 每页条目数 + Spec int `json:"spec"` // 布局格式版本 + ID string `json:"id"` // 布局 ID + + // 以下三个字段已经废弃,计划于 2026 年 6 月 30 日后删除 https://github.com/siyuan-note/siyuan/issues/15162 + Filters []*ViewFilter `json:"filters,omitempty"` // 过滤规则 + Sorts []*ViewSort `json:"sorts,omitempty"` // 排序规则 + PageSize int `json:"pageSize,omitempty"` // 每页条目数 } // BaseValue 描述了字段值的基础结构。 diff --git a/kernel/av/layout_gallery.go b/kernel/av/layout_gallery.go index 660e3a226..45c357866 100644 --- a/kernel/av/layout_gallery.go +++ b/kernel/av/layout_gallery.go @@ -43,11 +43,8 @@ func (layoutGallery *LayoutGallery) GetItemIDs() (ret []string) { func NewLayoutGallery() *LayoutGallery { return &LayoutGallery{ BaseLayout: &BaseLayout{ - Spec: 0, - ID: ast.NewNodeID(), - Filters: []*ViewFilter{}, - Sorts: []*ViewSort{}, - PageSize: GalleryViewDefaultPageSize, + Spec: 0, + ID: ast.NewNodeID(), }, CoverFrom: CoverFromContentImage, CardAspectRatio: CardAspectRatio16_9, diff --git a/kernel/av/layout_table.go b/kernel/av/layout_table.go index 9c2ee3515..8fb65f3ae 100644 --- a/kernel/av/layout_table.go +++ b/kernel/av/layout_table.go @@ -35,11 +35,8 @@ func (layoutTable *LayoutTable) GetItemIDs() (ret []string) { func NewLayoutTable() *LayoutTable { return &LayoutTable{ BaseLayout: &BaseLayout{ - Spec: 0, - ID: ast.NewNodeID(), - Filters: []*ViewFilter{}, - Sorts: []*ViewSort{}, - PageSize: TableViewDefaultPageSize, + Spec: 0, + ID: ast.NewNodeID(), }, } } diff --git a/kernel/model/attribute_view.go b/kernel/model/attribute_view.go index 2954857d6..9f10dd206 100644 --- a/kernel/model/attribute_view.go +++ b/kernel/model/attribute_view.go @@ -592,16 +592,8 @@ func GetAttributeViewFilterSort(avID, blockID string) (filters []*av.ViewFilter, } } - filters = []*av.ViewFilter{} - sorts = []*av.ViewSort{} - switch view.LayoutType { - case av.LayoutTypeTable: - filters = view.Table.Filters - sorts = view.Table.Sorts - case av.LayoutTypeGallery: - filters = view.Gallery.Filters - sorts = view.Gallery.Sorts - } + filters = view.Filters + sorts = view.Sorts return } @@ -1227,42 +1219,22 @@ func renderAttributeView(attrView *av.AttributeView, viewID, query string, page, checkViewInstance(attrView) upgradeAttributeViewSpec(attrView) - switch view.LayoutType { - case av.LayoutTypeTable: - // 列删除以后需要删除设置的过滤和排序 - tmpFilters := []*av.ViewFilter{} - for _, f := range view.Table.Filters { - if k, _ := attrView.GetKey(f.Column); nil != k { - tmpFilters = append(tmpFilters, f) - } + // 字段删除以后需要删除设置的过滤和排序 + tmpFilters := []*av.ViewFilter{} + for _, f := range view.Filters { + if k, _ := attrView.GetKey(f.Column); nil != k { + tmpFilters = append(tmpFilters, f) } - view.Table.Filters = tmpFilters - - tmpSorts := []*av.ViewSort{} - for _, s := range view.Table.Sorts { - if k, _ := attrView.GetKey(s.Column); nil != k { - tmpSorts = append(tmpSorts, s) - } - } - view.Table.Sorts = tmpSorts - case av.LayoutTypeGallery: - // 字段删除以后需要删除设置的过滤和排序 - tmpFilters := []*av.ViewFilter{} - for _, f := range view.Gallery.Filters { - if k, _ := attrView.GetKey(f.Column); nil != k { - tmpFilters = append(tmpFilters, f) - } - } - view.Gallery.Filters = tmpFilters - - tmpSorts := []*av.ViewSort{} - for _, s := range view.Gallery.Sorts { - if k, _ := attrView.GetKey(s.Column); nil != k { - tmpSorts = append(tmpSorts, s) - } - } - view.Gallery.Sorts = tmpSorts } + view.Filters = tmpFilters + + tmpSorts := []*av.ViewSort{} + for _, s := range view.Sorts { + if k, _ := attrView.GetKey(s.Column); nil != k { + tmpSorts = append(tmpSorts, s) + } + } + view.Sorts = tmpSorts viewable = sql.RenderView(view, attrView, query) if nil == viewable { @@ -1280,10 +1252,7 @@ func renderAttributeView(attrView *av.AttributeView, viewID, query string, page, case av.LayoutTypeTable: table := viewable.(*av.Table) table.RowCount = len(table.Rows) - if 1 > view.Table.PageSize { - view.Table.PageSize = av.TableViewDefaultPageSize - } - table.PageSize = view.Table.PageSize + table.PageSize = view.PageSize if 1 > pageSize { pageSize = table.PageSize } @@ -1296,10 +1265,7 @@ func renderAttributeView(attrView *av.AttributeView, viewID, query string, page, case av.LayoutTypeGallery: gallery := viewable.(*av.Gallery) gallery.CardCount = len(gallery.Cards) - if 1 > view.Gallery.PageSize { - view.Gallery.PageSize = av.GalleryViewDefaultPageSize - } - gallery.PageSize = view.Gallery.PageSize + gallery.PageSize = view.PageSize if 1 > pageSize { pageSize = gallery.PageSize } @@ -1893,6 +1859,25 @@ func (tx *Transaction) doDuplicateAttrViewView(operation *Operation) (ret *TxErr view.Desc = masterView.Desc view.LayoutType = masterView.LayoutType + for _, filter := range masterView.Filters { + view.Filters = append(view.Filters, &av.ViewFilter{ + Column: filter.Column, + Operator: filter.Operator, + Value: filter.Value, + RelativeDate: filter.RelativeDate, + RelativeDate2: filter.RelativeDate2, + }) + } + + for _, s := range masterView.Sorts { + view.Sorts = append(view.Sorts, &av.ViewSort{ + Column: s.Column, + Order: s.Order, + }) + } + + view.PageSize = masterView.PageSize + switch masterView.LayoutType { case av.LayoutTypeTable: for _, col := range masterView.Table.Columns { @@ -1907,24 +1892,6 @@ func (tx *Transaction) doDuplicateAttrViewView(operation *Operation) (ret *TxErr }) } - for _, filter := range masterView.Table.Filters { - view.Table.Filters = append(view.Table.Filters, &av.ViewFilter{ - Column: filter.Column, - Operator: filter.Operator, - Value: filter.Value, - RelativeDate: filter.RelativeDate, - RelativeDate2: filter.RelativeDate2, - }) - } - - for _, s := range masterView.Table.Sorts { - view.Table.Sorts = append(view.Table.Sorts, &av.ViewSort{ - Column: s.Column, - Order: s.Order, - }) - } - - view.Table.PageSize = masterView.Table.PageSize view.Table.RowIDs = masterView.Table.RowIDs case av.LayoutTypeGallery: for _, field := range masterView.Gallery.CardFields { @@ -1935,26 +1902,7 @@ func (tx *Transaction) doDuplicateAttrViewView(operation *Operation) (ret *TxErr }) } - for _, filter := range masterView.Gallery.Filters { - view.Gallery.Filters = append(view.Gallery.Filters, &av.ViewFilter{ - Column: filter.Column, - Operator: filter.Operator, - Value: filter.Value, - RelativeDate: filter.RelativeDate, - RelativeDate2: filter.RelativeDate2, - }) - } - - for _, s := range masterView.Gallery.Sorts { - view.Gallery.Sorts = append(view.Gallery.Sorts, &av.ViewSort{ - Column: s.Column, - Order: s.Order, - }) - } - - view.Gallery.PageSize = masterView.Gallery.PageSize view.Gallery.CardIDs = masterView.Gallery.CardIDs - view.Gallery.CoverFrom = masterView.Gallery.CoverFrom view.Gallery.CoverFromAssetKeyID = masterView.Gallery.CoverFromAssetKeyID view.Gallery.CardSize = masterView.Gallery.CardSize @@ -2256,15 +2204,8 @@ func setAttributeViewFilters(operation *Operation) (err error) { return } - switch view.LayoutType { - case av.LayoutTypeTable: - if err = gulu.JSON.UnmarshalJSON(data, &view.Table.Filters); err != nil { - return - } - case av.LayoutTypeGallery: - if err = gulu.JSON.UnmarshalJSON(data, &view.Gallery.Filters); err != nil { - return - } + if err = gulu.JSON.UnmarshalJSON(data, &view.Filters); err != nil { + return } err = av.SaveAttributeView(attrView) @@ -2296,15 +2237,8 @@ func setAttributeViewSorts(operation *Operation) (err error) { return } - switch view.LayoutType { - case av.LayoutTypeTable: - if err = gulu.JSON.UnmarshalJSON(data, &view.Table.Sorts); err != nil { - return - } - case av.LayoutTypeGallery: - if err = gulu.JSON.UnmarshalJSON(data, &view.Gallery.Sorts); err != nil { - return - } + if err = gulu.JSON.UnmarshalJSON(data, &view.Sorts); err != nil { + return } err = av.SaveAttributeView(attrView) @@ -2330,12 +2264,7 @@ func setAttributeViewPageSize(operation *Operation) (err error) { return } - switch view.LayoutType { - case av.LayoutTypeTable: - view.Table.PageSize = int(operation.Data.(float64)) - case av.LayoutTypeGallery: - view.Gallery.PageSize = int(operation.Data.(float64)) - } + view.PageSize = int(operation.Data.(float64)) err = av.SaveAttributeView(attrView) return @@ -2487,12 +2416,8 @@ func addAttributeViewBlock(now int64, avID, blockID, previousBlockID, addingBloc // 如果存在过滤条件,则将过滤条件应用到新添加的块上 view, _ := getAttrViewViewByBlockID(attrView, blockID) - var filters []*av.ViewFilter - if nil != view { - filters = view.GetFilters() - } - if nil != view && 0 < len(filters) && !ignoreFillFilter { + if nil != view && 0 < len(view.Filters) && !ignoreFillFilter { viewable := sql.RenderView(view, attrView, "") viewable.Filter(attrView) viewable.Sort(attrView) @@ -2517,13 +2442,12 @@ func addAttributeViewBlock(now int64, avID, blockID, previousBlockID, addingBloc } sameKeyFilterSort := false // 是否在同一个字段上同时存在过滤和排序 - sorts := view.GetSorts() - if 0 < len(sorts) { + if 0 < len(view.Sorts) { filterKeys, sortKeys := map[string]bool{}, map[string]bool{} - for _, f := range filters { + for _, f := range view.Filters { filterKeys[f.Column] = true } - for _, s := range sorts { + for _, s := range view.Sorts { sortKeys[s.Column] = true } @@ -2537,7 +2461,7 @@ func addAttributeViewBlock(now int64, avID, blockID, previousBlockID, addingBloc if !sameKeyFilterSort { // 如果在同一个字段上仅存在过滤条件,则将过滤条件应用到新添加的块上 - for _, filter := range filters { + for _, filter := range view.Filters { for _, keyValues := range attrView.KeyValues { if keyValues.Key.ID == filter.Column { var defaultVal *av.Value @@ -4233,36 +4157,17 @@ func updateAttributeViewColumnOption(operation *Operation) (err error) { // 如果存在选项对应的过滤器,需要更新过滤器中设置的选项值 // Database select field filters follow option editing changes https://github.com/siyuan-note/siyuan/issues/10881 for _, view := range attrView.Views { - switch view.LayoutType { - case av.LayoutTypeTable: - for _, filter := range view.Table.Filters { - if filter.Column != key.ID { - continue - } - - if nil != filter.Value && (av.KeyTypeSelect == filter.Value.Type || av.KeyTypeMSelect == filter.Value.Type) { - for i, opt := range filter.Value.MSelect { - if oldName == opt.Content { - filter.Value.MSelect[i].Content = newName - filter.Value.MSelect[i].Color = newColor - break - } - } - } + for _, filter := range view.Filters { + if filter.Column != key.ID { + continue } - case av.LayoutTypeGallery: - for _, filter := range view.Gallery.Filters { - if filter.Column != key.ID { - continue - } - if nil != filter.Value && (av.KeyTypeSelect == filter.Value.Type || av.KeyTypeMSelect == filter.Value.Type) { - for i, opt := range filter.Value.MSelect { - if oldName == opt.Content { - filter.Value.MSelect[i].Content = newName - filter.Value.MSelect[i].Color = newColor - break - } + if nil != filter.Value && (av.KeyTypeSelect == filter.Value.Type || av.KeyTypeMSelect == filter.Value.Type) { + for i, opt := range filter.Value.MSelect { + if oldName == opt.Content { + filter.Value.MSelect[i].Content = newName + filter.Value.MSelect[i].Color = newColor + break } } } diff --git a/kernel/sql/av_gallery.go b/kernel/sql/av_gallery.go index 800d34055..4e36a9c38 100644 --- a/kernel/sql/av_gallery.go +++ b/kernel/sql/av_gallery.go @@ -23,8 +23,8 @@ func RenderAttributeViewGallery(attrView *av.AttributeView, view *av.View, query Name: view.Name, Desc: view.Desc, HideAttrViewName: view.HideAttrViewName, - Filters: view.Gallery.Filters, - Sorts: view.Gallery.Sorts, + Filters: view.Filters, + Sorts: view.Sorts, }, CoverFrom: view.Gallery.CoverFrom, CoverFromAssetKeyID: view.Gallery.CoverFromAssetKeyID, diff --git a/kernel/sql/av_table.go b/kernel/sql/av_table.go index 14ffedc52..41a9e25dc 100644 --- a/kernel/sql/av_table.go +++ b/kernel/sql/av_table.go @@ -30,8 +30,8 @@ func RenderAttributeViewTable(attrView *av.AttributeView, view *av.View, query s Name: view.Name, Desc: view.Desc, HideAttrViewName: view.HideAttrViewName, - Filters: view.Table.Filters, - Sorts: view.Table.Sorts, + Filters: view.Filters, + Sorts: view.Sorts, }, Columns: []*av.TableColumn{}, Rows: []*av.TableRow{},