2023-06-10 16:27:52 +08:00
|
|
|
|
import {transaction} from "../../wysiwyg/transaction";
|
2023-06-30 11:11:45 +08:00
|
|
|
|
import {hasClosestBlock, hasClosestByClassName} from "../../util/hasClosest";
|
2023-07-09 23:54:32 +08:00
|
|
|
|
import {openMenuPanel} from "./openMenuPanel";
|
2023-09-21 10:54:17 +08:00
|
|
|
|
import {updateAttrViewCellAnimation} from "./action";
|
2023-12-15 12:30:57 +08:00
|
|
|
|
import {isNotCtrl} from "../../util/compatibility";
|
2023-10-06 10:56:30 +08:00
|
|
|
|
import {objEquals} from "../../../util/functions";
|
2023-10-13 11:30:44 +08:00
|
|
|
|
import {fetchPost} from "../../../util/fetch";
|
2023-10-13 11:55:51 +08:00
|
|
|
|
import {focusBlock} from "../../util/selection";
|
2023-10-14 11:04:23 +08:00
|
|
|
|
import * as dayjs from "dayjs";
|
2023-06-10 12:22:10 +08:00
|
|
|
|
|
2023-12-15 12:04:18 +08:00
|
|
|
|
export const getCellText = (cellElement: HTMLElement | false) => {
|
|
|
|
|
|
if (!cellElement) {
|
2023-12-15 12:30:57 +08:00
|
|
|
|
return "";
|
2023-12-15 12:04:18 +08:00
|
|
|
|
}
|
2023-12-15 12:30:57 +08:00
|
|
|
|
let cellText = ""
|
2023-12-15 12:04:18 +08:00
|
|
|
|
const textElement = cellElement.querySelector(".av__celltext");
|
|
|
|
|
|
if (textElement) {
|
|
|
|
|
|
if (textElement.querySelector(".av__cellicon")) {
|
2023-12-15 12:30:57 +08:00
|
|
|
|
cellText = `${textElement.firstChild.textContent} → ${textElement.lastChild.textContent}`;
|
2023-12-15 12:04:18 +08:00
|
|
|
|
} else {
|
2023-12-15 12:30:57 +08:00
|
|
|
|
cellText = textElement.textContent;
|
2023-12-15 12:04:18 +08:00
|
|
|
|
}
|
|
|
|
|
|
} else {
|
2023-12-15 12:30:57 +08:00
|
|
|
|
cellText = cellElement.textContent;
|
2023-12-15 12:04:18 +08:00
|
|
|
|
}
|
2023-12-15 12:30:57 +08:00
|
|
|
|
return cellText;
|
|
|
|
|
|
};
|
2023-12-15 12:04:18 +08:00
|
|
|
|
|
|
|
|
|
|
const genCellValueByElement = (colType: TAVCol, cellElement: HTMLElement) => {
|
|
|
|
|
|
let cellValue: IAVCellValue;
|
|
|
|
|
|
if (colType === "number") {
|
|
|
|
|
|
const value = cellElement.querySelector(".av__celltext").getAttribute("data-content")
|
|
|
|
|
|
cellValue = {
|
|
|
|
|
|
type: colType,
|
|
|
|
|
|
number: {
|
|
|
|
|
|
content: parseFloat(value) || 0,
|
|
|
|
|
|
isNotEmpty: !!value
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
} else if (["text", "block", "url", "phone", "email", "template"].includes(colType)) {
|
|
|
|
|
|
cellValue = {
|
|
|
|
|
|
type: colType,
|
|
|
|
|
|
[colType]: {
|
|
|
|
|
|
content: cellElement.querySelector(".av__celltext").textContent.trim()
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
} else if (colType === "mSelect" || colType === "select") {
|
|
|
|
|
|
const mSelect: IAVCellSelectValue[] = []
|
|
|
|
|
|
cellElement.querySelectorAll(".b3-chip").forEach((item: HTMLElement) => {
|
|
|
|
|
|
mSelect.push({
|
|
|
|
|
|
content: item.textContent.trim(),
|
|
|
|
|
|
color: item.style.color.replace("var(--b3-font-color", "").replace(")", "")
|
|
|
|
|
|
})
|
|
|
|
|
|
})
|
|
|
|
|
|
cellValue = {
|
|
|
|
|
|
type: colType,
|
|
|
|
|
|
mSelect
|
|
|
|
|
|
};
|
|
|
|
|
|
} else if (["date", "created", "updated"].includes(colType)) {
|
|
|
|
|
|
cellValue = {
|
|
|
|
|
|
type: colType,
|
|
|
|
|
|
[colType]: JSON.parse(cellElement.querySelector(".av__celltext").getAttribute("data-value"))
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
return cellValue;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-09-22 20:24:00 +08:00
|
|
|
|
export const genCellValue = (colType: TAVCol, value: string | any) => {
|
2023-07-13 23:48:05 +08:00
|
|
|
|
let cellValue: IAVCellValue;
|
|
|
|
|
|
if (typeof value === "string") {
|
|
|
|
|
|
if (colType === "number") {
|
|
|
|
|
|
if (value) {
|
|
|
|
|
|
cellValue = {
|
|
|
|
|
|
type: colType,
|
|
|
|
|
|
number: {
|
|
|
|
|
|
content: parseFloat(value),
|
|
|
|
|
|
isNotEmpty: true
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
} else {
|
|
|
|
|
|
cellValue = {
|
|
|
|
|
|
type: colType,
|
|
|
|
|
|
number: {
|
2023-12-15 12:04:18 +08:00
|
|
|
|
content: 0,
|
2023-07-13 23:48:05 +08:00
|
|
|
|
isNotEmpty: false
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
2023-10-09 09:52:40 +08:00
|
|
|
|
} else if (["text", "block", "url", "phone", "email", "template"].includes(colType)) {
|
2023-07-13 23:48:05 +08:00
|
|
|
|
cellValue = {
|
|
|
|
|
|
type: colType,
|
2023-08-02 14:27:49 +08:00
|
|
|
|
[colType]: {
|
2023-07-13 23:48:05 +08:00
|
|
|
|
content: value
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
} else if (colType === "mSelect" || colType === "select") {
|
2023-07-27 00:47:14 +08:00
|
|
|
|
cellValue = {
|
2023-07-13 23:48:05 +08:00
|
|
|
|
type: colType,
|
|
|
|
|
|
mSelect: [{
|
|
|
|
|
|
content: value,
|
2023-12-15 12:30:57 +08:00
|
|
|
|
color: value ? "1" : ""
|
2023-07-13 23:48:05 +08:00
|
|
|
|
}]
|
|
|
|
|
|
};
|
2023-10-09 11:33:29 +08:00
|
|
|
|
} else if (["date", "created", "updated"].includes(colType) && value === "") {
|
2023-07-27 13:50:59 +08:00
|
|
|
|
cellValue = {
|
|
|
|
|
|
type: colType,
|
2023-10-09 11:33:29 +08:00
|
|
|
|
[colType]: {
|
2023-07-27 13:50:59 +08:00
|
|
|
|
content: null,
|
2023-08-02 00:14:05 +08:00
|
|
|
|
isNotEmpty: false,
|
2023-07-27 13:50:59 +08:00
|
|
|
|
content2: null,
|
2023-08-02 00:14:05 +08:00
|
|
|
|
isNotEmpty2: false,
|
2023-07-27 13:50:59 +08:00
|
|
|
|
hasEndDate: false,
|
2023-10-27 23:09:42 +08:00
|
|
|
|
isNotTime: true,
|
2023-07-27 13:50:59 +08:00
|
|
|
|
}
|
|
|
|
|
|
};
|
2023-07-13 23:48:05 +08:00
|
|
|
|
}
|
2023-07-27 00:47:14 +08:00
|
|
|
|
} else {
|
|
|
|
|
|
if (colType === "mSelect" || colType === "select") {
|
|
|
|
|
|
cellValue = {
|
|
|
|
|
|
type: colType,
|
2023-09-22 20:24:00 +08:00
|
|
|
|
mSelect: value as IAVCellSelectValue[]
|
2023-07-27 00:47:14 +08:00
|
|
|
|
};
|
2023-10-09 11:33:29 +08:00
|
|
|
|
} else if (["date", "created", "updated"].includes(colType)) {
|
2023-07-27 00:47:14 +08:00
|
|
|
|
cellValue = {
|
|
|
|
|
|
type: colType,
|
2023-10-09 11:33:29 +08:00
|
|
|
|
[colType]: value as IAVCellDateValue
|
2023-07-27 00:47:14 +08:00
|
|
|
|
};
|
2023-09-22 20:24:00 +08:00
|
|
|
|
} else if (colType === "mAsset") {
|
|
|
|
|
|
cellValue = {
|
|
|
|
|
|
type: colType,
|
|
|
|
|
|
mAsset: value as IAVCellAssetValue[]
|
|
|
|
|
|
};
|
2023-11-20 11:12:02 +08:00
|
|
|
|
} else if (colType === "checkbox") {
|
|
|
|
|
|
cellValue = {
|
|
|
|
|
|
type: colType,
|
|
|
|
|
|
checkbox: {
|
|
|
|
|
|
checked: value ? true : false
|
2023-07-15 22:24:54 +08:00
|
|
|
|
}
|
2023-11-20 11:12:02 +08:00
|
|
|
|
};
|
2023-07-15 22:24:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2023-11-20 11:12:02 +08:00
|
|
|
|
return cellValue;
|
2023-07-15 23:19:40 +08:00
|
|
|
|
};
|
2023-07-15 22:24:54 +08:00
|
|
|
|
|
2023-11-14 12:58:45 +08:00
|
|
|
|
export const cellScrollIntoView = (blockElement: HTMLElement, cellElement: Element, onlyHeight = true) => {
|
|
|
|
|
|
const cellRect = cellElement.getBoundingClientRect();
|
2023-10-13 21:50:14 +08:00
|
|
|
|
if (!onlyHeight) {
|
|
|
|
|
|
const avScrollElement = blockElement.querySelector(".av__scroll");
|
2023-11-14 12:58:45 +08:00
|
|
|
|
if (avScrollElement) {
|
|
|
|
|
|
const avScrollRect = avScrollElement.getBoundingClientRect();
|
|
|
|
|
|
if (avScrollRect.right < cellRect.right) {
|
|
|
|
|
|
avScrollElement.scrollLeft = avScrollElement.scrollLeft + cellRect.right - avScrollRect.right;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
const rowElement = hasClosestByClassName(cellElement, "av__row");
|
|
|
|
|
|
if (rowElement) {
|
|
|
|
|
|
const stickyElement = rowElement.querySelector(".av__colsticky");
|
|
|
|
|
|
if (stickyElement) {
|
2023-11-14 23:18:18 +08:00
|
|
|
|
const stickyRight = stickyElement.getBoundingClientRect().right;
|
2023-11-14 12:58:45 +08:00
|
|
|
|
if (stickyRight > cellRect.left) {
|
|
|
|
|
|
avScrollElement.scrollLeft = avScrollElement.scrollLeft + cellRect.left - stickyRight;
|
|
|
|
|
|
}
|
|
|
|
|
|
} else if (avScrollRect.left > cellRect.left) {
|
|
|
|
|
|
avScrollElement.scrollLeft = avScrollElement.scrollLeft + cellRect.left - avScrollRect.left;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2023-10-13 21:50:14 +08:00
|
|
|
|
}
|
2023-10-13 12:33:29 +08:00
|
|
|
|
}
|
2023-10-27 23:31:39 +08:00
|
|
|
|
if (!blockElement.querySelector(".av__header")) {
|
|
|
|
|
|
// 属性面板
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2023-11-24 22:42:38 +08:00
|
|
|
|
const avHeaderRect = blockElement.querySelector(".av__row--header").getBoundingClientRect();
|
2023-10-13 12:33:29 +08:00
|
|
|
|
if (avHeaderRect.bottom > cellRect.top) {
|
2023-10-13 21:50:14 +08:00
|
|
|
|
const contentElement = hasClosestByClassName(blockElement, "protyle-content", true);
|
2023-10-13 12:33:29 +08:00
|
|
|
|
if (contentElement) {
|
|
|
|
|
|
contentElement.scrollTop = contentElement.scrollTop + cellRect.top - avHeaderRect.bottom;
|
|
|
|
|
|
}
|
2023-10-13 21:50:14 +08:00
|
|
|
|
} else {
|
|
|
|
|
|
const avFooterRect = blockElement.querySelector(".av__row--footer").getBoundingClientRect();
|
|
|
|
|
|
if (avFooterRect.top < cellRect.bottom) {
|
|
|
|
|
|
const contentElement = hasClosestByClassName(blockElement, "protyle-content", true);
|
|
|
|
|
|
if (contentElement) {
|
|
|
|
|
|
contentElement.scrollTop = contentElement.scrollTop + cellRect.bottom - avFooterRect.top;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2023-10-13 12:33:29 +08:00
|
|
|
|
}
|
2023-10-21 23:49:28 +08:00
|
|
|
|
};
|
2023-10-13 12:33:29 +08:00
|
|
|
|
|
2023-11-14 12:58:45 +08:00
|
|
|
|
export const getTypeByCellElement = (cellElement: Element) => {
|
2023-11-14 23:18:18 +08:00
|
|
|
|
const scrollElement = hasClosestByClassName(cellElement, "av__scroll");
|
2023-11-14 12:58:45 +08:00
|
|
|
|
if (!scrollElement) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
return scrollElement.querySelector(".av__row--header").querySelector(`[data-col-id="${cellElement.getAttribute("data-col-id")}"]`).getAttribute("data-dtype") as TAVCol;
|
2023-11-14 23:18:18 +08:00
|
|
|
|
};
|
2023-11-14 12:58:45 +08:00
|
|
|
|
|
2023-09-24 17:53:28 +08:00
|
|
|
|
export const popTextCell = (protyle: IProtyle, cellElements: HTMLElement[], type?: TAVCol) => {
|
2023-12-13 16:58:24 +08:00
|
|
|
|
if (cellElements.length === 0 || (cellElements.length === 1 && !cellElements[0])) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2023-09-24 17:53:28 +08:00
|
|
|
|
if (!type) {
|
2023-11-14 23:18:18 +08:00
|
|
|
|
type = getTypeByCellElement(cellElements[0]);
|
2023-09-24 17:53:28 +08:00
|
|
|
|
}
|
2023-12-13 16:58:24 +08:00
|
|
|
|
if (type === "updated" || type === "created" || document.querySelector(".av__mask")) {
|
2023-10-01 17:41:00 +08:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
2023-09-27 23:58:48 +08:00
|
|
|
|
if (type === "block" && (cellElements.length > 1 || !cellElements[0].getAttribute("data-detached"))) {
|
2023-08-02 22:48:36 +08:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
2023-10-13 09:37:24 +08:00
|
|
|
|
const blockElement = hasClosestBlock(cellElements[0]);
|
|
|
|
|
|
let cellRect = cellElements[0].getBoundingClientRect();
|
|
|
|
|
|
if (blockElement) {
|
2023-10-27 00:18:30 +08:00
|
|
|
|
/// #if MOBILE
|
|
|
|
|
|
const contentElement = hasClosestByClassName(blockElement, "protyle-content", true);
|
|
|
|
|
|
if (contentElement) {
|
|
|
|
|
|
contentElement.scrollTop = contentElement.scrollTop + cellRect.top - 110;
|
|
|
|
|
|
}
|
|
|
|
|
|
/// #else
|
2023-11-14 12:58:45 +08:00
|
|
|
|
cellScrollIntoView(blockElement, cellElements[0], false);
|
2023-10-27 00:18:30 +08:00
|
|
|
|
/// #endif
|
2023-10-13 09:37:24 +08:00
|
|
|
|
}
|
|
|
|
|
|
cellRect = cellElements[0].getBoundingClientRect();
|
2023-06-10 17:45:04 +08:00
|
|
|
|
let html = "";
|
2023-11-28 23:27:04 +08:00
|
|
|
|
const style = `style="padding-top: 6.5px;position:absolute;left: ${cellRect.left}px;top: ${cellRect.top}px;width:${Math.max(cellRect.width, 25)}px;height: ${cellRect.height}px"`;
|
2023-10-13 11:30:44 +08:00
|
|
|
|
if (["text", "url", "email", "phone", "block", "template"].includes(type)) {
|
2023-07-28 15:20:34 +08:00
|
|
|
|
html = `<textarea ${style} class="b3-text-field">${cellElements[0].firstElementChild.textContent}</textarea>`;
|
2023-10-01 17:41:00 +08:00
|
|
|
|
} else if (type === "number") {
|
2023-08-03 23:23:28 +08:00
|
|
|
|
html = `<input type="number" value="${cellElements[0].firstElementChild.getAttribute("data-content")}" ${style} class="b3-text-field">`;
|
2023-11-14 12:58:45 +08:00
|
|
|
|
} else if (blockElement) {
|
|
|
|
|
|
if (["select", "mSelect"].includes(type)) {
|
|
|
|
|
|
openMenuPanel({protyle, blockElement, type: "select", cellElements});
|
|
|
|
|
|
} else if (type === "mAsset") {
|
|
|
|
|
|
openMenuPanel({protyle, blockElement, type: "asset", cellElements});
|
|
|
|
|
|
} else if (type === "date") {
|
|
|
|
|
|
openMenuPanel({protyle, blockElement, type: "date", cellElements});
|
2023-11-20 11:12:02 +08:00
|
|
|
|
} else if (type === "checkbox") {
|
2023-12-15 12:04:18 +08:00
|
|
|
|
updateCellValueByInput(protyle, type, cellElements);
|
2023-11-14 12:58:45 +08:00
|
|
|
|
}
|
|
|
|
|
|
if (!hasClosestByClassName(cellElements[0], "custom-attr")) {
|
|
|
|
|
|
cellElements[0].classList.add("av__cell--select");
|
|
|
|
|
|
}
|
2023-07-09 23:54:32 +08:00
|
|
|
|
return;
|
2023-06-10 16:27:52 +08:00
|
|
|
|
}
|
2023-07-13 09:43:10 +08:00
|
|
|
|
window.siyuan.menus.menu.remove();
|
2023-09-02 11:13:47 +08:00
|
|
|
|
document.body.insertAdjacentHTML("beforeend", `<div class="av__mask" style="z-index: ${++window.siyuan.zIndex}">
|
2023-06-10 16:27:52 +08:00
|
|
|
|
${html}
|
|
|
|
|
|
</div>`);
|
|
|
|
|
|
const avMaskElement = document.querySelector(".av__mask");
|
|
|
|
|
|
const inputElement = avMaskElement.querySelector(".b3-text-field") as HTMLInputElement;
|
|
|
|
|
|
if (inputElement) {
|
|
|
|
|
|
inputElement.select();
|
2023-06-30 17:05:54 +08:00
|
|
|
|
inputElement.focus();
|
2023-10-13 11:30:44 +08:00
|
|
|
|
if (blockElement && type === "template") {
|
|
|
|
|
|
fetchPost("/api/av/renderAttributeView", {id: blockElement.dataset.avId}, (response) => {
|
|
|
|
|
|
response.data.view.columns.find((item: IAVColumn) => {
|
|
|
|
|
|
if (item.id === cellElements[0].dataset.colId) {
|
|
|
|
|
|
inputElement.value = item.template;
|
|
|
|
|
|
inputElement.dataset.template = item.template;
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
2023-06-10 16:27:52 +08:00
|
|
|
|
inputElement.addEventListener("keydown", (event) => {
|
|
|
|
|
|
if (event.isComposing) {
|
2023-06-10 17:45:04 +08:00
|
|
|
|
return;
|
2023-06-10 16:27:52 +08:00
|
|
|
|
}
|
2023-11-28 21:36:52 +08:00
|
|
|
|
if (event.key === "Escape" || event.key === "Tab" ||
|
2023-11-12 12:28:20 +08:00
|
|
|
|
(event.key === "Enter" && !event.shiftKey && isNotCtrl(event))) {
|
2023-12-15 12:04:18 +08:00
|
|
|
|
updateCellValueByInput(protyle, type, cellElements);
|
2023-11-28 21:36:52 +08:00
|
|
|
|
if (event.key === "Tab") {
|
2023-11-28 23:27:04 +08:00
|
|
|
|
protyle.wysiwyg.element.dispatchEvent(new KeyboardEvent("keydown", {
|
|
|
|
|
|
shiftKey: event.shiftKey,
|
|
|
|
|
|
ctrlKey: event.ctrlKey,
|
|
|
|
|
|
altKey: event.altKey,
|
|
|
|
|
|
metaKey: event.metaKey,
|
|
|
|
|
|
key: "Tab",
|
|
|
|
|
|
keyCode: 9
|
|
|
|
|
|
}));
|
2023-11-28 21:36:52 +08:00
|
|
|
|
}
|
2023-06-10 16:27:52 +08:00
|
|
|
|
event.preventDefault();
|
|
|
|
|
|
event.stopPropagation();
|
|
|
|
|
|
}
|
2023-06-10 17:45:04 +08:00
|
|
|
|
});
|
2023-06-10 16:27:52 +08:00
|
|
|
|
}
|
|
|
|
|
|
avMaskElement.addEventListener("click", (event) => {
|
|
|
|
|
|
if ((event.target as HTMLElement).classList.contains("av__mask")) {
|
2023-12-15 12:04:18 +08:00
|
|
|
|
updateCellValueByInput(protyle, type, cellElements);
|
2023-06-10 16:27:52 +08:00
|
|
|
|
avMaskElement?.remove();
|
|
|
|
|
|
}
|
2023-06-10 17:45:04 +08:00
|
|
|
|
});
|
2023-06-10 16:27:52 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
2023-12-15 12:04:18 +08:00
|
|
|
|
const updateCellValueByInput = (protyle: IProtyle, type: TAVCol, cellElements: HTMLElement[]) => {
|
2023-11-14 12:58:45 +08:00
|
|
|
|
const rowElement = hasClosestByClassName(cellElements[0], "av__row");
|
|
|
|
|
|
if (!rowElement) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2023-10-12 20:40:09 +08:00
|
|
|
|
if (!document.contains(cellElements[0]) && cellElements.length === 1) {
|
|
|
|
|
|
// 原始 cell 已被更新
|
2023-11-14 12:58:45 +08:00
|
|
|
|
const avid = rowElement.dataset.avid;
|
2023-10-12 20:40:09 +08:00
|
|
|
|
if (avid) {
|
|
|
|
|
|
// 新增行后弹出的输入框
|
2023-11-14 12:58:45 +08:00
|
|
|
|
const previousId = rowElement.dataset.previousId;
|
2023-11-07 10:36:15 +08:00
|
|
|
|
cellElements[0] = protyle.wysiwyg.element.querySelector(previousId ? `[data-av-id="${avid}"] .av__row[data-id="${previousId}"]` : `[data-av-id="${avid}"] .av__row--header`).nextElementSibling.querySelector('[data-detached="true"]');
|
2023-10-12 20:40:09 +08:00
|
|
|
|
} else {
|
|
|
|
|
|
// 修改单元格后立即修改其他单元格
|
2023-12-13 22:13:37 +08:00
|
|
|
|
let tempElement = protyle.wysiwyg.element.querySelector(`.av__cell[data-id="${cellElements[0].dataset.id}"]`) as HTMLElement;
|
|
|
|
|
|
if (!tempElement) {
|
|
|
|
|
|
// 修改单元格后修改其他没有内容的单元格(id 会随机)
|
|
|
|
|
|
tempElement = protyle.wysiwyg.element.querySelector(`.av__row[data-id="${rowElement.dataset.id}"] .av__cell[data-col-id="${cellElements[0].dataset.colId}"]`) as HTMLElement
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!tempElement) {
|
2023-10-12 20:40:09 +08:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
2023-12-13 22:13:37 +08:00
|
|
|
|
cellElements[0] = tempElement;
|
2023-10-12 20:40:09 +08:00
|
|
|
|
}
|
2023-09-28 00:33:00 +08:00
|
|
|
|
}
|
2023-11-14 12:58:45 +08:00
|
|
|
|
if (cellElements.length === 1 && cellElements[0].dataset.detached === "true" && !rowElement.dataset.id) {
|
2023-09-28 00:33:00 +08:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
2023-07-17 12:54:24 +08:00
|
|
|
|
const blockElement = hasClosestBlock(cellElements[0]);
|
2023-06-10 16:27:52 +08:00
|
|
|
|
if (!blockElement) {
|
2023-06-10 17:45:04 +08:00
|
|
|
|
return;
|
2023-06-10 16:27:52 +08:00
|
|
|
|
}
|
2023-07-17 19:56:52 +08:00
|
|
|
|
const avMaskElement = document.querySelector(".av__mask");
|
|
|
|
|
|
const doOperations: IOperation[] = [];
|
|
|
|
|
|
const undoOperations: IOperation[] = [];
|
2023-07-13 00:07:33 +08:00
|
|
|
|
const avID = blockElement.getAttribute("data-av-id");
|
2023-10-14 11:04:23 +08:00
|
|
|
|
const id = blockElement.getAttribute("data-node-id");
|
2023-10-13 11:30:44 +08:00
|
|
|
|
if (type === "template") {
|
|
|
|
|
|
const colId = cellElements[0].getAttribute("data-col-id");
|
|
|
|
|
|
const textElement = avMaskElement.querySelector(".b3-text-field") as HTMLInputElement;
|
2023-10-13 11:34:19 +08:00
|
|
|
|
if (textElement.value !== textElement.dataset.template) {
|
|
|
|
|
|
transaction(protyle, [{
|
|
|
|
|
|
action: "updateAttrViewColTemplate",
|
|
|
|
|
|
id: colId,
|
|
|
|
|
|
avID,
|
|
|
|
|
|
data: textElement.value,
|
|
|
|
|
|
type: "template",
|
|
|
|
|
|
}], [{
|
|
|
|
|
|
action: "updateAttrViewColTemplate",
|
|
|
|
|
|
id: colId,
|
|
|
|
|
|
avID,
|
|
|
|
|
|
data: textElement.dataset.template,
|
|
|
|
|
|
type: "template",
|
|
|
|
|
|
}]);
|
|
|
|
|
|
}
|
2023-10-13 11:30:44 +08:00
|
|
|
|
} else {
|
|
|
|
|
|
cellElements.forEach((item) => {
|
|
|
|
|
|
const rowElement = hasClosestByClassName(item, "av__row");
|
|
|
|
|
|
if (!rowElement) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
const rowID = rowElement.getAttribute("data-id");
|
|
|
|
|
|
const cellId = item.getAttribute("data-id");
|
|
|
|
|
|
const colId = item.getAttribute("data-col-id");
|
2023-11-14 12:58:45 +08:00
|
|
|
|
const inputValue: {
|
2023-11-20 11:12:02 +08:00
|
|
|
|
content?: string | number,
|
|
|
|
|
|
isNotEmpty?: boolean,
|
|
|
|
|
|
checked?: boolean,
|
|
|
|
|
|
} = {};
|
2023-11-14 12:58:45 +08:00
|
|
|
|
const oldValue: {
|
2023-11-20 11:12:02 +08:00
|
|
|
|
content?: string | number,
|
|
|
|
|
|
isNotEmpty?: boolean,
|
|
|
|
|
|
checked?: boolean,
|
|
|
|
|
|
} = {};
|
2023-10-13 11:30:44 +08:00
|
|
|
|
if (type === "number") {
|
2023-11-21 17:31:57 +08:00
|
|
|
|
oldValue.content = parseFloat(item.textContent.trim());
|
2023-10-13 11:30:44 +08:00
|
|
|
|
oldValue.isNotEmpty = typeof oldValue.content === "number" && !isNaN(oldValue.content);
|
2023-11-21 17:31:57 +08:00
|
|
|
|
inputValue.content = parseFloat((avMaskElement.querySelector(".b3-text-field") as HTMLInputElement).value);
|
2023-10-13 11:30:44 +08:00
|
|
|
|
inputValue.isNotEmpty = typeof inputValue.content === "number" && !isNaN(inputValue.content);
|
2023-12-12 17:11:06 +08:00
|
|
|
|
if (!inputValue.isNotEmpty) {
|
|
|
|
|
|
// 后端仅支持传入数字,因此在为空的时候需要设置为 0
|
|
|
|
|
|
inputValue.content = 0;
|
|
|
|
|
|
}
|
2023-11-20 11:12:02 +08:00
|
|
|
|
} else if (type === "checkbox") {
|
2023-11-20 12:28:20 +08:00
|
|
|
|
const useElement = item.querySelector("use");
|
|
|
|
|
|
inputValue.checked = useElement.getAttribute("xlink:href") === "#iconUncheck";
|
|
|
|
|
|
oldValue.checked = !inputValue.checked;
|
|
|
|
|
|
useElement.setAttribute("xlink:href", inputValue.checked ? "#iconCheck" : "#iconUncheck");
|
2023-11-20 11:12:02 +08:00
|
|
|
|
} else {
|
2023-11-20 12:28:20 +08:00
|
|
|
|
inputValue.content = (avMaskElement.querySelector(".b3-text-field") as HTMLInputElement).value;
|
|
|
|
|
|
oldValue.content = type === "block" ? item.firstElementChild.textContent.trim() : item.textContent.trim();
|
2023-07-17 12:54:24 +08:00
|
|
|
|
}
|
2023-10-13 11:30:44 +08:00
|
|
|
|
if (objEquals(inputValue, oldValue)) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
doOperations.push({
|
|
|
|
|
|
action: "updateAttrViewCell",
|
|
|
|
|
|
id: cellId,
|
|
|
|
|
|
avID,
|
|
|
|
|
|
keyID: colId,
|
|
|
|
|
|
rowID,
|
|
|
|
|
|
data: {
|
|
|
|
|
|
[type]: inputValue
|
|
|
|
|
|
}
|
2023-10-14 11:04:23 +08:00
|
|
|
|
}, {
|
|
|
|
|
|
action: "doUpdateUpdated",
|
|
|
|
|
|
id,
|
|
|
|
|
|
data: dayjs().format("YYYYMMDDHHmmss"),
|
2023-10-13 11:30:44 +08:00
|
|
|
|
});
|
|
|
|
|
|
undoOperations.push({
|
|
|
|
|
|
action: "updateAttrViewCell",
|
|
|
|
|
|
id: cellId,
|
|
|
|
|
|
avID,
|
|
|
|
|
|
keyID: colId,
|
|
|
|
|
|
rowID,
|
|
|
|
|
|
data: {
|
|
|
|
|
|
[type]: oldValue
|
|
|
|
|
|
}
|
2023-10-14 11:04:23 +08:00
|
|
|
|
}, {
|
|
|
|
|
|
action: "doUpdateUpdated",
|
|
|
|
|
|
id,
|
|
|
|
|
|
data: blockElement.getAttribute("updated"),
|
2023-10-13 11:30:44 +08:00
|
|
|
|
});
|
2023-11-20 12:27:20 +08:00
|
|
|
|
if (!hasClosestByClassName(cellElements[0], "custom-attr")) {
|
|
|
|
|
|
updateAttrViewCellAnimation(item);
|
|
|
|
|
|
}
|
2023-07-17 19:56:52 +08:00
|
|
|
|
});
|
2023-10-13 11:30:44 +08:00
|
|
|
|
}
|
2023-10-06 10:56:30 +08:00
|
|
|
|
if (doOperations.length > 0) {
|
|
|
|
|
|
transaction(protyle, doOperations, undoOperations);
|
|
|
|
|
|
}
|
2023-11-20 12:27:20 +08:00
|
|
|
|
if (!hasClosestByClassName(cellElements[0], "custom-attr")) {
|
|
|
|
|
|
cellElements[0].classList.add("av__cell--select");
|
|
|
|
|
|
}
|
2023-12-13 22:30:00 +08:00
|
|
|
|
if (blockElement &&
|
|
|
|
|
|
// 单元格编辑中 ctrl+p 光标定位
|
|
|
|
|
|
!document.querySelector(".b3-dialog")) {
|
2023-10-13 11:55:51 +08:00
|
|
|
|
focusBlock(blockElement);
|
|
|
|
|
|
}
|
2023-12-07 21:12:29 +08:00
|
|
|
|
document.querySelectorAll(".av__mask").forEach((item) => {
|
|
|
|
|
|
item.remove();
|
2023-06-10 17:45:04 +08:00
|
|
|
|
});
|
|
|
|
|
|
};
|
2023-12-15 12:04:18 +08:00
|
|
|
|
|
2023-12-15 12:30:57 +08:00
|
|
|
|
export const updateCellsValue = (protyle: IProtyle, nodeElement: HTMLElement, value = "") => {
|
2023-12-15 12:04:18 +08:00
|
|
|
|
const doOperations: IOperation[] = []
|
|
|
|
|
|
const undoOperations: IOperation[] = []
|
|
|
|
|
|
|
|
|
|
|
|
const avID = nodeElement.dataset.avId
|
|
|
|
|
|
const id = nodeElement.dataset.nodeId
|
|
|
|
|
|
let text = ''
|
|
|
|
|
|
const cellElements: Element[] = Array.from(nodeElement.querySelectorAll(".av__cell--select")) || [];
|
|
|
|
|
|
if (cellElements.length === 0) {
|
|
|
|
|
|
nodeElement.querySelectorAll(".av__row--select:not(.av__row--header)").forEach(rowElement => {
|
|
|
|
|
|
rowElement.querySelectorAll(".av__cell").forEach(cellElement => {
|
|
|
|
|
|
cellElements.push(cellElement)
|
|
|
|
|
|
})
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
cellElements.forEach((item: HTMLElement) => {
|
|
|
|
|
|
const rowElement = hasClosestByClassName(item, "av__row");
|
|
|
|
|
|
if (!rowElement) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
const type = getTypeByCellElement(item);
|
|
|
|
|
|
if (["created", "updated", "template"].includes(type)) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
const rowID = rowElement.getAttribute("data-id");
|
|
|
|
|
|
const cellId = item.getAttribute("data-id");
|
|
|
|
|
|
const colId = item.getAttribute("data-col-id");
|
|
|
|
|
|
|
|
|
|
|
|
text += getCellText(item);
|
|
|
|
|
|
|
|
|
|
|
|
doOperations.push({
|
|
|
|
|
|
action: "updateAttrViewCell",
|
|
|
|
|
|
id: cellId,
|
|
|
|
|
|
avID,
|
|
|
|
|
|
keyID: colId,
|
|
|
|
|
|
rowID,
|
2023-12-15 12:30:57 +08:00
|
|
|
|
data: genCellValue(type, value)
|
2023-12-15 12:04:18 +08:00
|
|
|
|
});
|
|
|
|
|
|
undoOperations.push({
|
|
|
|
|
|
action: "updateAttrViewCell",
|
|
|
|
|
|
id: cellId,
|
|
|
|
|
|
avID,
|
|
|
|
|
|
keyID: colId,
|
|
|
|
|
|
rowID,
|
|
|
|
|
|
data: genCellValueByElement(type, item)
|
|
|
|
|
|
});
|
|
|
|
|
|
if (!hasClosestByClassName(cellElements[0], "custom-attr")) {
|
|
|
|
|
|
updateAttrViewCellAnimation(item);
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
if (doOperations.length > 0) {
|
|
|
|
|
|
doOperations.push({
|
|
|
|
|
|
action: "doUpdateUpdated",
|
|
|
|
|
|
id,
|
|
|
|
|
|
data: dayjs().format("YYYYMMDDHHmmss"),
|
|
|
|
|
|
})
|
|
|
|
|
|
undoOperations.push({
|
|
|
|
|
|
action: "doUpdateUpdated",
|
|
|
|
|
|
id,
|
|
|
|
|
|
data: nodeElement.getAttribute("updated"),
|
|
|
|
|
|
})
|
|
|
|
|
|
transaction(protyle, doOperations, undoOperations);
|
|
|
|
|
|
}
|
|
|
|
|
|
return text;
|
|
|
|
|
|
}
|