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

This commit is contained in:
Vanessa 2025-07-28 09:28:55 +08:00
commit 99ad5a0f77
6 changed files with 63 additions and 64 deletions

View file

@ -220,6 +220,21 @@ func (view *View) GetGroup(groupID string) *View {
return nil
}
// GetGroupKey 获取分组视图的分组字段。
func (view *View) GetGroupKey(attrView *AttributeView) (ret *Key) {
if nil == view.Group || "" == view.Group.Field {
return
}
for _, kv := range attrView.KeyValues {
if kv.Key.ID == view.Group.Field {
ret = kv.Key
return
}
}
return
}
// GroupCalc 描述了分组计算规则和结果的结构。
type GroupCalc struct {
Field string `json:"field"` // 字段 ID

View file

@ -63,18 +63,19 @@ func sortAttributeViewGroup(avID, blockID, previousGroupID, groupID string) (err
return err
}
var group *av.View
var groupView *av.View
var index, previousIndex int
for i, g := range view.Groups {
if g.ID == groupID {
group = g
groupView = g
index = i
break
}
}
if nil == group {
if nil == groupView {
return
}
view.Group.Order = av.GroupOrderMan
view.Groups = append(view.Groups[:index], view.Groups[index+1:]...)
for i, g := range view.Groups {
@ -83,7 +84,7 @@ func sortAttributeViewGroup(avID, blockID, previousGroupID, groupID string) (err
break
}
}
view.Groups = util.InsertElem(view.Groups, previousIndex, group)
view.Groups = util.InsertElem(view.Groups, previousIndex, groupView)
err = av.SaveAttributeView(attrView)
return
@ -295,6 +296,7 @@ func SetAttributeViewGroup(avID, blockID string, group *av.ViewGroup) (err error
}
err = av.SaveAttributeView(attrView)
ReloadAttrView(avID)
return
}
@ -1573,6 +1575,19 @@ func genAttrViewViewGroups(view *av.View, attrView *av.AttributeView) {
return
}
// 临时记录每个分组视图的状态,以便后面重新生成分组后可以恢复这些状态
type GroupState struct {
Folded bool
Hidden int
}
groupStates := map[string]*GroupState{}
for _, groupView := range view.Groups {
groupStates[groupView.Name] = &GroupState{
Folded: groupView.GroupFolded,
Hidden: groupView.GroupHidden,
}
}
group := view.Group
view.Groups = nil
viewable := sql.RenderView(attrView, view, "")
@ -1586,30 +1601,12 @@ func genAttrViewViewGroups(view *av.View, attrView *av.AttributeView) {
return
}
// 如果是按日期分组,则需要记录每个分组视图的一些状态字段,以便后面重新计算分组后可以恢复这些状态
type GroupState struct {
Folded bool
Hidden int
}
groupStates := map[string]*GroupState{}
if isGroupByDate(view) {
for _, groupView := range view.Groups {
groupStates[groupView.Name] = &GroupState{
Folded: groupView.GroupFolded,
Hidden: groupView.GroupHidden,
}
}
}
var rangeStart, rangeEnd float64
switch group.Method {
case av.GroupMethodValue:
if av.GroupOrderMan != group.Order {
sort.SliceStable(items, func(i, j int) bool {
if av.GroupOrderAsc == group.Order {
return items[i].GetValue(group.Field).String(false) < items[j].GetValue(group.Field).String(false)
}
return items[i].GetValue(group.Field).String(false) > items[j].GetValue(group.Field).String(false)
return items[i].GetValue(group.Field).String(false) < items[j].GetValue(group.Field).String(false)
})
}
case av.GroupMethodRangeNum:
@ -1619,17 +1616,11 @@ func genAttrViewViewGroups(view *av.View, attrView *av.AttributeView) {
rangeStart, rangeEnd = group.Range.NumStart, group.Range.NumStart+group.Range.NumStep
sort.SliceStable(items, func(i, j int) bool {
if av.GroupOrderAsc == group.Order {
return items[i].GetValue(group.Field).Number.Content < items[j].GetValue(group.Field).Number.Content
}
return items[i].GetValue(group.Field).Number.Content > items[j].GetValue(group.Field).Number.Content
return items[i].GetValue(group.Field).Number.Content < items[j].GetValue(group.Field).Number.Content
})
case av.GroupMethodDateDay, av.GroupMethodDateWeek, av.GroupMethodDateMonth, av.GroupMethodDateYear, av.GroupMethodDateRelative:
sort.SliceStable(items, func(i, j int) bool {
if av.GroupOrderAsc == group.Order {
return items[i].GetValue(group.Field).Date.Content < items[j].GetValue(group.Field).Date.Content
}
return items[i].GetValue(group.Field).Date.Content > items[j].GetValue(group.Field).Date.Content
return items[i].GetValue(group.Field).Date.Content < items[j].GetValue(group.Field).Date.Content
})
}
@ -1747,24 +1738,23 @@ func genAttrViewViewGroups(view *av.View, attrView *av.AttributeView) {
view.Groups = append(view.Groups, v)
}
if isGroupByDate(view) {
view.GroupUpdated = time.Now().UnixMilli()
view.GroupUpdated = time.Now().UnixMilli()
// 则恢复分组视图状态
for _, groupView := range view.Groups {
if state, ok := groupStates[groupView.Name]; ok {
groupView.GroupFolded = state.Folded
groupView.GroupHidden = state.Hidden
}
// 则恢复分组视图状态
for _, groupView := range view.Groups {
if state, ok := groupStates[groupView.Name]; ok {
groupView.GroupFolded = state.Folded
groupView.GroupHidden = state.Hidden
}
}
if av.GroupOrderMan != view.Group.Order {
sort.SliceStable(view.Groups, func(i, j int) bool {
iName, jName := view.Groups[i].Name, view.Groups[j].Name
if av.GroupOrderAsc == view.Group.Order {
return view.Groups[i].Name < view.Groups[j].Name
return util.NaturalCompare(iName, jName)
}
return view.Groups[i].Name > view.Groups[j].Name
return util.NaturalCompare(jName, iName)
})
}
@ -3063,7 +3053,7 @@ func addAttributeViewBlock(now int64, avID, blockID, groupID, previousBlockID, a
}
// 如果存在分组条件,则将分组条件应用到新添加的块上
groupKey := getViewGroupKey(view, attrView)
groupKey := view.GetGroupKey(attrView)
if nil != view && nil != groupKey {
if !filterKeyIDs[groupKey.ID] /* 过滤条件应用过的话就不重复处理了 */ && "" != groupID {
if groupView := view.GetGroup(groupID); nil != groupView {
@ -3091,7 +3081,7 @@ func addAttributeViewBlock(now int64, avID, blockID, groupID, previousBlockID, a
if av.KeyTypeSelect == groupKey.Type || av.KeyTypeMSelect == groupKey.Type {
// 因为单选或多选只能按选项分组,并且可能存在空白分组(前面可能找不到临近项) ,所以单选或多选类型的分组字段使用分组值内容对应的选项
if opt := groupKey.GetOption(groupView.GroupValue); nil != opt {
if opt := groupKey.GetOption(groupView.GroupValue); nil != opt && av.GroupValueDefault != groupView.GroupValue {
newValue.MSelect[0].Content = opt.Name
newValue.MSelect[0].Color = opt.Color
}
@ -3175,6 +3165,9 @@ func removeAttributeViewBlock(srcIDs []string, avID string, tx *Transaction) (er
}
err = av.SaveAttributeView(attrView)
if nil != err {
return
}
historyDir, err := GetHistoryDir(HistoryOpUpdate)
if err != nil {
@ -3865,6 +3858,7 @@ func updateAttributeViewColTemplate(operation *Operation) (err error) {
}
}
regenAttrViewViewGroups(attrView, operation.ID)
err = av.SaveAttributeView(attrView)
return
}
@ -4521,7 +4515,7 @@ func updateAttributeViewValue(tx *Transaction, attrView *av.AttributeView, keyID
func regenAttrViewViewGroups(attrView *av.AttributeView, keyID string) {
for _, view := range attrView.Views {
groupKey := getViewGroupKey(view, attrView)
groupKey := view.GetGroupKey(attrView)
if nil == groupKey {
continue
}
@ -4546,17 +4540,6 @@ func regenAttrViewViewGroups(attrView *av.AttributeView, keyID string) {
}
}
func getViewGroupKey(view *av.View, attrView *av.AttributeView) *av.Key {
if nil == view.Group {
return nil
}
if "" == view.Group.Field {
return nil
}
ret, _ := attrView.GetKey(view.Group.Field)
return ret
}
func unbindBlockAv(tx *Transaction, avID, blockID string) {
node, tree, err := getNodeByBlockID(tx, blockID)
if err != nil {
@ -4750,6 +4733,7 @@ func removeAttributeViewColumnOption(operation *Operation) (err error) {
break
}
regenAttrViewViewGroups(attrView, operation.ID)
err = av.SaveAttributeView(attrView)
return
}
@ -4868,6 +4852,7 @@ func updateAttributeViewColumnOption(operation *Operation) (err error) {
}
}
regenAttrViewViewGroups(attrView, operation.ID)
err = av.SaveAttributeView(attrView)
return
}

View file

@ -46,8 +46,7 @@ const (
var (
accountsMap = AccountsMap{}
key = make([]byte, 32)
jwtKey = make([]byte, 32)
)
func GetBasicAuthAccount(username string) *Account {
@ -69,7 +68,7 @@ func InitAccounts() {
}
func InitJWT() {
if _, err := rand.Read(key); err != nil {
if _, err := rand.Read(jwtKey); err != nil {
logging.LogErrorf("generate JWT signing key failed: %s", err)
return
}
@ -87,7 +86,7 @@ func InitJWT() {
ClaimsKeyRole: RoleReader,
},
)
if token, err := t.SignedString(key); err != nil {
if token, err := t.SignedString(jwtKey); err != nil {
logging.LogErrorf("JWT signature failed: %s", err)
return
} else {
@ -101,7 +100,7 @@ func ParseJWT(tokenString string) (*jwt.Token, error) {
return jwt.Parse(
tokenString,
func(token *jwt.Token) (interface{}, error) {
return key, nil
return jwtKey, nil
},
jwt.WithIssuer(iss),
jwt.WithSubject(sub),

View file

@ -690,7 +690,7 @@ func fullReindex() {
sql.IndexIgnoreCached = false
openedBoxes := Conf.GetOpenedBoxes()
for _, openedBox := range openedBoxes {
index(openedBox.ID)
indexBox(openedBox.ID)
}
LoadFlashcards()
debug.FreeOSMemory()

View file

@ -870,7 +870,7 @@ func InitBoxes() {
box.UpdateHistoryGenerated() // 初始化历史生成时间为当前时间
if !initialized {
index(box.ID)
indexBox(box.ID)
}
}

View file

@ -120,7 +120,7 @@ func unindex(boxID string) {
func (box *Box) Index() {
task.AppendTask(task.DatabaseIndexRef, removeBoxRefs, box.ID)
task.AppendTask(task.DatabaseIndex, index, box.ID)
task.AppendTask(task.DatabaseIndex, indexBox, box.ID)
task.AppendTask(task.DatabaseIndexRef, IndexRefs)
go func() {
sql.FlushQueue()
@ -132,7 +132,7 @@ func removeBoxRefs(boxID string) {
sql.DeleteBoxRefsQueue(boxID)
}
func index(boxID string) {
func indexBox(boxID string) {
box := Conf.Box(boxID)
if nil == box {
return