diff --git a/app/src/protyle/render/av/render.ts b/app/src/protyle/render/av/render.ts
index ff26c1341..f0f36245e 100644
--- a/app/src/protyle/render/av/render.ts
+++ b/app/src/protyle/render/av/render.ts
@@ -136,9 +136,9 @@ style="width: ${index === 0 ? ((parseInt(column.width || "200") + 24) + "px") :
}
});
tableHTML += `
`;
// body
diff --git a/kernel/av/av.go b/kernel/av/av.go
index db829fb95..f434ef777 100644
--- a/kernel/av/av.go
+++ b/kernel/av/av.go
@@ -91,20 +91,23 @@ type Key struct {
// 以下是某些列类型的特有属性
- // 单选/多选列
+ // 单选/多选
Options []*SelectOption `json:"options,omitempty"` // 选项列表
- // 数字列
+ // 数字
NumberFormat NumberFormat `json:"numberFormat"` // 列数字格式化
- // 模板列
+ // 模板
Template string `json:"template"` // 模板内容
- // 关联列
+ // 关联
Relation *Relation `json:"relation,omitempty"` // 关联信息
- // 汇总列
+ // 汇总
Rollup *Rollup `json:"rollup,omitempty"` // 汇总信息
+
+ // 日期
+ Date *Date `json:"date,omitempty"` // 日期设置
}
func NewKey(id, name, icon string, keyType KeyType) *Key {
@@ -116,6 +119,10 @@ func NewKey(id, name, icon string, keyType KeyType) *Key {
}
}
+type Date struct {
+ AutoFillNow bool `json:"autoFillNow"` // 是否自动填充当前时间 The database date field supports filling the current time by default https://github.com/siyuan-note/siyuan/issues/10823
+}
+
type Rollup struct {
RelationKeyID string `json:"relationKeyID"` // 关联列 ID
KeyID string `json:"keyID"` // 目标列 ID
diff --git a/kernel/model/attribute_view.go b/kernel/model/attribute_view.go
index ce9fa5b1f..d18835b16 100644
--- a/kernel/model/attribute_view.go
+++ b/kernel/model/attribute_view.go
@@ -1184,6 +1184,36 @@ func getRowBlockValue(keyValues []*av.KeyValues) (ret *av.Value) {
return
}
+func (tx *Transaction) doSetAttrViewColDate(operation *Operation) (ret *TxErr) {
+ err := setAttributeViewColDate(operation)
+ if nil != err {
+ return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
+ }
+ return
+}
+
+func setAttributeViewColDate(operation *Operation) (err error) {
+ attrView, err := av.ParseAttributeView(operation.AvID)
+ if nil != err {
+ return
+ }
+
+ keyID := operation.ID
+ key, _ := attrView.GetKey(keyID)
+ if nil == key || av.KeyTypeDate != key.Type {
+ return
+ }
+
+ if nil == key.Date {
+ key.Date = &av.Date{}
+ }
+
+ key.Date.AutoFillNow = operation.Data.(bool)
+
+ err = av.SaveAttributeView(attrView)
+ return
+}
+
func (tx *Transaction) doHideAttrViewName(operation *Operation) (ret *TxErr) {
err := hideAttrViewName(operation)
if nil != err {
@@ -2104,27 +2134,39 @@ func addAttributeViewBlock(avID, blockID, previousBlockID, addingBlockID string,
}
}
+ // 处理日期字段默认填充当前创建时间
+ // The database date field supports filling the current time by default https://github.com/siyuan-note/siyuan/issues/10823
+ for _, keyValues := range attrView.KeyValues {
+ if av.KeyTypeDate == keyValues.Key.Type && nil != keyValues.Key.Date && keyValues.Key.Date.AutoFillNow {
+ dateVal := &av.Value{
+ ID: ast.NewNodeID(), KeyID: keyValues.Key.ID, BlockID: addingBlockID, Type: av.KeyTypeDate, IsDetached: isDetached, CreatedAt: now, UpdatedAt: now + 1000,
+ Date: &av.ValueDate{Content: now, IsNotEmpty: true},
+ }
+ keyValues.Values = append(keyValues.Values, dateVal)
+ }
+ }
+
if !isDetached {
bindBlockAv0(tx, avID, blockID, node, tree)
}
- for _, view := range attrView.Views {
- switch view.LayoutType {
+ for _, v := range attrView.Views {
+ switch v.LayoutType {
case av.LayoutTypeTable:
if "" != previousBlockID {
changed := false
- for i, id := range view.Table.RowIDs {
+ for i, id := range v.Table.RowIDs {
if id == previousBlockID {
- view.Table.RowIDs = append(view.Table.RowIDs[:i+1], append([]string{addingBlockID}, view.Table.RowIDs[i+1:]...)...)
+ v.Table.RowIDs = append(v.Table.RowIDs[:i+1], append([]string{addingBlockID}, v.Table.RowIDs[i+1:]...)...)
changed = true
break
}
}
if !changed {
- view.Table.RowIDs = append(view.Table.RowIDs, addingBlockID)
+ v.Table.RowIDs = append(v.Table.RowIDs, addingBlockID)
}
} else {
- view.Table.RowIDs = append([]string{addingBlockID}, view.Table.RowIDs...)
+ v.Table.RowIDs = append([]string{addingBlockID}, v.Table.RowIDs...)
}
}
}
diff --git a/kernel/model/import.go b/kernel/model/import.go
index 48a91e104..641e0cea1 100644
--- a/kernel/model/import.go
+++ b/kernel/model/import.go
@@ -149,16 +149,18 @@ func ImportSY(zipPath, boxID, toPath string) (err error) {
// 新 ID 保留时间部分,仅修改随机值,避免时间变化导致更新时间早于创建时间
// Keep original creation time when importing .sy.zip https://github.com/siyuan-note/siyuan/issues/9923
- newNodeID := util.TimeFromID(n.ID) + "-" + gulu.Rand.String(7)
+ newNodeID := util.TimeFromID(n.ID) + "-" + util.RandString(7)
blockIDs[n.ID] = newNodeID
oldNodeID := n.ID
n.ID = newNodeID
n.SetIALAttr("id", newNodeID)
// 重新指向数据库属性值
- ial := parse.IAL2Map(n.KramdownIAL)
- for k, _ := range ial {
- if strings.HasPrefix(k, av.NodeAttrNameAvs) {
+ for _, kv := range n.KramdownIAL {
+ if 2 > len(kv) {
+ continue
+ }
+ if strings.HasPrefix(kv[0], av.NodeAttrNameAvs) {
avBlockIDs[oldNodeID] = newNodeID
}
}
diff --git a/kernel/model/transaction.go b/kernel/model/transaction.go
index 67882b680..39f480211 100644
--- a/kernel/model/transaction.go
+++ b/kernel/model/transaction.go
@@ -292,6 +292,8 @@ func performTx(tx *Transaction) (ret *TxErr) {
ret = tx.doUpdateAttrViewColRollup(op)
case "hideAttrViewName":
ret = tx.doHideAttrViewName(op)
+ case "setAttrViewColDate":
+ ret = tx.doSetAttrViewColDate(op)
}
if nil != ret {
diff --git a/kernel/model/virutalref.go b/kernel/model/virutalref.go
index 72a0f2b2b..668bb204e 100644
--- a/kernel/model/virutalref.go
+++ b/kernel/model/virutalref.go
@@ -275,7 +275,7 @@ func prepareMarkKeywords(keywords []string) (ret []string) {
ret = gulu.Str.RemoveDuplicatedElem(keywords)
var tmp []string
for _, k := range ret {
- if "" != k {
+ if "" != k && "*" != k { // 提及和虚引排除 * Ignore `*` back mentions and virtual references https://github.com/siyuan-note/siyuan/issues/10873
tmp = append(tmp, k)
}
}
diff --git a/kernel/util/misc.go b/kernel/util/misc.go
index 6ef47299f..c339917cf 100644
--- a/kernel/util/misc.go
+++ b/kernel/util/misc.go
@@ -18,13 +18,31 @@ package util
import (
"bytes"
+ "math/rand"
"strconv"
"strings"
+ "time"
"unicode"
"github.com/88250/lute/html"
)
+func init() {
+ rand.Seed(time.Now().UTC().UnixNano())
+}
+
+var (
+ letter = []rune("abcdefghijklmnopqrstuvwxyz0123456789")
+)
+
+func RandString(length int) string {
+ b := make([]rune, length)
+ for i := range b {
+ b[i] = letter[rand.Intn(len(letter))]
+ }
+ return string(b)
+}
+
// InsertElem inserts value at index into a.
// 0 <= index <= len(s)
func InsertElem[T any](s []T, index int, value T) []T {