diff --git a/app/src/assets/scss/business/_av.scss b/app/src/assets/scss/business/_av.scss
index e09db007f..72c0bd3fb 100644
--- a/app/src/assets/scss/business/_av.scss
+++ b/app/src/assets/scss/business/_av.scss
@@ -325,7 +325,7 @@
height: 100%;
&--fit {
- background-size: contain;
+ background-size: cover;
background-position: center center;
background-repeat: no-repeat;
}
@@ -354,6 +354,22 @@
flex: 1;
transition: background 100ms ease-out;
}
+
+ &-add {
+ border: 1px solid var(--b3-border-color);
+ border-radius: var(--b3-border-radius);
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ color: var(--b3-theme-on-surface);
+ cursor: pointer;
+ transition: background 100ms ease-out, color 100ms ease-out;
+
+ &:hover {
+ background-color: var(--b3-list-hover);
+ color: var(--b3-theme-on-background);
+ }
+ }
}
&__layout {
diff --git a/app/src/protyle/render/av/action.ts b/app/src/protyle/render/av/action.ts
index 708399a54..08a203bfd 100644
--- a/app/src/protyle/render/av/action.ts
+++ b/app/src/protyle/render/av/action.ts
@@ -199,7 +199,10 @@ export const avClick = (protyle: IProtyle, event: MouseEvent & { target: HTMLEle
event.stopPropagation();
return true;
} else if (type === "av-add-bottom") {
- insertRows(blockElement, protyle, 1, blockElement.querySelector(".av__row--util").previousElementSibling.getAttribute("data-id") || "");
+ insertRows(blockElement, protyle, 1,
+ blockElement.querySelector(".av__row--util")?.previousElementSibling?.getAttribute("data-id") ||
+ target.previousElementSibling?.getAttribute("data-id") || undefined
+ );
event.preventDefault();
event.stopPropagation();
return true;
diff --git a/app/src/protyle/render/av/gallery/item.ts b/app/src/protyle/render/av/gallery/item.ts
new file mode 100644
index 000000000..b8b0030d6
--- /dev/null
+++ b/app/src/protyle/render/av/gallery/item.ts
@@ -0,0 +1,133 @@
+import {showMessage} from "../../../../dialog/message";
+import {
+ genCellValueByElement,
+ getTypeByCellElement,
+ renderCell,
+ renderCellAttr
+} from "../cell";
+import {fetchPost} from "../../../../util/fetch";
+import {setPage} from "../row";
+
+export const insertGalleryItemAnimation = (options: {
+ blockElement: HTMLElement;
+ protyle: IProtyle;
+ srcIDs: string[];
+ previousId: string;
+}) => {
+ if ((options.blockElement.querySelector('[data-type="av-search"]') as HTMLInputElement).value !== "") {
+ showMessage(window.siyuan.languages.insertRowTip);
+ return;
+ }
+ const avId = options.blockElement.getAttribute("data-av-id");
+ const sideItemElement = options.previousId ? options.blockElement.querySelector(`.av__gallery-item[data-id="${options.previousId}"]`) : options.blockElement.querySelector(".av__gallery-item");
+ let html = "";
+ let needUpdate = "";
+ if (options.blockElement.querySelector('.av__views [data-type="av-sort"]').classList.contains("block__icon--active") &&
+ !options.blockElement.querySelector('[data-type="av-load-more"]').classList.contains("fn__none")) {
+ needUpdate = ' data-need-update="true"';
+ }
+ options.srcIDs.forEach((id) => {
+ html += `
`;
+ });
+ if (options.previousId) {
+ sideItemElement.insertAdjacentHTML("afterend", html);
+ } else {
+ options.blockElement.querySelector(".av__gallery").insertAdjacentHTML("afterbegin", html);
+ }
+ const currentItemElement = options.blockElement.querySelector(`.av__gallery-item[data-id="${options.srcIDs[0]}"]`);
+ fetchPost("/api/av/getAttributeViewFilterSort", {
+ id: avId,
+ blockID: options.blockElement.getAttribute("data-node-id")
+ }, (response) => {
+ // https://github.com/siyuan-note/siyuan/issues/10517
+ let hideTextCell = false;
+ response.data.filters.find((item: IAVFilter) => {
+ const itemCellElement = options.blockElement.querySelector(`.av__cell[data-field-id="${item.column}"]`);
+ if (!itemCellElement) {
+ return;
+ }
+ const filterType = itemCellElement.getAttribute("data-dtype");
+ if (item.value && filterType !== item.value.type) {
+ return;
+ }
+ if (["relation", "rollup", "template"].includes(filterType)) {
+ hideTextCell = true;
+ return true;
+ }
+
+ // 根据后台计算出显示与否的结果进行标识,以便于在 refreshAV 中更新 UI
+ if (["created", "updated"].includes(filterType)) {
+ currentItemElement.setAttribute("data-need-update", "true");
+ } else {
+ response.data.sorts.find((sortItem: IAVSort) => {
+ if (sortItem.column === item.column) {
+ currentItemElement.setAttribute("data-need-update", "true");
+ return true;
+ }
+ });
+ }
+ // 当空或非空外,需要根据值进行判断
+ let isRenderValue = true;
+ if (item.operator !== "Is empty" && item.operator !== "Is not empty") {
+ switch (item.value.type) {
+ case "select":
+ case "mSelect":
+ if (!item.value.mSelect || item.value.mSelect.length === 0) {
+ isRenderValue = false;
+ }
+ break;
+ case "block":
+ if (!item.value.block || !item.value.block.content) {
+ isRenderValue = false;
+ }
+ break;
+ case "number":
+ if (!item.value.number || !item.value.number.isNotEmpty) {
+ isRenderValue = false;
+ }
+ break;
+ case "date":
+ case "created":
+ case "updated":
+ if (!item.value[item.value.type] || !item.value[item.value.type].isNotEmpty) {
+ isRenderValue = false;
+ }
+ break;
+ case "mAsset":
+ if (!item.value.mAsset || item.value.mAsset.length === 0) {
+ isRenderValue = false;
+ }
+ break;
+ case "checkbox":
+ if (!item.value.checkbox) {
+ isRenderValue = false;
+ }
+ break;
+ case "text":
+ case "url":
+ case "phone":
+ case "email":
+ if (!item.value[item.value.type] || !item.value[item.value.type].content) {
+ isRenderValue = false;
+ }
+ break;
+ }
+ }
+ if (sideItemElement.classList.contains("av__row") && isRenderValue) {
+ const sideItemCellElement = sideItemElement.querySelector(`.av__cell[data-field-id="${item.column}"]`) as HTMLElement;
+ const cellElement = currentItemElement.querySelector(`.av__cell[data-field-id="${item.column}"]`);
+ const cellValue = genCellValueByElement(getTypeByCellElement(sideItemCellElement), sideItemCellElement);
+ cellElement.innerHTML = renderCell(cellValue);
+ renderCellAttr(cellElement, cellValue);
+ }
+ });
+ if (hideTextCell) {
+ currentItemElement.remove();
+ showMessage(window.siyuan.languages.insertRowTip);
+ }
+ setPage(options.blockElement);
+ });
+};
diff --git a/app/src/protyle/render/av/gallery/render.ts b/app/src/protyle/render/av/gallery/render.ts
index f5789418e..ea897f2c5 100644
--- a/app/src/protyle/render/av/gallery/render.ts
+++ b/app/src/protyle/render/av/gallery/render.ts
@@ -68,7 +68,7 @@ export const renderGallery = (options: {
let galleryHTML = "";
// body
view.cards.forEach((item: IAVGalleryItem, rowIndex: number) => {
- galleryHTML += ``;
+ galleryHTML += `
`;
if (view.coverFrom !== 0) {
if (item.coverURL) {
if (item.coverURL.startsWith("background")) {
@@ -92,7 +92,7 @@ export const renderGallery = (options: {
if (cell.valueType === "checkbox") {
checkClass = cell.value?.checkbox?.checked ? " av__cell-check" : " av__cell-uncheck";
}
- galleryHTML += `
${renderCell(cell.value, rowIndex)}
});
galleryHTML += "
";
});
+ galleryHTML += `
${window.siyuan.languages.newCol}
`;
let tabHTML = "";
let viewData: IAVView;
response.data.views.forEach((item: IAVView) => {
@@ -164,6 +165,13 @@ ${cell.color ? `color:${cell.color};` : ""}">${renderCell(cell.value, rowIndex)}
${view.hideAttrViewName ? " av__gallery--top" : ""}">
${galleryHTML}
+
+
+
${Constants.ZWSP}
`;
} else {
diff --git a/app/src/protyle/render/av/layout.ts b/app/src/protyle/render/av/layout.ts
index 3e8df8d59..1999f86cf 100644
--- a/app/src/protyle/render/av/layout.ts
+++ b/app/src/protyle/render/av/layout.ts
@@ -1,4 +1,5 @@
import {transaction} from "../../wysiwyg/transaction";
+import {Constants} from "../../../constants";
export const getLayoutHTML = (data: IAV) => {
let html = "";
@@ -74,6 +75,12 @@ export const getLayoutHTML = (data: IAV) => {
${html}
+
`;
};
diff --git a/app/src/protyle/render/av/row.ts b/app/src/protyle/render/av/row.ts
index 5ab01a4b0..318e5b660 100644
--- a/app/src/protyle/render/av/row.ts
+++ b/app/src/protyle/render/av/row.ts
@@ -14,6 +14,7 @@ import {fetchPost} from "../../../util/fetch";
import {showMessage} from "../../../dialog/message";
import * as dayjs from "dayjs";
import {Constants} from "../../../constants";
+import {insertGalleryItemAnimation} from "./gallery/item";
export const selectRow = (checkElement: Element, type: "toggle" | "select" | "unselect" | "unselectAll") => {
const rowElement = hasClosestByClassName(checkElement, "av__row");
@@ -81,7 +82,7 @@ export const updateHeader = (rowElement: HTMLElement) => {
avHeadElement.style.position = "sticky";
};
-const setPage = (blockElement: Element) => {
+export const setPage = (blockElement: Element) => {
const pageSize = parseInt(blockElement.getAttribute("data-page-size"));
if (pageSize) {
const currentCount = blockElement.querySelectorAll(".av__row:not(.av__row--header)").length;
@@ -477,6 +478,15 @@ export const insertRows = (blockElement: HTMLElement, protyle: IProtyle, count:
id: blockElement.dataset.nodeId,
data: blockElement.getAttribute("updated")
}]);
- insertAttrViewBlockAnimation(protyle, blockElement, srcIDs, previousID, avID);
+ if (blockElement.getAttribute("data-av-type") === "gallery") {
+ insertGalleryItemAnimation({
+ blockElement,
+ protyle,
+ srcIDs,
+ previousId: previousID
+ });
+ } else {
+ insertAttrViewBlockAnimation(protyle, blockElement, srcIDs, previousID, avID);
+ }
blockElement.setAttribute("updated", newUpdated);
};
diff --git a/app/src/protyle/render/av/view.ts b/app/src/protyle/render/av/view.ts
index cb6fcbf28..1082f094d 100644
--- a/app/src/protyle/render/av/view.ts
+++ b/app/src/protyle/render/av/view.ts
@@ -219,12 +219,6 @@ export const getViewHTML = (data: IAV) => {
-