From a566c823ce498a33f1b6eccdb4c0a68e5f849966 Mon Sep 17 00:00:00 2001 From: Vanessa Date: Thu, 12 Jun 2025 18:33:46 +0800 Subject: [PATCH] :art: https://github.com/siyuan-note/siyuan/issues/10414 --- app/src/assets/scss/business/_av.scss | 18 ++- app/src/protyle/render/av/action.ts | 5 +- app/src/protyle/render/av/gallery/item.ts | 133 ++++++++++++++++++++ app/src/protyle/render/av/gallery/render.ts | 12 +- app/src/protyle/render/av/layout.ts | 7 ++ app/src/protyle/render/av/row.ts | 14 ++- app/src/protyle/render/av/view.ts | 6 - 7 files changed, 183 insertions(+), 12 deletions(-) create mode 100644 app/src/protyle/render/av/gallery/item.ts 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 += ` +
+ +
${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) => { ${view.sorts.length} -