Vanessa 2025-08-21 10:50:42 +08:00
parent 6e6522d56a
commit 557f4866d5
9 changed files with 143 additions and 71 deletions

View file

@ -399,11 +399,6 @@
border-right: 0; border-right: 0;
min-height: calc(1.625em + 4px); min-height: calc(1.625em + 4px);
&:not([data-dtype="block"])[data-empty="true"] {
padding: 0 4px;
min-height: auto;
}
&:hover { &:hover {
background-color: var(--b3-list-hover); background-color: var(--b3-list-hover);
border-radius: var(--b3-border-radius); border-radius: var(--b3-border-radius);
@ -420,30 +415,62 @@
cursor: default; cursor: default;
} }
&[data-dtype="mAsset"], &[data-dtype="mAsset"] .av__cellassetimg:first-child,
&[data-dtype="mSelect"], &[data-dtype="mAsset"] .b3-chip:first-child,
&[data-dtype="select"] { &[data-dtype="mSelect"] .b3-chip:first-child,
margin-left: -2px; &[data-dtype="select"] .b3-chip:first-child {
margin-left: 0;
} }
} }
&--edit .av__cell { &--edit .av__gallery-field[data-empty="true"] .av__gallery-tip {
padding: 2px 4px !important; display: flex;
min-height: calc(1.625em + 4px) !important; }
&[data-dtype="mAsset"][data-empty="true"], &:not(.av__gallery-fields--edit) [data-empty="true"] {
&[data-dtype="mSelect"][data-empty="true"], display: none;
&[data-dtype="select"][data-empty="true"] { }
margin-left: 0; }
}
.b3-menu__avemoji { &-field {
display: none; position: relative;
} }
&[data-empty="true"] .av__gallery-tip { &-name {
display: flex; display: flex;
} align-items: center;
opacity: 0.38;
padding: 2px 4px;
width: 100%;
flex-wrap: wrap;
white-space: normal;
word-break: break-all;
}
&-tip {
display: none;
align-items: center;
opacity: 0.38;
padding: 2px 4px;
width: 100%;
position: absolute;
top: 0;
}
&-tip,
&-name {
img:first-child, svg:first-child {
height: calc(1.625em - 10px);
width: calc(1.625em - 10px);
margin: 0 5px 0 0;
font-size: 1em;
}
span:first-child {
width: calc(1.9em - 10px);
margin: 0 5px 0 0;
height: 1.625em;
font-size: .85em;
} }
} }
@ -479,26 +506,6 @@
z-index: 2; z-index: 2;
} }
&-tip {
display: none;
align-items: center;
opacity: 0.38;
img, svg {
height: calc(1.625em - 10px);
width: calc(1.625em - 10px);
margin: 0 5px 0 0;
font-size: 1em;
}
span {
width: calc(1.9em - 10px);
margin: 0 5px 0 0;
height: 1.625em;
font-size: .85em;
}
}
&-item, &-add { &-item, &-add {
&.dragover__left::after, &.dragover__left::after,
&.dragover__right::after { &.dragover__right::after {

View file

@ -714,11 +714,11 @@ ${window.siyuan.languages[avType === "table" ? "insertRowAfter" : "insertItemAft
const selectElements: HTMLElement[] = Array.from(blockElement.querySelectorAll(`.av__gallery-item--select .av__cell[data-field-id="${cellElement.dataset.fieldId}"]`)); const selectElements: HTMLElement[] = Array.from(blockElement.querySelectorAll(`.av__gallery-item--select .av__cell[data-field-id="${cellElement.dataset.fieldId}"]`));
const type = cellElement.getAttribute("data-dtype") as TAVCol; const type = cellElement.getAttribute("data-dtype") as TAVCol;
if (!["updated", "created"].includes(type)) { if (!["updated", "created"].includes(type)) {
const iconElement = cellElement.querySelector(".av__gallery-tip").firstElementChild.cloneNode(true) as HTMLElement; const iconElement = cellElement.parentElement.querySelector(".av__gallery-tip, .av__gallery-name").firstElementChild.cloneNode(true) as HTMLElement;
iconElement.classList.add("b3-menu__icon"); iconElement.classList.add("b3-menu__icon");
editAttrSubmenu.push({ editAttrSubmenu.push({
iconHTML: iconElement.outerHTML, iconHTML: iconElement.outerHTML,
label: escapeHtml(cellElement.getAttribute("aria-label")), label: escapeHtml(cellElement.getAttribute("aria-label").split('<div class="ft__on-surface">')[0]),
click() { click() {
rowElement.querySelector(".av__gallery-fields").classList.add("av__gallery-fields--edit"); rowElement.querySelector(".av__gallery-fields").classList.add("av__gallery-fields--edit");
rowElement.querySelector('[data-type="av-gallery-edit"]').setAttribute("aria-label", window.siyuan.languages.hideEmptyFields); rowElement.querySelector('[data-type="av-gallery-edit"]').setAttribute("aria-label", window.siyuan.languages.hideEmptyFields);
@ -829,12 +829,11 @@ export const updateAttrViewCellAnimation = (cellElement: HTMLElement, value: IAV
if (value.type === "checkbox") { if (value.type === "checkbox") {
value.checkbox = { value.checkbox = {
checked: value.checkbox?.checked || false, checked: value.checkbox?.checked || false,
content: cellElement.getAttribute("aria-label"), content: cellElement.getAttribute("aria-label").split('<div class="ft__on-surface">')[0],
}; };
} }
cellElement.innerHTML = renderCell(value, 0, iconElement ? !iconElement.classList.contains("fn__none") : false, viewType) + cellElement.innerHTML = renderCell(value, 0, iconElement ? !iconElement.classList.contains("fn__none") : false, viewType);
cellElement.querySelector(".av__gallery-tip").outerHTML; cellElement.parentElement.setAttribute("data-empty", cellValueIsEmpty(value).toString());
cellElement.setAttribute("data-empty", cellValueIsEmpty(value).toString());
} else { } else {
cellElement.innerHTML = renderCell(value, 0, iconElement ? !iconElement.classList.contains("fn__none") : false); cellElement.innerHTML = renderCell(value, 0, iconElement ? !iconElement.classList.contains("fn__none") : false);
} }

View file

@ -460,7 +460,7 @@ export const cellScrollIntoView = (blockElement: HTMLElement, cellElement: Eleme
}; };
export const getTypeByCellElement = (cellElement: Element) => { export const getTypeByCellElement = (cellElement: Element) => {
if (cellElement.parentElement.classList.contains("av__gallery-fields")) { if (cellElement.parentElement.classList.contains("av__gallery-field")) {
return cellElement.getAttribute("data-dtype") as TAVCol; return cellElement.getAttribute("data-dtype") as TAVCol;
} }
const scrollElement = hasClosestByClassName(cellElement, "av__scroll"); const scrollElement = hasClosestByClassName(cellElement, "av__scroll");

View file

@ -36,11 +36,23 @@ export const insertGalleryItemAnimation = (options: {
lineNumber = parseInt(lineNumberValue); lineNumber = parseInt(lineNumberValue);
} }
} }
cellsHTML += `<div class="av__cell${fieldType === "checkbox" ? " av__cell-uncheck" : ""}" data-field-id="${item.dataset.fieldId}"
const cellHTML = `<div class="av__cell${fieldType === "checkbox" ? " av__cell-uncheck" : ""}"
data-field-id="${item.dataset.fieldId}"
data-wrap="${item.dataset.wrap}" data-wrap="${item.dataset.wrap}"
data-dtype="${item.dataset.dtype}" data-dtype="${item.dataset.dtype}"
data-empty="${item.dataset.empty}"
${fieldType === "block" ? ' data-detached="true"' : ""}>${renderCell(genCellValue(fieldType, null), lineNumber, false, "gallery")}</div>`; ${fieldType === "block" ? ' data-detached="true"' : ""}>${renderCell(genCellValue(fieldType, null), lineNumber, false, "gallery")}</div>`;
if (item.previousElementSibling.classList.contains("av__gallery-name")) {
cellsHTML += `<div class="av__gallery-field av__gallery-field--name" data-empty="${item.parentElement.dataset.empty}">
${item.previousElementSibling.outerHTML}
${cellHTML}
</div>`;
} else {
cellsHTML += `<div class="av__gallery-field" data-empty="${item.parentElement.dataset.empty}">
${item.previousElementSibling.outerHTML}
${cellHTML}
</div>`;
}
}); });
clearSelect(["galleryItem"], options.blockElement); clearSelect(["galleryItem"], options.blockElement);
let html = ""; let html = "";
@ -72,8 +84,8 @@ ${fieldType === "block" ? ' data-detached="true"' : ""}>${renderCell(genCellValu
} }
if (updateIds.includes(cellItem.dataset.fieldId)) { if (updateIds.includes(cellItem.dataset.fieldId)) {
const cellValue = response.data.values[cellItem.dataset.fieldId]; const cellValue = response.data.values[cellItem.dataset.fieldId];
if (cellValue.type === "checkbox") { if (cellValue.type === "checkbox" && cellItem.parentElement.querySelector(".av__gallery-tip")) {
cellValue.checkbox.content = cellItem.getAttribute("aria-label"); cellValue.checkbox.content = cellItem.getAttribute("aria-label").split('<div class="ft__on-surface">')[0];
} }
cellItem.innerHTML = renderCell(cellValue, undefined, false, "gallery"); cellItem.innerHTML = renderCell(cellValue, undefined, false, "gallery");
renderCellAttr(cellItem, cellValue); renderCellAttr(cellItem, cellValue);

View file

@ -65,15 +65,19 @@ const getGalleryHTML = (data: IAVGallery) => {
} }
const isEmpty = cellValueIsEmpty(cell.value); const isEmpty = cellValueIsEmpty(cell.value);
// NOTE: innerHTML 中不能换行否则 https://github.com/siyuan-note/siyuan/issues/15132 // NOTE: innerHTML 中不能换行否则 https://github.com/siyuan-note/siyuan/issues/15132
let ariaLabel = escapeAttr(data.fields[fieldsIndex].name) || getColNameByType(data.fields[fieldsIndex].type); let ariaLabel = "";
if (data.fields[fieldsIndex].desc) { if (!data.displayFieldName) {
ariaLabel += escapeAttr(`<div class="ft__on-surface">${data.fields[fieldsIndex].desc}</div>`); ariaLabel = escapeAttr(data.fields[fieldsIndex].name) || getColNameByType(data.fields[fieldsIndex].type);
if (data.fields[fieldsIndex].desc) {
ariaLabel += escapeAttr(`<div class="ft__on-surface">${data.fields[fieldsIndex].desc}</div>`);
}
} }
if (cell.valueType === "checkbox") {
cell.value["checkbox"].content = data.fields[fieldsIndex].name || getColNameByType(data.fields[fieldsIndex].type); if (cell.valueType === "checkbox" && !data.displayFieldName) {
cell.value.checkbox.content = data.fields[fieldsIndex].name || getColNameByType(data.fields[fieldsIndex].type);
} }
galleryHTML += `<div class="av__cell${checkClass} ariaLabel" data-wrap="${data.fields[fieldsIndex].wrap}" const cellHTML = `<div class="av__cell${checkClass}${data.displayFieldName ? "" : " ariaLabel"}"
data-empty="${isEmpty}" data-wrap="${data.fields[fieldsIndex].wrap}"
aria-label="${ariaLabel}" aria-label="${ariaLabel}"
data-position="5west" data-position="5west"
data-id="${cell.id}" data-id="${cell.id}"
@ -81,7 +85,26 @@ data-field-id="${data.fields[fieldsIndex].id}"
data-dtype="${cell.valueType}" data-dtype="${cell.valueType}"
${cell.value?.isDetached ? ' data-detached="true"' : ""} ${cell.value?.isDetached ? ' data-detached="true"' : ""}
style="${cell.bgColor ? `background-color:${cell.bgColor};` : ""} style="${cell.bgColor ? `background-color:${cell.bgColor};` : ""}
${cell.color ? `color:${cell.color};` : ""}">${renderCell(cell.value, rowIndex, data.showIcon, "gallery")}<div class="av__gallery-tip">${data.fields[fieldsIndex].icon ? unicode2Emoji(data.fields[fieldsIndex].icon, undefined, true) : `<svg><use xlink:href="#${getColIconByType(data.fields[fieldsIndex].type)}"></use></svg>`}${window.siyuan.languages.edit} ${Lute.EscapeHTMLStr(data.fields[fieldsIndex].name)}</div></div>`; ${cell.color ? `color:${cell.color};` : ""}">${renderCell(cell.value, rowIndex, data.showIcon, "gallery")}</div>`;
if (data.displayFieldName) {
galleryHTML += `<div class="av__gallery-field av__gallery-field--name" data-empty="${isEmpty}">
<div class="av__gallery-name">
${data.fields[fieldsIndex].icon ? unicode2Emoji(data.fields[fieldsIndex].icon, undefined, true) : `<svg><use xlink:href="#${getColIconByType(data.fields[fieldsIndex].type)}"></use></svg>`}
${Lute.EscapeHTMLStr(data.fields[fieldsIndex].name)}
<span class="fn__space"></span>
<span class="ft__smaller">${data.fields[fieldsIndex].desc || ""}</span>
</div>
${cellHTML}
</div>`;
} else {
galleryHTML += `<div class="av__gallery-field" data-empty="${isEmpty}">
<div class="av__gallery-tip">
${data.fields[fieldsIndex].icon ? unicode2Emoji(data.fields[fieldsIndex].icon, undefined, true) : `<svg><use xlink:href="#${getColIconByType(data.fields[fieldsIndex].type)}"></use></svg>`}
${window.siyuan.languages.edit} ${Lute.EscapeHTMLStr(data.fields[fieldsIndex].name)}
</div>
${cellHTML}
</div>`;
}
}); });
galleryHTML += `</div> galleryHTML += `</div>
<div class="av__gallery-actions"> <div class="av__gallery-actions">

View file

@ -45,6 +45,11 @@ export const getLayoutHTML = (data: IAV) => {
<span class="fn__flex-center">${window.siyuan.languages.fitImage}</span> <span class="fn__flex-center">${window.siyuan.languages.fitImage}</span>
<span class="fn__space fn__flex-1"></span> <span class="fn__space fn__flex-1"></span>
<input data-type="toggle-gallery-fit" type="checkbox" class="b3-switch b3-switch--menu" ${view.fitImage ? "checked" : ""}> <input data-type="toggle-gallery-fit" type="checkbox" class="b3-switch b3-switch--menu" ${view.fitImage ? "checked" : ""}>
</label>
<label class="b3-menu__item">
<span class="fn__flex-center">${window.siyuan.languages.displayFieldName}</span>
<span class="fn__space fn__flex-1"></span>
<input data-type="toggle-gallery-name" type="checkbox" class="b3-switch b3-switch--menu" ${view.displayFieldName ? "checked" : ""}>
</label>`; </label>`;
} }
return `<div class="b3-menu__items"> return `<div class="b3-menu__items">
@ -117,6 +122,7 @@ export const bindLayoutEvent = (options: {
blockID, blockID,
data: checked data: checked
}]); }]);
options.data.view.hideAttrViewName = !checked;
}); });
const toggleIconElement = options.menuElement.querySelector('.b3-switch[data-type="toggle-gallery-icon"]') as HTMLInputElement; const toggleIconElement = options.menuElement.querySelector('.b3-switch[data-type="toggle-gallery-icon"]') as HTMLInputElement;
toggleIconElement.addEventListener("change", () => { toggleIconElement.addEventListener("change", () => {
@ -134,6 +140,7 @@ export const bindLayoutEvent = (options: {
blockID, blockID,
data: !checked data: !checked
}]); }]);
options.data.view.showIcon = checked;
}); });
const toggleWrapElement = options.menuElement.querySelector('.b3-switch[data-type="toggle-gallery-wrap"]') as HTMLInputElement; const toggleWrapElement = options.menuElement.querySelector('.b3-switch[data-type="toggle-gallery-wrap"]') as HTMLInputElement;
toggleWrapElement.addEventListener("change", () => { toggleWrapElement.addEventListener("change", () => {
@ -175,13 +182,25 @@ export const bindLayoutEvent = (options: {
blockID, blockID,
data: !checked data: !checked
}]); }]);
options.blockElement.querySelectorAll(".av__gallery-img").forEach(item => { (options.data.view as IAVGallery).fitImage = checked;
if (checked) { });
item.classList.add("av__gallery-img--fit"); const toggleNameElement = options.menuElement.querySelector('.b3-switch[data-type="toggle-gallery-name"]') as HTMLInputElement;
} else { toggleNameElement.addEventListener("change", () => {
item.classList.remove("av__gallery-img--fit"); const avID = options.blockElement.getAttribute("data-av-id");
} const blockID = options.blockElement.getAttribute("data-node-id");
}); const checked = toggleNameElement.checked;
transaction(options.protyle, [{
action: "setDisplayFieldName",
avID,
blockID,
data: checked
}], [{
action: "setDisplayFieldName",
avID,
blockID,
data: !checked
}]);
(options.data.view as IAVGallery).displayFieldName = checked;
}); });
}; };

View file

@ -673,6 +673,16 @@ export const refreshAV = (protyle: IProtyle, operation: IOperation) => {
}); });
return; return;
} }
if (operation.action === "setAttrViewFitImage") {
Array.from(protyle.wysiwyg.element.querySelectorAll(`.av[data-av-id="${operation.avID}"] .av__gallery-img`)).forEach((item: HTMLElement) => {
if (operation.data) {
item.classList.add("av__gallery-img--fit");
} else {
item.classList.remove("av__gallery-img--fit");
}
});
return;
}
if (operation.action === "setAttrViewShowIcon") { if (operation.action === "setAttrViewShowIcon") {
Array.from(protyle.wysiwyg.element.querySelectorAll(`.av[data-av-id="${operation.avID}"]`)).forEach((item: HTMLElement) => { Array.from(protyle.wysiwyg.element.querySelectorAll(`.av[data-av-id="${operation.avID}"]`)).forEach((item: HTMLElement) => {
item.querySelectorAll('.av__cell[data-dtype="block"] .b3-menu__avemoji, .av__cell[data-dtype="relation"] .b3-menu__avemoji').forEach(cellItem => { item.querySelectorAll('.av__cell[data-dtype="block"] .b3-menu__avemoji, .av__cell[data-dtype="relation"] .b3-menu__avemoji').forEach(cellItem => {
@ -758,7 +768,7 @@ export const refreshAV = (protyle: IProtyle, operation: IOperation) => {
if (item.getAttribute("data-av-type") === "gallery") { if (item.getAttribute("data-av-type") === "gallery") {
operation.srcs.forEach(srcItem => { operation.srcs.forEach(srcItem => {
const filesElement = item.querySelector(`.av__body${groupQuery} .av__gallery-item[data-id="${srcItem.itemID}"]`)?.querySelector(".av__gallery-fields"); const filesElement = item.querySelector(`.av__body${groupQuery} .av__gallery-item[data-id="${srcItem.itemID}"]`)?.querySelector(".av__gallery-fields");
if (filesElement && filesElement.querySelector('[data-dtype="block"]')?.getAttribute("data-empty") === "true") { if (filesElement && filesElement.querySelector('[data-dtype="block"]')?.parentElement.getAttribute("data-empty") === "true") {
filesElement.classList.add("av__gallery-fields--edit"); filesElement.classList.add("av__gallery-fields--edit");
} }
}); });

View file

@ -864,7 +864,7 @@ export const onTransaction = (protyle: IProtyle, operation: IOperation, isUndo:
"duplicateAttrViewKey", "setAttrViewViewDesc", "setAttrViewCoverFrom", "setAttrViewCoverFromAssetKeyID", "duplicateAttrViewKey", "setAttrViewViewDesc", "setAttrViewCoverFrom", "setAttrViewCoverFromAssetKeyID",
"setAttrViewBlockView", "setAttrViewCardSize", "setAttrViewCardAspectRatio", "hideAttrViewName", "setAttrViewShowIcon", "setAttrViewBlockView", "setAttrViewCardSize", "setAttrViewCardAspectRatio", "hideAttrViewName", "setAttrViewShowIcon",
"setAttrViewWrapField", "setAttrViewGroup", "removeAttrViewGroup", "hideAttrViewGroup", "sortAttrViewGroup", "setAttrViewWrapField", "setAttrViewGroup", "removeAttrViewGroup", "hideAttrViewGroup", "sortAttrViewGroup",
"foldAttrViewGroup", "hideAttrViewAllGroups"].includes(operation.action)) { "foldAttrViewGroup", "hideAttrViewAllGroups", "setAttrViewFitImage", "setDisplayFieldName"].includes(operation.action)) {
if (!isUndo) { if (!isUndo) {
// 撤销 transaction 会进行推送,需使用推送来进行刷新最新数据 https://github.com/siyuan-note/siyuan/issues/13607 // 撤销 transaction 会进行推送,需使用推送来进行刷新最新数据 https://github.com/siyuan-note/siyuan/issues/13607
refreshAV(protyle, operation); refreshAV(protyle, operation);

View file

@ -69,6 +69,7 @@ type TOperation =
| "hideAttrViewGroup" | "hideAttrViewGroup"
| "sortAttrViewGroup" | "sortAttrViewGroup"
| "foldAttrViewGroup" | "foldAttrViewGroup"
| "setDisplayFieldName"
type TBazaarType = "templates" | "icons" | "widgets" | "themes" | "plugins" type TBazaarType = "templates" | "icons" | "widgets" | "themes" | "plugins"
type TCardType = "doc" | "notebook" | "all" type TCardType = "doc" | "notebook" | "all"
type TEventBus = "ws-main" | "sync-start" | "sync-end" | "sync-fail" | type TEventBus = "ws-main" | "sync-start" | "sync-end" | "sync-fail" |
@ -879,6 +880,7 @@ interface IAVGallery extends IAVView {
coverFromAssetKeyID?: string; coverFromAssetKeyID?: string;
cardSize: number; // 0小卡片1中卡片2大卡片 cardSize: number; // 0小卡片1中卡片2大卡片
cardAspectRatio: number; cardAspectRatio: number;
displayFieldName: boolean;
fitImage: boolean; fitImage: boolean;
cards: IAVGalleryItem[], cards: IAVGalleryItem[],
desc: string desc: string