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

This commit is contained in:
Vanessa 2024-04-15 01:29:39 +08:00
commit 9e1fc704c9
32 changed files with 390 additions and 243 deletions

1
.gitignore vendored
View file

@ -24,6 +24,7 @@ electron/dist
# IDE # IDE
.idea/ .idea/
.vscode/
# Log # Log
logs logs

View file

@ -119,6 +119,7 @@
"goToEditTabPrev": "Go to previous edited tab", "goToEditTabPrev": "Go to previous edited tab",
"createdTime": "Created time", "createdTime": "Created time",
"updatedTime": "Updated time", "updatedTime": "Updated time",
"lineNumber": "Line number",
"removeBookmark": "Remove bookmark from ${x}?", "removeBookmark": "Remove bookmark from ${x}?",
"defaultMargin": "Default", "defaultMargin": "Default",
"noneMargin": "None", "noneMargin": "None",

View file

@ -119,6 +119,7 @@
"goToEditTabPrev": "Ir a la pestaña editada anteriormente", "goToEditTabPrev": "Ir a la pestaña editada anteriormente",
"createdTime": "Hora de creación", "createdTime": "Hora de creación",
"updatedTime": "Hora actualizada", "updatedTime": "Hora actualizada",
"lineNumber": "Número de línea",
"removeBookmark": "¿Eliminar marcador de ${x}?", "removeBookmark": "¿Eliminar marcador de ${x}?",
"lockEdit": "Hacer que el documento sea de sólo lectura", "lockEdit": "Hacer que el documento sea de sólo lectura",
"unlockEdit": "Hacer que el documento sea escribible", "unlockEdit": "Hacer que el documento sea escribible",

View file

@ -119,6 +119,7 @@
"goToEditTabPrev": "Aller à l'onglet modifié précédent", "goToEditTabPrev": "Aller à l'onglet modifié précédent",
"createdTime": "Heure de création", "createdTime": "Heure de création",
"updatedTime": "Heure mise à jour", "updatedTime": "Heure mise à jour",
"lineNumber": "Numéro de ligne",
"removeBookmark": "Supprimer le signet de ${x} ?", "removeBookmark": "Supprimer le signet de ${x} ?",
"lockEdit": "Rendre le document en lecture seule", "lockEdit": "Rendre le document en lecture seule",
"unlockEdit": "Rendre le document accessible en écriture", "unlockEdit": "Rendre le document accessible en écriture",

View file

@ -119,6 +119,7 @@
"goToEditTabPrev": "跳到上一個編輯頁籤", "goToEditTabPrev": "跳到上一個編輯頁籤",
"createdTime": "建立時間", "createdTime": "建立時間",
"updatedTime": "更新時間", "updatedTime": "更新時間",
"lineNumber": "行號",
"removeBookmark": "移除 ${x} 中的書籤?", "removeBookmark": "移除 ${x} 中的書籤?",
"lockEdit": "鎖定編輯", "lockEdit": "鎖定編輯",
"unlockEdit": "解除鎖定", "unlockEdit": "解除鎖定",

View file

@ -119,6 +119,7 @@
"goToEditTabPrev": "跳转到上一个编辑页签", "goToEditTabPrev": "跳转到上一个编辑页签",
"createdTime": "创建时间", "createdTime": "创建时间",
"updatedTime": "更新时间", "updatedTime": "更新时间",
"lineNumber": "行号",
"removeBookmark": "移除 ${x} 中的书签?", "removeBookmark": "移除 ${x} 中的书签?",
"lockEdit": "锁定编辑", "lockEdit": "锁定编辑",
"unlockEdit": "解除锁定", "unlockEdit": "解除锁定",

View file

@ -251,7 +251,8 @@ export const avClick = (protyle: IProtyle, event: MouseEvent & { target: HTMLEle
return; return;
} }
const type = getTypeByCellElement(target); const type = getTypeByCellElement(target);
if (type === "updated" || type === "created" || (type === "block" && !target.getAttribute("data-detached"))) { // TODO 点击单元格的时候, lineNumber 选中整行
if (type === "updated" || type === "created" || type === "lineNumber" || (type === "block" && !target.getAttribute("data-detached"))) {
selectRow(rowElement.querySelector(".av__firstcol"), "toggle"); selectRow(rowElement.querySelector(".av__firstcol"), "toggle");
} else { } else {
scrollElement.querySelectorAll(".av__row--select").forEach(item => { scrollElement.querySelectorAll(".av__row--select").forEach(item => {

View file

@ -644,7 +644,7 @@ export const renderCellAttr = (cellElement: Element, value: IAVCellValue) => {
} }
}; };
export const renderCell = (cellValue: IAVCellValue) => { export const renderCell = (cellValue: IAVCellValue, rowIndex = 0) => {
let text = ""; let text = "";
if (["text", "template"].includes(cellValue.type)) { if (["text", "template"].includes(cellValue.type)) {
text = `<span class="av__celltext">${cellValue ? (cellValue[cellValue.type as "text"].content || "") : ""}</span>`; text = `<span class="av__celltext">${cellValue ? (cellValue[cellValue.type as "text"].content || "") : ""}</span>`;
@ -683,6 +683,9 @@ export const renderCell = (cellValue: IAVCellValue) => {
text += dayjs(dataValue.content).format("YYYY-MM-DD HH:mm"); text += dayjs(dataValue.content).format("YYYY-MM-DD HH:mm");
} }
text += "</span>"; text += "</span>";
} else if (["lineNumber"].includes(cellValue.type)) {
// 渲染行号
text = `<span class="av__celltext" data-value='${rowIndex + 1}'>${rowIndex + 1}</span>`;
} else if (cellValue.type === "mAsset") { } else if (cellValue.type === "mAsset") {
cellValue?.mAsset?.forEach((item) => { cellValue?.mAsset?.forEach((item) => {
if (item.type === "image") { if (item.type === "image") {
@ -713,8 +716,9 @@ export const renderCell = (cellValue: IAVCellValue) => {
text = text.substring(0, text.length - 2); text = text.substring(0, text.length - 2);
} }
} }
if (["text", "template", "url", "email", "phone", "number", "date", "created", "updated"].includes(cellValue.type) &&
cellValue && cellValue[cellValue.type as "url"].content) { if (["text", "template", "url", "email", "phone", "number", "date", "created", "updated", "lineNumber"].includes(cellValue.type) &&
( cellValue.type === "lineNumber" || (cellValue && cellValue[cellValue.type as "url"].content))) {
text += `<span ${cellValue.type !== "number" ? "" : 'style="right:auto;left:5px"'} data-type="copy" class="block__icon"><svg><use xlink:href="#iconCopy"></use></svg></span>`; text += `<span ${cellValue.type !== "number" ? "" : 'style="right:auto;left:5px"'} data-type="copy" class="block__icon"><svg><use xlink:href="#iconCopy"></use></svg></span>`;
} }
return text; return text;

View file

@ -252,6 +252,7 @@ export const getEditHTML = (options: {
${genUpdateColItem("template", colData.type)} ${genUpdateColItem("template", colData.type)}
${genUpdateColItem("relation", colData.type)} ${genUpdateColItem("relation", colData.type)}
${genUpdateColItem("rollup", colData.type)} ${genUpdateColItem("rollup", colData.type)}
${genUpdateColItem("lineNumber", colData.type)}
${genUpdateColItem("created", colData.type)} ${genUpdateColItem("created", colData.type)}
${genUpdateColItem("updated", colData.type)} ${genUpdateColItem("updated", colData.type)}
</div>`; </div>`;
@ -482,6 +483,8 @@ export const getColNameByType = (type: TAVCol) => {
return window.siyuan.languages.checkbox; return window.siyuan.languages.checkbox;
case "block": case "block":
return window.siyuan.languages["_attrView"].key; return window.siyuan.languages["_attrView"].key;
case "lineNumber":
return window.siyuan.languages.lineNumber;
} }
}; };
@ -518,6 +521,8 @@ export const getColIconByType = (type: TAVCol) => {
return "iconMath"; return "iconMath";
case "checkbox": case "checkbox":
return "iconCheck"; return "iconCheck";
case "lineNumber":
return "iconSpreadOdd";
} }
}; };
@ -694,6 +699,9 @@ export const showColMenu = (protyle: IProtyle, blockElement: Element, cellElemen
} }
}); });
menu.addSeparator(); menu.addSeparator();
// 行号 类型不参与 排序和筛选
if (type !== "lineNumber") {
menu.addItem({ menu.addItem({
icon: "iconUp", icon: "iconUp",
label: window.siyuan.languages.asc, label: window.siyuan.languages.asc,
@ -778,6 +786,7 @@ export const showColMenu = (protyle: IProtyle, blockElement: Element, cellElemen
}); });
} }
menu.addSeparator(); menu.addSeparator();
}
menu.addItem({ menu.addItem({
icon: "iconInsertLeft", icon: "iconInsertLeft",
@ -1429,6 +1438,44 @@ export const addCol = (protyle: IProtyle, blockElement: Element, previousID?: st
blockElement.setAttribute("updated", newUpdated); blockElement.setAttribute("updated", newUpdated);
} }
}); });
// 在创建时间前插入 lineNumber
menu.addItem({
icon: "iconSpreadOdd",
label: window.siyuan.languages.lineNumber,
click() {
const id = Lute.NewNodeID();
const newUpdated = dayjs().format("YYYYMMDDHHmmss");
transaction(protyle, [{
action: "addAttrViewCol",
name: window.siyuan.languages.lineNumber,
avID,
type: "lineNumber",
id,
previousID
}, {
action: "doUpdateUpdated",
id: blockId,
data: newUpdated,
}], [{
action: "removeAttrViewCol",
id,
avID,
}, {
action: "doUpdateUpdated",
id: blockId,
data: blockElement.getAttribute("updated")
}]);
addAttrViewColAnimation({
blockElement: blockElement,
protyle: protyle,
type: "lineNumber",
name: window.siyuan.languages.lineNumber,
id,
previousID
});
blockElement.setAttribute("updated", newUpdated);
}
});
menu.addItem({ menu.addItem({
icon: "iconClock", icon: "iconClock",
label: window.siyuan.languages.createdTime, label: window.siyuan.languages.createdTime,

View file

@ -566,7 +566,8 @@ export const addFilter = (options: {
return true; return true;
} }
}); });
if (!filter && column.type !== "mAsset") { // 该列是行号类型列,则不允许添加到过滤器
if (!filter && column.type !== "mAsset" && column.type !== "lineNumber") {
menu.addItem({ menu.addItem({
label: column.name, label: column.name,
iconHTML: column.icon ? unicode2Emoji(column.icon, "b3-menu__icon", true) : `<svg class="b3-menu__icon"><use xlink:href="#${getColIconByType(column.type)}"></use></svg>`, iconHTML: column.icon ? unicode2Emoji(column.icon, "b3-menu__icon", true) : `<svg class="b3-menu__icon"><use xlink:href="#${getColIconByType(column.type)}"></use></svg>`,

View file

@ -854,6 +854,46 @@ export const openMenuPanel = (options: {
name, name,
type: target.dataset.oldType as TAVCol, type: target.dataset.oldType as TAVCol,
}]); }]);
// 需要取消 lineNumber 列的排序和过滤
if (target.dataset.newType === "lineNumber") {
const sortExist = data.view.sorts.find((sort) => sort.column === options.colId);
if (sortExist) {
const oldSorts = Object.assign([], data.view.sorts);
const newSorts = data.view.sorts.filter((sort) => sort.column !== options.colId);
transaction(options.protyle, [{
action: "setAttrViewSorts",
avID: data.id,
data: newSorts,
blockID,
}], [{
action: "setAttrViewSorts",
avID: data.id,
data: oldSorts,
blockID,
}]);
}
const filterExist = data.view.filters.find((filter) => filter.column === options.colId);
if (filterExist) {
const oldFilters = JSON.parse(JSON.stringify(data.view.filters));
const newFilters = data.view.filters.filter((filter) => filter.column !== options.colId);
transaction(options.protyle, [{
action: "setAttrViewFilters",
avID: data.id,
data: newFilters,
blockID
}], [{
action: "setAttrViewFilters",
avID: data.id,
data: oldFilters,
blockID
}]);
}
}
} }
avPanelElement.remove(); avPanelElement.remove();
event.preventDefault(); event.preventDefault();

View file

@ -129,8 +129,16 @@ style="width: ${column.width || "200px"};">
if (pinIndex === index) { if (pinIndex === index) {
tableHTML += "</div>"; tableHTML += "</div>";
} }
// lineNumber type 不参与计算操作
if (column.type === "lineNumber") {
calcHTML += `<div data-col-id="${column.id}" data-dtype="${column.type}"
style="display: flex; width: ${index === 0 ? ((parseInt(column.width || "200") + 24) + "px") : (column.width || "200px")}">&nbsp;</div>`;
} else {
calcHTML += `<div class="av__calc${column.calc && column.calc.operator !== "" ? " av__calc--ashow" : ""}" data-col-id="${column.id}" data-dtype="${column.type}" data-operator="${column.calc?.operator || ""}" calcHTML += `<div class="av__calc${column.calc && column.calc.operator !== "" ? " av__calc--ashow" : ""}" data-col-id="${column.id}" data-dtype="${column.type}" data-operator="${column.calc?.operator || ""}"
style="width: ${index === 0 ? ((parseInt(column.width || "200") + 24) + "px") : (column.width || "200px")}">${getCalcValue(column) || '<svg><use xlink:href="#iconDown"></use></svg>' + window.siyuan.languages.calc}</div>`; style="width: ${index === 0 ? ((parseInt(column.width || "200") + 24) + "px") : (column.width || "200px")}">${getCalcValue(column) || '<svg><use xlink:href="#iconDown"></use></svg>' + window.siyuan.languages.calc}</div>`;
}
if (pinIndex === index) { if (pinIndex === index) {
calcHTML += "</div>"; calcHTML += "</div>";
} }
@ -142,7 +150,7 @@ style="width: ${index === 0 ? ((parseInt(column.width || "200") + 24) + "px") :
</div> </div>
</div>`; </div>`;
// body // body
data.rows.forEach((row: IAVRow) => { data.rows.forEach((row: IAVRow, rowIndex: number) => {
tableHTML += `<div class="av__row" data-id="${row.id}">`; tableHTML += `<div class="av__row" data-id="${row.id}">`;
if (pinIndex > -1) { if (pinIndex > -1) {
tableHTML += '<div class="av__colsticky"><div class="av__firstcol"><svg><use xlink:href="#iconUncheck"></use></svg></div>'; tableHTML += '<div class="av__colsticky"><div class="av__firstcol"><svg><use xlink:href="#iconUncheck"></use></svg></div>';
@ -165,7 +173,7 @@ ${cell.value?.isDetached ? ' data-detached="true"' : ""}
style="width: ${data.columns[index].width || "200px"}; style="width: ${data.columns[index].width || "200px"};
${cell.valueType === "number" ? "text-align: right;" : ""} ${cell.valueType === "number" ? "text-align: right;" : ""}
${cell.bgColor ? `background-color:${cell.bgColor};` : ""} ${cell.bgColor ? `background-color:${cell.bgColor};` : ""}
${cell.color ? `color:${cell.color};` : ""}">${renderCell(cell.value)}</div>`; ${cell.color ? `color:${cell.color};` : ""}">${renderCell(cell.value, rowIndex)}</div>`;
if (pinIndex === index) { if (pinIndex === index) {
tableHTML += "</div>"; tableHTML += "</div>";

View file

@ -16,12 +16,19 @@ export const addSort = (options: {
const menu = new Menu("av-add-sort"); const menu = new Menu("av-add-sort");
options.data.view.columns.forEach((column) => { options.data.view.columns.forEach((column) => {
let hasSort = false; let hasSort = false;
// 如果该列是行号类型列,不允许添加排序
if (column.type === "lineNumber") {
hasSort = true;
} else {
options.data.view.sorts.find((sort) => { options.data.view.sorts.find((sort) => {
if (sort.column === column.id) { if (sort.column === column.id) {
hasSort = true; hasSort = true;
return true; return true;
} }
}); });
}
if (!hasSort) { if (!hasSort) {
menu.addItem({ menu.addItem({
label: column.name, label: column.name,

View file

@ -82,6 +82,7 @@ type TAVCol =
| "created" | "created"
| "updated" | "updated"
| "checkbox" | "checkbox"
| "lineNumber"
type THintSource = "search" | "av" | "hint"; type THintSource = "search" | "av" | "hint";
type TAVFilterOperator = type TAVFilterOperator =
"=" "="

View file

@ -80,6 +80,7 @@ const (
KeyTypeCheckbox KeyType = "checkbox" KeyTypeCheckbox KeyType = "checkbox"
KeyTypeRelation KeyType = "relation" KeyTypeRelation KeyType = "relation"
KeyTypeRollup KeyType = "rollup" KeyTypeRollup KeyType = "rollup"
KeyTypeLineNumber KeyType = "lineNumber"
) )
// Key 描述了属性视图属性列的基础结构。 // Key 描述了属性视图属性列的基础结构。

View file

@ -220,59 +220,62 @@ func (value *Value) Compare(other *Value, attrView *AttributeView) int {
} }
case KeyTypeRelation: case KeyTypeRelation:
if nil != value.Relation && nil != other.Relation { if nil != value.Relation && nil != other.Relation {
if 1 < len(value.Relation.Contents) && 1 < len(other.Relation.Contents) && KeyTypeNumber == value.Relation.Contents[0].Type && KeyTypeNumber == other.Relation.Contents[0].Type {
v1, ok1 := util.Convert2Float(value.Relation.Contents[0].String(false))
v2, ok2 := util.Convert2Float(other.Relation.Contents[0].String(false))
if ok1 && ok2 {
if v1 > v2 {
return 1
}
if v1 < v2 {
return -1
}
return 0
}
}
vContentBuf := bytes.Buffer{} vContentBuf := bytes.Buffer{}
for _, c := range value.Relation.Contents { for _, c := range value.Relation.Contents {
vContentBuf.WriteString(c.String()) vContentBuf.WriteString(c.String(true))
vContentBuf.WriteByte(' ') vContentBuf.WriteByte(' ')
} }
vContent := strings.TrimSpace(vContentBuf.String()) vContent := strings.TrimSpace(vContentBuf.String())
oContentBuf := bytes.Buffer{} oContentBuf := bytes.Buffer{}
for _, c := range other.Relation.Contents { for _, c := range other.Relation.Contents {
oContentBuf.WriteString(c.String()) oContentBuf.WriteString(c.String(true))
oContentBuf.WriteByte(' ') oContentBuf.WriteByte(' ')
} }
oContent := strings.TrimSpace(oContentBuf.String()) oContent := strings.TrimSpace(oContentBuf.String())
return strings.Compare(vContent, oContent)
v1, ok1 := util.Convert2Float(vContent) }
v2, ok2 := util.Convert2Float(oContent) case KeyTypeRollup:
if nil != value.Rollup && nil != other.Rollup {
if 1 < len(value.Rollup.Contents) && 1 < len(other.Rollup.Contents) && KeyTypeNumber == value.Rollup.Contents[0].Type && KeyTypeNumber == other.Rollup.Contents[0].Type {
v1, ok1 := util.Convert2Float(value.Rollup.Contents[0].String(false))
v2, ok2 := util.Convert2Float(other.Rollup.Contents[0].String(false))
if ok1 && ok2 { if ok1 && ok2 {
if v1 > v2 { if v1 > v2 {
return 1 return 1
} }
if v1 < v2 { if v1 < v2 {
return -1 return -1
} }
return 0 return 0
} }
return strings.Compare(vContent, oContent)
} }
case KeyTypeRollup:
if nil != value.Rollup && nil != other.Rollup {
vContentBuf := bytes.Buffer{} vContentBuf := bytes.Buffer{}
for _, c := range value.Rollup.Contents { for _, c := range value.Rollup.Contents {
vContentBuf.WriteString(c.String()) vContentBuf.WriteString(c.String(true))
vContentBuf.WriteByte(' ') vContentBuf.WriteByte(' ')
} }
vContent := strings.TrimSpace(vContentBuf.String()) vContent := strings.TrimSpace(vContentBuf.String())
oContentBuf := bytes.Buffer{} oContentBuf := bytes.Buffer{}
for _, c := range other.Rollup.Contents { for _, c := range other.Rollup.Contents {
oContentBuf.WriteString(c.String()) oContentBuf.WriteString(c.String(true))
oContentBuf.WriteByte(' ') oContentBuf.WriteByte(' ')
} }
oContent := strings.TrimSpace(oContentBuf.String()) oContent := strings.TrimSpace(oContentBuf.String())
v1, ok1 := util.Convert2Float(vContent)
v2, ok2 := util.Convert2Float(oContent)
if ok1 && ok2 {
if v1 > v2 {
return 1
}
if v1 < v2 {
return -1
}
return 0
}
return strings.Compare(vContent, oContent) return strings.Compare(vContent, oContent)
} }
} }

View file

@ -1586,8 +1586,8 @@ func (table *Table) calcColRollup(col *TableColumn, colIndex int) {
for _, row := range table.Rows { for _, row := range table.Rows {
if nil != row.Cells[colIndex] && nil != row.Cells[colIndex].Value && nil != row.Cells[colIndex].Value.Rollup { if nil != row.Cells[colIndex] && nil != row.Cells[colIndex].Value && nil != row.Cells[colIndex].Value.Rollup {
for _, content := range row.Cells[colIndex].Value.Rollup.Contents { for _, content := range row.Cells[colIndex].Value.Rollup.Contents {
if !uniqueValues[content.String()] { if !uniqueValues[content.String(true)] {
uniqueValues[content.String()] = true uniqueValues[content.String(true)] = true
countUniqueValues++ countUniqueValues++
} }
} }
@ -1635,7 +1635,7 @@ func (table *Table) calcColRollup(col *TableColumn, colIndex int) {
for _, row := range table.Rows { for _, row := range table.Rows {
if nil != row.Cells[colIndex] && nil != row.Cells[colIndex].Value && nil != row.Cells[colIndex].Value.Rollup && 0 < len(row.Cells[colIndex].Value.Rollup.Contents) { if nil != row.Cells[colIndex] && nil != row.Cells[colIndex].Value && nil != row.Cells[colIndex].Value.Rollup && 0 < len(row.Cells[colIndex].Value.Rollup.Contents) {
for _, content := range row.Cells[colIndex].Value.Rollup.Contents { for _, content := range row.Cells[colIndex].Value.Rollup.Contents {
val, _ := util.Convert2Float(content.String()) val, _ := util.Convert2Float(content.String(false))
sum += val sum += val
} }
} }
@ -1647,7 +1647,7 @@ func (table *Table) calcColRollup(col *TableColumn, colIndex int) {
for _, row := range table.Rows { for _, row := range table.Rows {
if nil != row.Cells[colIndex] && nil != row.Cells[colIndex].Value && nil != row.Cells[colIndex].Value.Rollup && 0 < len(row.Cells[colIndex].Value.Rollup.Contents) { if nil != row.Cells[colIndex] && nil != row.Cells[colIndex].Value && nil != row.Cells[colIndex].Value.Rollup && 0 < len(row.Cells[colIndex].Value.Rollup.Contents) {
for _, content := range row.Cells[colIndex].Value.Rollup.Contents { for _, content := range row.Cells[colIndex].Value.Rollup.Contents {
val, _ := util.Convert2Float(content.String()) val, _ := util.Convert2Float(content.String(false))
sum += val sum += val
count++ count++
} }
@ -1661,7 +1661,7 @@ func (table *Table) calcColRollup(col *TableColumn, colIndex int) {
for _, row := range table.Rows { for _, row := range table.Rows {
if nil != row.Cells[colIndex] && nil != row.Cells[colIndex].Value && nil != row.Cells[colIndex].Value.Rollup && 0 < len(row.Cells[colIndex].Value.Rollup.Contents) { if nil != row.Cells[colIndex] && nil != row.Cells[colIndex].Value && nil != row.Cells[colIndex].Value.Rollup && 0 < len(row.Cells[colIndex].Value.Rollup.Contents) {
for _, content := range row.Cells[colIndex].Value.Rollup.Contents { for _, content := range row.Cells[colIndex].Value.Rollup.Contents {
val, _ := util.Convert2Float(content.String()) val, _ := util.Convert2Float(content.String(false))
values = append(values, val) values = append(values, val)
} }
} }
@ -1679,7 +1679,7 @@ func (table *Table) calcColRollup(col *TableColumn, colIndex int) {
for _, row := range table.Rows { for _, row := range table.Rows {
if nil != row.Cells[colIndex] && nil != row.Cells[colIndex].Value && nil != row.Cells[colIndex].Value.Rollup && 0 < len(row.Cells[colIndex].Value.Rollup.Contents) { if nil != row.Cells[colIndex] && nil != row.Cells[colIndex].Value && nil != row.Cells[colIndex].Value.Rollup && 0 < len(row.Cells[colIndex].Value.Rollup.Contents) {
for _, content := range row.Cells[colIndex].Value.Rollup.Contents { for _, content := range row.Cells[colIndex].Value.Rollup.Contents {
val, _ := util.Convert2Float(content.String()) val, _ := util.Convert2Float(content.String(false))
if val < minVal { if val < minVal {
minVal = val minVal = val
} }
@ -1694,7 +1694,7 @@ func (table *Table) calcColRollup(col *TableColumn, colIndex int) {
for _, row := range table.Rows { for _, row := range table.Rows {
if nil != row.Cells[colIndex] && nil != row.Cells[colIndex].Value && nil != row.Cells[colIndex].Value.Rollup && 0 < len(row.Cells[colIndex].Value.Rollup.Contents) { if nil != row.Cells[colIndex] && nil != row.Cells[colIndex].Value && nil != row.Cells[colIndex].Value.Rollup && 0 < len(row.Cells[colIndex].Value.Rollup.Contents) {
for _, content := range row.Cells[colIndex].Value.Rollup.Contents { for _, content := range row.Cells[colIndex].Value.Rollup.Contents {
val, _ := util.Convert2Float(content.String()) val, _ := util.Convert2Float(content.String(false))
if val > maxVal { if val > maxVal {
maxVal = val maxVal = val
} }
@ -1710,7 +1710,7 @@ func (table *Table) calcColRollup(col *TableColumn, colIndex int) {
for _, row := range table.Rows { for _, row := range table.Rows {
if nil != row.Cells[colIndex] && nil != row.Cells[colIndex].Value && nil != row.Cells[colIndex].Value.Rollup && 0 < len(row.Cells[colIndex].Value.Rollup.Contents) { if nil != row.Cells[colIndex] && nil != row.Cells[colIndex].Value && nil != row.Cells[colIndex].Value.Rollup && 0 < len(row.Cells[colIndex].Value.Rollup.Contents) {
for _, content := range row.Cells[colIndex].Value.Rollup.Contents { for _, content := range row.Cells[colIndex].Value.Rollup.Contents {
val, _ := util.Convert2Float(content.String()) val, _ := util.Convert2Float(content.String(false))
if val < minVal { if val < minVal {
minVal = val minVal = val
} }

View file

@ -64,7 +64,7 @@ func (value *Value) SetUpdatedAt(mills int64) {
} }
} }
func (value *Value) String() string { func (value *Value) String(format bool) string {
if nil == value { if nil == value {
return "" return ""
} }
@ -84,7 +84,10 @@ func (value *Value) String() string {
if nil == value.Number { if nil == value.Number {
return "" return ""
} }
if format {
return value.Number.FormattedContent return value.Number.FormattedContent
}
return fmt.Sprintf("%f", value.Number.Content)
case KeyTypeDate: case KeyTypeDate:
if nil == value.Date { if nil == value.Date {
return "" return ""
@ -158,7 +161,7 @@ func (value *Value) String() string {
} }
var ret []string var ret []string
for _, v := range value.Relation.Contents { for _, v := range value.Relation.Contents {
ret = append(ret, v.String()) ret = append(ret, v.String(format))
} }
return strings.TrimSpace(strings.Join(ret, ", ")) return strings.TrimSpace(strings.Join(ret, ", "))
case KeyTypeRollup: case KeyTypeRollup:
@ -167,7 +170,7 @@ func (value *Value) String() string {
} }
var ret []string var ret []string
for _, v := range value.Rollup.Contents { for _, v := range value.Rollup.Contents {
ret = append(ret, v.String()) ret = append(ret, v.String(format))
} }
return strings.TrimSpace(strings.Join(ret, ", ")) return strings.TrimSpace(strings.Join(ret, ", "))
default: default:
@ -679,8 +682,8 @@ func (r *ValueRollup) RenderContents(calc *RollupCalc, destKey *Key) {
countUniqueValues := 0 countUniqueValues := 0
uniqueValues := map[string]bool{} uniqueValues := map[string]bool{}
for _, v := range r.Contents { for _, v := range r.Contents {
if _, ok := uniqueValues[v.String()]; !ok { if _, ok := uniqueValues[v.String(true)]; !ok {
uniqueValues[v.String()] = true uniqueValues[v.String(true)] = true
countUniqueValues++ countUniqueValues++
} }
} }
@ -688,7 +691,7 @@ func (r *ValueRollup) RenderContents(calc *RollupCalc, destKey *Key) {
case CalcOperatorCountEmpty: case CalcOperatorCountEmpty:
countEmpty := 0 countEmpty := 0
for _, v := range r.Contents { for _, v := range r.Contents {
if "" == v.String() { if "" == v.String(true) {
countEmpty++ countEmpty++
} }
} }
@ -696,7 +699,7 @@ func (r *ValueRollup) RenderContents(calc *RollupCalc, destKey *Key) {
case CalcOperatorCountNotEmpty: case CalcOperatorCountNotEmpty:
countNonEmpty := 0 countNonEmpty := 0
for _, v := range r.Contents { for _, v := range r.Contents {
if "" != v.String() { if "" != v.String(true) {
countNonEmpty++ countNonEmpty++
} }
} }
@ -704,7 +707,7 @@ func (r *ValueRollup) RenderContents(calc *RollupCalc, destKey *Key) {
case CalcOperatorPercentEmpty: case CalcOperatorPercentEmpty:
countEmpty := 0 countEmpty := 0
for _, v := range r.Contents { for _, v := range r.Contents {
if "" == v.String() { if "" == v.String(true) {
countEmpty++ countEmpty++
} }
} }
@ -714,7 +717,7 @@ func (r *ValueRollup) RenderContents(calc *RollupCalc, destKey *Key) {
case CalcOperatorPercentNotEmpty: case CalcOperatorPercentNotEmpty:
countNonEmpty := 0 countNonEmpty := 0
for _, v := range r.Contents { for _, v := range r.Contents {
if "" != v.String() { if "" != v.String(true) {
countNonEmpty++ countNonEmpty++
} }
} }

View file

@ -17,7 +17,6 @@
package bazaar package bazaar
import ( import (
"errors"
"os" "os"
"path/filepath" "path/filepath"
"sort" "sort"
@ -184,14 +183,9 @@ func InstallIcon(repoURL, repoHash, installPath string, systemID string) error {
if nil != err { if nil != err {
return err return err
} }
return installPackage(data, installPath) return installPackage(data, installPath, repoURLHash)
} }
func UninstallIcon(installPath string) error { func UninstallIcon(installPath string) error {
if err := os.RemoveAll(installPath); nil != err { return uninstallPackage(installPath)
logging.LogErrorf("remove icon [%s] failed: %s", installPath, err)
return errors.New("remove community icon failed")
}
//logging.Logger.Infof("uninstalled icon [%s]", installPath)
return nil
} }

View file

@ -19,6 +19,7 @@ package bazaar
import ( import (
"bytes" "bytes"
"errors" "errors"
"fmt"
"os" "os"
"path/filepath" "path/filepath"
"strings" "strings"
@ -588,7 +589,26 @@ func incPackageDownloads(repoURLHash, systemID string) {
}).Post(u) }).Post(u)
} }
func installPackage(data []byte, installPath string) (err error) { func uninstallPackage(installPath string) (err error) {
if err = os.RemoveAll(installPath); nil != err {
logging.LogErrorf("remove [%s] failed: %s", installPath, err)
return fmt.Errorf("remove community package [%s] failed", filepath.Base(installPath))
}
packageCache.Flush()
return
}
func installPackage(data []byte, installPath, repoURLHash string) (err error) {
err = installPackage0(data, installPath)
if nil != err {
return
}
packageCache.Delete(strings.TrimPrefix(repoURLHash, "https://github.com/"))
return
}
func installPackage0(data []byte, installPath string) (err error) {
tmpPackage := filepath.Join(util.TempDir, "bazaar", "package") tmpPackage := filepath.Join(util.TempDir, "bazaar", "package")
if err = os.MkdirAll(tmpPackage, 0755); nil != err { if err = os.MkdirAll(tmpPackage, 0755); nil != err {
return return

View file

@ -17,7 +17,6 @@
package bazaar package bazaar
import ( import (
"errors"
"os" "os"
"path/filepath" "path/filepath"
"runtime" "runtime"
@ -27,7 +26,6 @@ import (
"github.com/dustin/go-humanize" "github.com/dustin/go-humanize"
ants "github.com/panjf2000/ants/v2" ants "github.com/panjf2000/ants/v2"
"github.com/siyuan-note/filelock"
"github.com/siyuan-note/httpclient" "github.com/siyuan-note/httpclient"
"github.com/siyuan-note/logging" "github.com/siyuan-note/logging"
"github.com/siyuan-note/siyuan/kernel/util" "github.com/siyuan-note/siyuan/kernel/util"
@ -220,16 +218,11 @@ func InstallPlugin(repoURL, repoHash, installPath string, systemID string) error
if nil != err { if nil != err {
return err return err
} }
return installPackage(data, installPath) return installPackage(data, installPath, repoURLHash)
} }
func UninstallPlugin(installPath string) error { func UninstallPlugin(installPath string) error {
if err := filelock.Remove(installPath); nil != err { return uninstallPackage(installPath)
logging.LogErrorf("remove plugin [%s] failed: %s", installPath, err)
return errors.New("remove community plugin failed")
}
//logging.Logger.Infof("uninstalled plugin [%s]", installPath)
return nil
} }
func isIncompatiblePlugin(plugin *Plugin, currentFrontend string) bool { func isIncompatiblePlugin(plugin *Plugin, currentFrontend string) bool {

View file

@ -17,7 +17,6 @@
package bazaar package bazaar
import ( import (
"errors"
"os" "os"
"path/filepath" "path/filepath"
"sort" "sort"
@ -27,7 +26,6 @@ import (
"github.com/dustin/go-humanize" "github.com/dustin/go-humanize"
"github.com/panjf2000/ants/v2" "github.com/panjf2000/ants/v2"
"github.com/siyuan-note/filelock"
"github.com/siyuan-note/httpclient" "github.com/siyuan-note/httpclient"
"github.com/siyuan-note/logging" "github.com/siyuan-note/logging"
"github.com/siyuan-note/siyuan/kernel/util" "github.com/siyuan-note/siyuan/kernel/util"
@ -182,15 +180,11 @@ func InstallTemplate(repoURL, repoHash, installPath string, systemID string) err
if nil != err { if nil != err {
return err return err
} }
return installPackage(data, installPath) return installPackage(data, installPath, repoURLHash)
} }
func UninstallTemplate(installPath string) error { func UninstallTemplate(installPath string) error {
if err := filelock.Remove(installPath); nil != err { return uninstallPackage(installPath)
logging.LogErrorf("remove template [%s] failed: %s", installPath, err)
return errors.New("remove community template failed")
}
return nil
} }
func filterLegacyTemplates(templates []*Template) (ret []*Template) { func filterLegacyTemplates(templates []*Template) (ret []*Template) {

View file

@ -17,7 +17,6 @@
package bazaar package bazaar
import ( import (
"errors"
"os" "os"
"path/filepath" "path/filepath"
"sort" "sort"
@ -186,14 +185,9 @@ func InstallTheme(repoURL, repoHash, installPath string, systemID string) error
if nil != err { if nil != err {
return err return err
} }
return installPackage(data, installPath) return installPackage(data, installPath, repoURLHash)
} }
func UninstallTheme(installPath string) error { func UninstallTheme(installPath string) error {
if err := os.RemoveAll(installPath); nil != err { return uninstallPackage(installPath)
logging.LogErrorf("remove theme [%s] failed: %s", installPath, err)
return errors.New("remove community theme failed")
}
//logging.Logger.Infof("uninstalled theme [%s]", installPath)
return nil
} }

View file

@ -17,7 +17,6 @@
package bazaar package bazaar
import ( import (
"errors"
"os" "os"
"path/filepath" "path/filepath"
"sort" "sort"
@ -26,7 +25,6 @@ import (
"github.com/dustin/go-humanize" "github.com/dustin/go-humanize"
ants "github.com/panjf2000/ants/v2" ants "github.com/panjf2000/ants/v2"
"github.com/siyuan-note/filelock"
"github.com/siyuan-note/httpclient" "github.com/siyuan-note/httpclient"
"github.com/siyuan-note/logging" "github.com/siyuan-note/logging"
"github.com/siyuan-note/siyuan/kernel/util" "github.com/siyuan-note/siyuan/kernel/util"
@ -180,14 +178,9 @@ func InstallWidget(repoURL, repoHash, installPath string, systemID string) error
if nil != err { if nil != err {
return err return err
} }
return installPackage(data, installPath) return installPackage(data, installPath, repoURLHash)
} }
func UninstallWidget(installPath string) error { func UninstallWidget(installPath string) error {
if err := filelock.Remove(installPath); nil != err { return uninstallPackage(installPath)
logging.LogErrorf("remove widget [%s] failed: %s", installPath, err)
return errors.New("remove community widget failed")
}
//logging.Logger.Infof("uninstalled widget [%s]", installPath)
return nil
} }

View file

@ -89,7 +89,7 @@ func GetAttributeViewPrimaryKeyValues(avID, keyword string, page, pageSize int)
} }
keyValues.Values = []*av.Value{} keyValues.Values = []*av.Value{}
for _, v := range tmp { for _, v := range tmp {
if strings.Contains(strings.ToLower(v.String()), strings.ToLower(keyword)) { if strings.Contains(strings.ToLower(v.String(true)), strings.ToLower(keyword)) {
keyValues.Values = append(keyValues.Values, v) keyValues.Values = append(keyValues.Values, v)
} }
} }
@ -145,7 +145,7 @@ func SearchAttributeViewNonRelationKey(avID, keyword string) (ret []*av.Key) {
} }
for _, keyValues := range attrView.KeyValues { for _, keyValues := range attrView.KeyValues {
if av.KeyTypeRelation != keyValues.Key.Type && av.KeyTypeRollup != keyValues.Key.Type && av.KeyTypeTemplate != keyValues.Key.Type && av.KeyTypeCreated != keyValues.Key.Type && av.KeyTypeUpdated != keyValues.Key.Type { if av.KeyTypeRelation != keyValues.Key.Type && av.KeyTypeRollup != keyValues.Key.Type && av.KeyTypeTemplate != keyValues.Key.Type && av.KeyTypeCreated != keyValues.Key.Type && av.KeyTypeUpdated != keyValues.Key.Type && av.KeyTypeLineNumber != keyValues.Key.Type {
if strings.Contains(strings.ToLower(keyValues.Key.Name), strings.ToLower(keyword)) { if strings.Contains(strings.ToLower(keyValues.Key.Name), strings.ToLower(keyword)) {
ret = append(ret, keyValues.Key) ret = append(ret, keyValues.Key)
} }
@ -905,14 +905,33 @@ func renderTemplateCol(ial map[string]string, flashcard *Flashcard, rowValues []
dataModel[rowValue.Key.Name] = time.UnixMilli(v.Date.Content) dataModel[rowValue.Key.Name] = time.UnixMilli(v.Date.Content)
} }
} else if av.KeyTypeRollup == v.Type { } else if av.KeyTypeRollup == v.Type {
if 0 < len(v.Rollup.Contents) && av.KeyTypeNumber == v.Rollup.Contents[0].Type { if 0 < len(v.Rollup.Contents) {
// 模板使用汇总时支持数字计算 var numbers []float64
// Template supports numerical calculations when using rollup https://github.com/siyuan-note/siyuan/issues/10810 var contents []string
// 汇总数字时仅取第一个数字填充模板 for _, content := range v.Rollup.Contents {
dataModel[rowValue.Key.Name] = v.Rollup.Contents[0].Number.Content if av.KeyTypeNumber == content.Type {
numbers = append(numbers, content.Number.Content)
} else {
contents = append(contents, content.String(true))
}
}
if 0 < len(numbers) {
dataModel[rowValue.Key.Name] = numbers
} else {
dataModel[rowValue.Key.Name] = contents
}
}
} else if av.KeyTypeRelation == v.Type {
if 0 < len(v.Relation.Contents) {
var contents []string
for _, content := range v.Relation.Contents {
contents = append(contents, content.String(true))
}
dataModel[rowValue.Key.Name] = contents
} }
} else { } else {
dataModel[rowValue.Key.Name] = v.String() dataModel[rowValue.Key.Name] = v.String(true)
} }
} }
} }
@ -1218,7 +1237,7 @@ func renderAttributeViewTable(attrView *av.AttributeView, view *av.View, query s
hit := false hit := false
for _, cell := range row.Cells { for _, cell := range row.Cells {
for _, keyword := range keywords { for _, keyword := range keywords {
if strings.Contains(strings.ToLower(cell.Value.String()), strings.ToLower(keyword)) { if strings.Contains(strings.ToLower(cell.Value.String(true)), strings.ToLower(keyword)) {
hit = true hit = true
break break
} }
@ -2635,7 +2654,7 @@ func AddAttributeViewKey(avID, keyID, keyName, keyType, keyIcon, previousKeyID s
switch keyTyp { switch keyTyp {
case av.KeyTypeText, av.KeyTypeNumber, av.KeyTypeDate, av.KeyTypeSelect, av.KeyTypeMSelect, av.KeyTypeURL, av.KeyTypeEmail, case av.KeyTypeText, av.KeyTypeNumber, av.KeyTypeDate, av.KeyTypeSelect, av.KeyTypeMSelect, av.KeyTypeURL, av.KeyTypeEmail,
av.KeyTypePhone, av.KeyTypeMAsset, av.KeyTypeTemplate, av.KeyTypeCreated, av.KeyTypeUpdated, av.KeyTypeCheckbox, av.KeyTypePhone, av.KeyTypeMAsset, av.KeyTypeTemplate, av.KeyTypeCreated, av.KeyTypeUpdated, av.KeyTypeCheckbox,
av.KeyTypeRelation, av.KeyTypeRollup: av.KeyTypeRelation, av.KeyTypeRollup, av.KeyTypeLineNumber:
key := av.NewKey(keyID, keyName, keyIcon, keyTyp) key := av.NewKey(keyID, keyName, keyIcon, keyTyp)
if av.KeyTypeRollup == keyTyp { if av.KeyTypeRollup == keyTyp {
@ -2747,7 +2766,7 @@ func updateAttributeViewColumn(operation *Operation) (err error) {
switch colType { switch colType {
case av.KeyTypeBlock, av.KeyTypeText, av.KeyTypeNumber, av.KeyTypeDate, av.KeyTypeSelect, av.KeyTypeMSelect, av.KeyTypeURL, av.KeyTypeEmail, case av.KeyTypeBlock, av.KeyTypeText, av.KeyTypeNumber, av.KeyTypeDate, av.KeyTypeSelect, av.KeyTypeMSelect, av.KeyTypeURL, av.KeyTypeEmail,
av.KeyTypePhone, av.KeyTypeMAsset, av.KeyTypeTemplate, av.KeyTypeCreated, av.KeyTypeUpdated, av.KeyTypeCheckbox, av.KeyTypePhone, av.KeyTypeMAsset, av.KeyTypeTemplate, av.KeyTypeCreated, av.KeyTypeUpdated, av.KeyTypeCheckbox,
av.KeyTypeRelation, av.KeyTypeRollup: av.KeyTypeRelation, av.KeyTypeRollup, av.KeyTypeLineNumber:
for _, keyValues := range attrView.KeyValues { for _, keyValues := range attrView.KeyValues {
if keyValues.Key.ID == operation.ID { if keyValues.Key.ID == operation.ID {
keyValues.Key.Name = strings.TrimSpace(operation.Name) keyValues.Key.Name = strings.TrimSpace(operation.Name)

View file

@ -19,16 +19,17 @@ package model
import ( import (
"errors" "errors"
"fmt" "fmt"
"github.com/88250/gulu"
"github.com/siyuan-note/logging"
"github.com/siyuan-note/siyuan/kernel/util"
"path" "path"
"path/filepath" "path/filepath"
"strings" "strings"
"sync" "sync"
"time" "time"
"github.com/88250/gulu"
"github.com/siyuan-note/logging"
"github.com/siyuan-note/siyuan/kernel/bazaar" "github.com/siyuan-note/siyuan/kernel/bazaar"
"github.com/siyuan-note/siyuan/kernel/util"
"golang.org/x/mod/semver"
) )
func BatchUpdateBazaarPackages(frontend string) { func BatchUpdateBazaarPackages(frontend string) {
@ -202,9 +203,7 @@ func BazaarPlugins(frontend, keyword string) (plugins []*bazaar.Plugin) {
plugin.Installed = util.IsPathRegularDirOrSymlinkDir(filepath.Join(util.DataDir, "plugins", plugin.Name)) plugin.Installed = util.IsPathRegularDirOrSymlinkDir(filepath.Join(util.DataDir, "plugins", plugin.Name))
if plugin.Installed { if plugin.Installed {
if pluginConf, err := bazaar.PluginJSON(plugin.Name); nil == err && nil != plugin { if pluginConf, err := bazaar.PluginJSON(plugin.Name); nil == err && nil != plugin {
if plugin.Version != pluginConf.Version { plugin.Outdated = 0 > semver.Compare("v"+pluginConf.Version, "v"+plugin.Version)
plugin.Outdated = true
}
} }
} }
} }
@ -273,9 +272,7 @@ func BazaarWidgets(keyword string) (widgets []*bazaar.Widget) {
widget.Installed = util.IsPathRegularDirOrSymlinkDir(filepath.Join(util.DataDir, "widgets", widget.Name)) widget.Installed = util.IsPathRegularDirOrSymlinkDir(filepath.Join(util.DataDir, "widgets", widget.Name))
if widget.Installed { if widget.Installed {
if widgetConf, err := bazaar.WidgetJSON(widget.Name); nil == err && nil != widget { if widgetConf, err := bazaar.WidgetJSON(widget.Name); nil == err && nil != widget {
if widget.Version != widgetConf.Version { widget.Outdated = 0 > semver.Compare("v"+widgetConf.Version, "v"+widget.Version)
widget.Outdated = true
}
} }
} }
} }
@ -324,10 +321,8 @@ func BazaarIcons(keyword string) (icons []*bazaar.Icon) {
for _, icon := range icons { for _, icon := range icons {
if installed == icon.Name { if installed == icon.Name {
icon.Installed = true icon.Installed = true
if themeConf, err := bazaar.IconJSON(icon.Name); nil == err { if iconConf, err := bazaar.IconJSON(icon.Name); nil == err {
if icon.Version != themeConf.Version { icon.Outdated = 0 > semver.Compare("v"+iconConf.Version, "v"+icon.Version)
icon.Outdated = true
}
} }
} }
icon.Current = icon.Name == Conf.Appearance.Icon icon.Current = icon.Name == Conf.Appearance.Icon
@ -389,7 +384,7 @@ func BazaarThemes(keyword string) (ret []*bazaar.Theme) {
if installed == theme.Name { if installed == theme.Name {
theme.Installed = true theme.Installed = true
if themeConf, err := bazaar.ThemeJSON(theme.Name); nil == err { if themeConf, err := bazaar.ThemeJSON(theme.Name); nil == err {
theme.Outdated = theme.Version != themeConf.Version theme.Outdated = 0 > semver.Compare("v"+themeConf.Version, "v"+theme.Version)
} }
theme.Current = theme.Name == Conf.Appearance.ThemeDark || theme.Name == Conf.Appearance.ThemeLight theme.Current = theme.Name == Conf.Appearance.ThemeDark || theme.Name == Conf.Appearance.ThemeLight
} }
@ -462,10 +457,8 @@ func BazaarTemplates(keyword string) (templates []*bazaar.Template) {
for _, template := range templates { for _, template := range templates {
template.Installed = util.IsPathRegularDirOrSymlinkDir(filepath.Join(util.DataDir, "templates", template.Name)) template.Installed = util.IsPathRegularDirOrSymlinkDir(filepath.Join(util.DataDir, "templates", template.Name))
if template.Installed { if template.Installed {
if themeConf, err := bazaar.TemplateJSON(template.Name); nil == err && nil != themeConf { if templateConf, err := bazaar.TemplateJSON(template.Name); nil == err && nil != templateConf {
if template.Version != themeConf.Version { template.Outdated = 0 > semver.Compare("v"+templateConf.Version, "v"+template.Version)
template.Outdated = true
}
} }
} }
} }

View file

@ -506,14 +506,15 @@ func FullReindex() {
} }
func fullReindex() { func fullReindex() {
util.PushMsg(Conf.Language(35), 7*1000) util.PushEndlessProgress(Conf.language(35))
defer util.PushClearProgress()
WaitForWritingFiles() WaitForWritingFiles()
if err := sql.InitDatabase(true); nil != err { if err := sql.InitDatabase(true); nil != err {
os.Exit(logging.ExitCodeReadOnlyDatabase) os.Exit(logging.ExitCodeReadOnlyDatabase)
return return
} }
treenode.InitBlockTree(true)
sql.IndexIgnoreCached = false sql.IndexIgnoreCached = false
openedBoxes := Conf.GetOpenedBoxes() openedBoxes := Conf.GetOpenedBoxes()

View file

@ -148,7 +148,7 @@ func ExportAv2CSV(avID, blockID string) (zipPath string, err error) {
} }
} }
val = cell.Value.String() val = cell.Value.String(true)
} }
rowVal = append(rowVal, val) rowVal = append(rowVal, val)
@ -2335,7 +2335,7 @@ func exportTree(tree *parse.Tree, wysiwyg, expandKaTexMacros, keepFold bool,
} }
} }
val = cell.Value.String() val = cell.Value.String(true)
} }
mdTableCell.AppendChild(&ast.Node{Type: ast.NodeText, Tokens: []byte(val)}) mdTableCell.AppendChild(&ast.Node{Type: ast.NodeText, Tokens: []byte(val)})
} }

View file

@ -162,7 +162,7 @@ func LoadTreeByBlockIDWithReindex(id string) (ret *parse.Tree, err error) {
bt := treenode.GetBlockTree(id) bt := treenode.GetBlockTree(id)
if nil == bt { if nil == bt {
if task.Contain(task.DatabaseIndex, task.DatabaseIndexFull) { if task.ContainIndexTask() {
err = ErrIndexing err = ErrIndexing
return return
} }
@ -187,7 +187,7 @@ func LoadTreeByBlockID(id string) (ret *parse.Tree, err error) {
bt := treenode.GetBlockTree(id) bt := treenode.GetBlockTree(id)
if nil == bt { if nil == bt {
if task.Contain(task.DatabaseIndex, task.DatabaseIndexFull) { if task.ContainIndexTask() {
err = ErrIndexing err = ErrIndexing
return return
} }

View file

@ -115,17 +115,13 @@ var uniqueActions = []string{
AssetContentDatabaseIndexCommit, AssetContentDatabaseIndexCommit,
} }
func Contain(action string, moreActions ...string) bool { func ContainIndexTask() bool {
actions := append(moreActions, action) actions := getCurrentActions()
actions = gulu.Str.RemoveDuplicatedElem(actions) for _, action := range actions {
if gulu.Str.Contains(action, []string{DatabaseIndexFull, DatabaseIndex}) {
queueLock.Lock()
for _, task := range taskQueue {
if gulu.Str.Contains(task.Action, actions) {
return true return true
} }
} }
queueLock.Unlock()
return false return false
} }

View file

@ -31,6 +31,7 @@ import (
"github.com/panjf2000/ants/v2" "github.com/panjf2000/ants/v2"
util2 "github.com/siyuan-note/dejavu/util" util2 "github.com/siyuan-note/dejavu/util"
"github.com/siyuan-note/logging" "github.com/siyuan-note/logging"
"github.com/siyuan-note/siyuan/kernel/task"
"github.com/siyuan-note/siyuan/kernel/util" "github.com/siyuan-note/siyuan/kernel/util"
"github.com/vmihailenco/msgpack/v5" "github.com/vmihailenco/msgpack/v5"
) )
@ -504,6 +505,12 @@ func SaveBlockTree(force bool) {
blockTreeLock.Lock() blockTreeLock.Lock()
defer blockTreeLock.Unlock() defer blockTreeLock.Unlock()
if task.ContainIndexTask() {
//logging.LogInfof("skip saving block tree because indexing")
return
}
//logging.LogInfof("saving block tree")
start := time.Now() start := time.Now()
if err := os.MkdirAll(util.BlockTreePath, 0755); nil != err { if err := os.MkdirAll(util.BlockTreePath, 0755); nil != err {
logging.LogErrorf("create block tree dir [%s] failed: %s", util.BlockTreePath, err) logging.LogErrorf("create block tree dir [%s] failed: %s", util.BlockTreePath, err)

View file

@ -598,7 +598,7 @@ func getAttributeViewContent(avID string) (content string) {
if nil == cell.Value { if nil == cell.Value {
continue continue
} }
buf.WriteString(cell.Value.String()) buf.WriteString(cell.Value.String(true))
buf.WriteByte(' ') buf.WriteByte(' ')
} }
} }
@ -1050,12 +1050,33 @@ func renderTemplateCol(ial map[string]string, rowValues []*av.KeyValues, tplCont
dataModel[rowValue.Key.Name] = time.UnixMilli(v.Date.Content) dataModel[rowValue.Key.Name] = time.UnixMilli(v.Date.Content)
} }
} else if av.KeyTypeRollup == v.Type { } else if av.KeyTypeRollup == v.Type {
if 0 < len(v.Rollup.Contents) && av.KeyTypeNumber == v.Rollup.Contents[0].Type { if 0 < len(v.Rollup.Contents) {
// 汇总数字时仅取第一个数字填充模板 var numbers []float64
dataModel[rowValue.Key.Name] = v.Rollup.Contents[0].Number.Content var contents []string
for _, content := range v.Rollup.Contents {
if av.KeyTypeNumber == content.Type {
numbers = append(numbers, content.Number.Content)
} else {
contents = append(contents, content.String(true))
}
}
if 0 < len(numbers) {
dataModel[rowValue.Key.Name] = numbers
} else {
dataModel[rowValue.Key.Name] = contents
}
}
} else if av.KeyTypeRelation == v.Type {
if 0 < len(v.Relation.Contents) {
var contents []string
for _, content := range v.Relation.Contents {
contents = append(contents, content.String(true))
}
dataModel[rowValue.Key.Name] = contents
} }
} else { } else {
dataModel[rowValue.Key.Name] = v.String() dataModel[rowValue.Key.Name] = v.String(true)
} }
} }
} }