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;
min-height: calc(1.625em + 4px);
&:not([data-dtype="block"])[data-empty="true"] {
padding: 0 4px;
min-height: auto;
}
&:hover {
background-color: var(--b3-list-hover);
border-radius: var(--b3-border-radius);
@ -420,30 +415,62 @@
cursor: default;
}
&[data-dtype="mAsset"],
&[data-dtype="mSelect"],
&[data-dtype="select"] {
margin-left: -2px;
&[data-dtype="mAsset"] .av__cellassetimg:first-child,
&[data-dtype="mAsset"] .b3-chip:first-child,
&[data-dtype="mSelect"] .b3-chip:first-child,
&[data-dtype="select"] .b3-chip:first-child {
margin-left: 0;
}
}
&--edit .av__cell {
padding: 2px 4px !important;
min-height: calc(1.625em + 4px) !important;
&--edit .av__gallery-field[data-empty="true"] .av__gallery-tip {
display: flex;
}
&[data-dtype="mAsset"][data-empty="true"],
&[data-dtype="mSelect"][data-empty="true"],
&[data-dtype="select"][data-empty="true"] {
margin-left: 0;
}
&:not(.av__gallery-fields--edit) [data-empty="true"] {
display: none;
}
}
.b3-menu__avemoji {
display: none;
}
&-field {
position: relative;
}
&[data-empty="true"] .av__gallery-tip {
display: flex;
}
&-name {
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;
}
&-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 {
&.dragover__left::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 type = cellElement.getAttribute("data-dtype") as TAVCol;
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");
editAttrSubmenu.push({
iconHTML: iconElement.outerHTML,
label: escapeHtml(cellElement.getAttribute("aria-label")),
label: escapeHtml(cellElement.getAttribute("aria-label").split('<div class="ft__on-surface">')[0]),
click() {
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);
@ -829,12 +829,11 @@ export const updateAttrViewCellAnimation = (cellElement: HTMLElement, value: IAV
if (value.type === "checkbox") {
value.checkbox = {
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.querySelector(".av__gallery-tip").outerHTML;
cellElement.setAttribute("data-empty", cellValueIsEmpty(value).toString());
cellElement.innerHTML = renderCell(value, 0, iconElement ? !iconElement.classList.contains("fn__none") : false, viewType);
cellElement.parentElement.setAttribute("data-empty", cellValueIsEmpty(value).toString());
} else {
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) => {
if (cellElement.parentElement.classList.contains("av__gallery-fields")) {
if (cellElement.parentElement.classList.contains("av__gallery-field")) {
return cellElement.getAttribute("data-dtype") as TAVCol;
}
const scrollElement = hasClosestByClassName(cellElement, "av__scroll");

View file

@ -36,11 +36,23 @@ export const insertGalleryItemAnimation = (options: {
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-dtype="${item.dataset.dtype}"
data-empty="${item.dataset.empty}"
${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);
let html = "";
@ -72,8 +84,8 @@ ${fieldType === "block" ? ' data-detached="true"' : ""}>${renderCell(genCellValu
}
if (updateIds.includes(cellItem.dataset.fieldId)) {
const cellValue = response.data.values[cellItem.dataset.fieldId];
if (cellValue.type === "checkbox") {
cellValue.checkbox.content = cellItem.getAttribute("aria-label");
if (cellValue.type === "checkbox" && cellItem.parentElement.querySelector(".av__gallery-tip")) {
cellValue.checkbox.content = cellItem.getAttribute("aria-label").split('<div class="ft__on-surface">')[0];
}
cellItem.innerHTML = renderCell(cellValue, undefined, false, "gallery");
renderCellAttr(cellItem, cellValue);

View file

@ -65,15 +65,19 @@ const getGalleryHTML = (data: IAVGallery) => {
}
const isEmpty = cellValueIsEmpty(cell.value);
// NOTE: innerHTML 中不能换行否则 https://github.com/siyuan-note/siyuan/issues/15132
let 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>`);
let ariaLabel = "";
if (!data.displayFieldName) {
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}"
data-empty="${isEmpty}"
const cellHTML = `<div class="av__cell${checkClass}${data.displayFieldName ? "" : " ariaLabel"}"
data-wrap="${data.fields[fieldsIndex].wrap}"
aria-label="${ariaLabel}"
data-position="5west"
data-id="${cell.id}"
@ -81,7 +85,26 @@ data-field-id="${data.fields[fieldsIndex].id}"
data-dtype="${cell.valueType}"
${cell.value?.isDetached ? ' data-detached="true"' : ""}
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>
<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__space fn__flex-1"></span>
<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>`;
}
return `<div class="b3-menu__items">
@ -117,6 +122,7 @@ export const bindLayoutEvent = (options: {
blockID,
data: checked
}]);
options.data.view.hideAttrViewName = !checked;
});
const toggleIconElement = options.menuElement.querySelector('.b3-switch[data-type="toggle-gallery-icon"]') as HTMLInputElement;
toggleIconElement.addEventListener("change", () => {
@ -134,6 +140,7 @@ export const bindLayoutEvent = (options: {
blockID,
data: !checked
}]);
options.data.view.showIcon = checked;
});
const toggleWrapElement = options.menuElement.querySelector('.b3-switch[data-type="toggle-gallery-wrap"]') as HTMLInputElement;
toggleWrapElement.addEventListener("change", () => {
@ -175,13 +182,25 @@ export const bindLayoutEvent = (options: {
blockID,
data: !checked
}]);
options.blockElement.querySelectorAll(".av__gallery-img").forEach(item => {
if (checked) {
item.classList.add("av__gallery-img--fit");
} else {
item.classList.remove("av__gallery-img--fit");
}
});
(options.data.view as IAVGallery).fitImage = checked;
});
const toggleNameElement = options.menuElement.querySelector('.b3-switch[data-type="toggle-gallery-name"]') as HTMLInputElement;
toggleNameElement.addEventListener("change", () => {
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;
}
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") {
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 => {
@ -758,7 +768,7 @@ export const refreshAV = (protyle: IProtyle, operation: IOperation) => {
if (item.getAttribute("data-av-type") === "gallery") {
operation.srcs.forEach(srcItem => {
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");
}
});

View file

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

View file

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