浏览代码

:art: https://github.com/siyuan-note/siyuan/issues/9667

Vanessa 1 年之前
父节点
当前提交
c8ea33c5ce

+ 5 - 0
app/appearance/langs/en_US.json

@@ -1,4 +1,9 @@
 {
 {
+  "checked": "Checked",
+  "unchecked": "Unchecked",
+  "percentChecked": "Percent checked",
+  "percentUnchecked": "Percent unchecked",
+  "checkbox": "Checkbox",
   "copyInline": "Copy inline element",
   "copyInline": "Copy inline element",
   "unsplit": "Unsplit",
   "unsplit": "Unsplit",
   "unsplitAll": "Unsplit All",
   "unsplitAll": "Unsplit All",

+ 5 - 0
app/appearance/langs/es_ES.json

@@ -1,4 +1,9 @@
 {
 {
+  "checked": "marcado",
+  "unchecked": "desmarcado",
+  "percentChecked": "Porcentaje comprobado",
+  "percentUnchecked": "Porcentaje no marcado",
+  "checkbox": "Casilla de verificación",
   "copyInline": "Copiar elemento en línea",
   "copyInline": "Copiar elemento en línea",
   "unsplit": "Desdividir",
   "unsplit": "Desdividir",
   "unsplitAll": "Desdividir Todo",
   "unsplitAll": "Desdividir Todo",

+ 5 - 0
app/appearance/langs/fr_FR.json

@@ -1,4 +1,9 @@
 {
 {
+  "checked": "Coché",
+  "unchecked": "Décoché",
+  "percentChecked": "Pourcentage vérifié",
+  "percentUnchecked": "Pourcentage non coché",
+  "checkbox": "case à cocher",
   "copyInline": "Copier l'élément en ligne",
   "copyInline": "Copier l'élément en ligne",
   "unsplit": "Unsplit",
   "unsplit": "Unsplit",
   "unsplitAll": "Tout dédiviser",
   "unsplitAll": "Tout dédiviser",

+ 5 - 0
app/appearance/langs/zh_CHT.json

@@ -1,4 +1,9 @@
 {
 {
+  "checked": "已完成",
+  "unchecked": "未完成",
+  "percentChecked": "已完成佔比",
+  "percentUnchecked": "未完成佔比",
+  "checkbox": "勾選方塊",
   "copyInline": "複製行級元素",
   "copyInline": "複製行級元素",
   "unsplit": "取消分割畫面",
   "unsplit": "取消分割畫面",
   "unsplitAll": "取消全部分螢幕",
   "unsplitAll": "取消全部分螢幕",

+ 5 - 0
app/appearance/langs/zh_CN.json

@@ -1,4 +1,9 @@
 {
 {
+  "checked": "已完成",
+  "unchecked": "未完成",
+  "percentChecked": "已完成占比",
+  "percentUnchecked": "未完成占比",
+  "checkbox": "勾选框",
   "copyInline": "复制行级元素",
   "copyInline": "复制行级元素",
   "unsplit": "取消分屏",
   "unsplit": "取消分屏",
   "unsplitAll": "取消全部分屏",
   "unsplitAll": "取消全部分屏",

+ 25 - 16
app/src/assets/scss/business/_av.scss

@@ -113,7 +113,8 @@
     }
     }
 
 
     &--select {
     &--select {
-      &:not(.av__row--header) .av__cell {
+      &:not(.av__row--header) .av__cell,
+      &:not(.av__row--header) .av__firstcol {
         background-color: var(--b3-av-background-hl);
         background-color: var(--b3-av-background-hl);
       }
       }
 
 
@@ -231,7 +232,7 @@
       position: absolute;
       position: absolute;
       right: 5px;
       right: 5px;
       font-size: 85%;
       font-size: 85%;
-      top: 8px;
+      top: 5.5px;
     }
     }
 
 
     &.dragover__right {
     &.dragover__right {
@@ -267,15 +268,15 @@
     align-items: center;
     align-items: center;
     flex: 1;
     flex: 1;
     overflow: hidden;
     overflow: hidden;
+  }
 
 
-    & > .av__cellicon {
-      height: 1em;
-      width: 1em;
-      color: var(--b3-theme-on-surface);
-      margin: 0 5px 0 0;
-      flex-shrink: 0;
-      line-height: 1em;
-    }
+  &__cellheadericon {
+    height: 1em;
+    width: 1em;
+    color: var(--b3-theme-on-surface);
+    margin: 0 5px 0 0;
+    flex-shrink: 0;
+    line-height: 1em;
   }
   }
 
 
   &__celltext {
   &__celltext {
@@ -292,15 +293,23 @@
     }
     }
   }
   }
 
 
+  &__checkbox {
+    color: var(--b3-theme-on-surface);
+    height: 14px;
+    width: 14px;
+    float: left;
+    padding: 4.5px 0;
+
+    &:hover {
+      color: var(--b3-theme-on-background);
+    }
+  }
+
   &__firstcol {
   &__firstcol {
     svg {
     svg {
-      color: var(--b3-theme-on-surface);
-      height: 33px;
-      width: 24px;
+      @extend .av__checkbox;
       opacity: 0;
       opacity: 0;
-      padding: 5px;
-      box-sizing: border-box;
-      float: left;
+      padding: 9.5px 5px;
     }
     }
 
 
     &:hover svg {
     &:hover svg {

+ 2 - 1
app/src/protyle/render/av/action.ts

@@ -3,7 +3,7 @@ import {hasClosestBlock, hasClosestByAttribute, hasClosestByClassName} from "../
 import {transaction} from "../../wysiwyg/transaction";
 import {transaction} from "../../wysiwyg/transaction";
 import {openEditorTab} from "../../../menus/util";
 import {openEditorTab} from "../../../menus/util";
 import {copySubMenu} from "../../../menus/commonMenuItem";
 import {copySubMenu} from "../../../menus/commonMenuItem";
-import {getTypeByCellElement, openCalcMenu, popTextCell} from "./cell";
+import {getTypeByCellElement, popTextCell} from "./cell";
 import {getColIconByType, showColMenu} from "./col";
 import {getColIconByType, showColMenu} from "./col";
 import {insertAttrViewBlockAnimation, updateHeader} from "./row";
 import {insertAttrViewBlockAnimation, updateHeader} from "./row";
 import {emitOpenMenu} from "../../../plugin/EventBus";
 import {emitOpenMenu} from "../../../plugin/EventBus";
@@ -23,6 +23,7 @@ import {getSearch} from "../../../util/functions";
 import {unicode2Emoji} from "../../../emoji";
 import {unicode2Emoji} from "../../../emoji";
 import {selectRow} from "./row";
 import {selectRow} from "./row";
 import * as dayjs from "dayjs";
 import * as dayjs from "dayjs";
+import {openCalcMenu} from "./calc";
 
 
 export const avClick = (protyle: IProtyle, event: MouseEvent & { target: HTMLElement }) => {
 export const avClick = (protyle: IProtyle, event: MouseEvent & { target: HTMLElement }) => {
     const blockElement = hasClosestBlock(event.target);
     const blockElement = hasClosestBlock(event.target);

+ 256 - 0
app/src/protyle/render/av/calc.ts

@@ -0,0 +1,256 @@
+import {Menu} from "../../../plugin/Menu";
+import {transaction} from "../../wysiwyg/transaction";
+import {hasClosestBlock, hasClosestByClassName} from "../../util/hasClosest";
+
+const calcItem = (options: {
+    menu: Menu,
+    protyle: IProtyle,
+    label: string,
+    operator: string,
+    oldOperator: string,
+    colId: string,
+    avId: string
+}) => {
+    options.menu.addItem({
+        iconHTML: "",
+        label: options.label,
+        click() {
+            transaction(options.protyle, [{
+                action: "setAttrViewColCalc",
+                avID: options.avId,
+                id: options.colId,
+                data: {
+                    operator: options.operator
+                }
+            }], [{
+                action: "setAttrViewColCalc",
+                avID: options.avId,
+                id: options.colId,
+                data: {
+                    operator: options.oldOperator
+                }
+            }]);
+        }
+    });
+};
+
+export const openCalcMenu = (protyle: IProtyle, calcElement: HTMLElement) => {
+    const blockElement = hasClosestBlock(calcElement);
+    if (!blockElement) {
+        return;
+    }
+    const rowElement = hasClosestByClassName(calcElement, "av__row--footer");
+    if (!rowElement) {
+        return;
+    }
+    rowElement.classList.add("av__row--show");
+    const menu = new Menu("av-calc", () => {
+        rowElement.classList.remove("av__row--show");
+    });
+    if (menu.isOpen) {
+        return;
+    }
+    const type = calcElement.dataset.dtype as TAVCol;
+    const colId = calcElement.dataset.colId;
+    const avId = blockElement.dataset.avId;
+    const oldOperator = calcElement.dataset.operator;
+    if (type !== "checkbox") {
+        calcItem({
+            menu,
+            protyle,
+            colId,
+            avId,
+            oldOperator,
+            operator: "",
+            label: window.siyuan.languages.calcOperatorNone
+        });
+    }
+    calcItem({
+        menu,
+        protyle,
+        colId,
+        avId,
+        oldOperator,
+        operator: "Count all",
+        label: window.siyuan.languages.calcOperatorCountAll
+    });
+    if (type !== "checkbox") {
+        calcItem({
+            menu,
+            protyle,
+            colId,
+            avId,
+            oldOperator,
+            operator: "Count values",
+            label: window.siyuan.languages.calcOperatorCountValues
+        });
+        calcItem({
+            menu,
+            protyle,
+            colId,
+            avId,
+            oldOperator,
+            operator: "Count unique values",
+            label: window.siyuan.languages.calcOperatorCountUniqueValues
+        });
+        calcItem({
+            menu,
+            protyle,
+            colId,
+            avId,
+            oldOperator,
+            operator: "Count empty",
+            label: window.siyuan.languages.calcOperatorCountEmpty
+        });
+        calcItem({
+            menu,
+            protyle,
+            colId,
+            avId,
+            oldOperator,
+            operator: "Count not empty",
+            label: window.siyuan.languages.calcOperatorCountNotEmpty
+        });
+        calcItem({
+            menu,
+            protyle,
+            colId,
+            avId,
+            oldOperator,
+            operator: "Percent empty",
+            label: window.siyuan.languages.calcOperatorPercentEmpty
+        });
+        calcItem({
+            menu,
+            protyle,
+            colId,
+            avId,
+            oldOperator,
+            operator: "Percent not empty",
+            label: window.siyuan.languages.calcOperatorPercentNotEmpty
+        });
+    } else {
+        calcItem({
+            menu,
+            protyle,
+            colId,
+            avId,
+            oldOperator,
+            operator: "Checked",
+            label: window.siyuan.languages.checked
+        });
+        calcItem({
+            menu,
+            protyle,
+            colId,
+            avId,
+            oldOperator,
+            operator: "Unchecked",
+            label: window.siyuan.languages.unchecked
+        });
+        calcItem({
+            menu,
+            protyle,
+            colId,
+            avId,
+            oldOperator,
+            operator: "Percent checked",
+            label: window.siyuan.languages.percentChecked
+        });
+        calcItem({
+            menu,
+            protyle,
+            colId,
+            avId,
+            oldOperator,
+            operator: "Percent unchecked",
+            label: window.siyuan.languages.percentUnchecked
+        });
+    }
+    if (["number", "template"].includes(type)) {
+        calcItem({
+            menu,
+            protyle,
+            colId,
+            avId,
+            oldOperator,
+            operator: "Sum",
+            label: window.siyuan.languages.calcOperatorSum
+        });
+        calcItem({
+            menu,
+            protyle,
+            colId,
+            avId,
+            oldOperator,
+            operator: "Average",
+            label: window.siyuan.languages.calcOperatorAverage
+        });
+        calcItem({
+            menu,
+            protyle,
+            colId,
+            avId,
+            oldOperator,
+            operator: "Median",
+            label: window.siyuan.languages.calcOperatorMedian
+        });
+        calcItem({
+            menu,
+            protyle,
+            colId,
+            avId,
+            oldOperator,
+            operator: "Min",
+            label: window.siyuan.languages.calcOperatorMin
+        });
+        calcItem({
+            menu,
+            protyle,
+            colId,
+            avId,
+            oldOperator,
+            operator: "Max",
+            label: window.siyuan.languages.calcOperatorMax
+        });
+        calcItem({
+            menu,
+            protyle,
+            colId,
+            avId,
+            oldOperator,
+            operator: "Range",
+            label: window.siyuan.languages.calcOperatorRange
+        });
+    } else if (["date", "created", "updated"].includes(type)) {
+        calcItem({
+            menu,
+            protyle,
+            colId,
+            avId,
+            oldOperator,
+            operator: "Earliest",
+            label: window.siyuan.languages.calcOperatorEarliest
+        });
+        calcItem({
+            menu,
+            protyle,
+            colId,
+            avId,
+            oldOperator,
+            operator: "Latest",
+            label: window.siyuan.languages.calcOperatorLatest
+        });
+        calcItem({
+            menu,
+            protyle,
+            colId,
+            avId,
+            oldOperator,
+            operator: "Range",
+            label: window.siyuan.languages.calcOperatorRange
+        });
+    }
+    const calcRect = calcElement.getBoundingClientRect();
+    menu.open({x: calcRect.left, y: calcRect.bottom, h: calcRect.height});
+};

+ 27 - 224
app/src/protyle/render/av/cell.ts

@@ -133,221 +133,16 @@ export const genCellValue = (colType: TAVCol, value: string | any) => {
                 type: colType,
                 type: colType,
                 mAsset: value as IAVCellAssetValue[]
                 mAsset: value as IAVCellAssetValue[]
             };
             };
-        }
-    }
-    return cellValue;
-};
-
-const calcItem = (options: {
-    menu: Menu,
-    protyle: IProtyle,
-    label: string,
-    operator: string,
-    oldOperator: string,
-    colId: string,
-    avId: string
-}) => {
-    options.menu.addItem({
-        iconHTML: "",
-        label: options.label,
-        click() {
-            transaction(options.protyle, [{
-                action: "setAttrViewColCalc",
-                avID: options.avId,
-                id: options.colId,
-                data: {
-                    operator: options.operator
-                }
-            }], [{
-                action: "setAttrViewColCalc",
-                avID: options.avId,
-                id: options.colId,
-                data: {
-                    operator: options.oldOperator
+        } else if (colType === "checkbox") {
+            cellValue = {
+                type: colType,
+                checkbox: {
+                    checked: value ? true : false
                 }
                 }
-            }]);
+            };
         }
         }
-    });
-};
-
-export const openCalcMenu = (protyle: IProtyle, calcElement: HTMLElement) => {
-    const blockElement = hasClosestBlock(calcElement);
-    if (!blockElement) {
-        return;
-    }
-    const rowElement = hasClosestByClassName(calcElement, "av__row--footer");
-    if (!rowElement) {
-        return;
-    }
-    rowElement.classList.add("av__row--show");
-    const menu = new Menu("av-calc", () => {
-        rowElement.classList.remove("av__row--show");
-    });
-    if (menu.isOpen) {
-        return;
     }
     }
-    const type = calcElement.dataset.dtype as TAVCol;
-    const colId = calcElement.dataset.colId;
-    const avId = blockElement.dataset.avId;
-    const oldOperator = calcElement.dataset.operator;
-    calcItem({
-        menu,
-        protyle,
-        colId,
-        avId,
-        oldOperator,
-        operator: "",
-        label: window.siyuan.languages.calcOperatorNone
-    });
-    calcItem({
-        menu,
-        protyle,
-        colId,
-        avId,
-        oldOperator,
-        operator: "Count all",
-        label: window.siyuan.languages.calcOperatorCountAll
-    });
-    calcItem({
-        menu,
-        protyle,
-        colId,
-        avId,
-        oldOperator,
-        operator: "Count values",
-        label: window.siyuan.languages.calcOperatorCountValues
-    });
-    calcItem({
-        menu,
-        protyle,
-        colId,
-        avId,
-        oldOperator,
-        operator: "Count unique values",
-        label: window.siyuan.languages.calcOperatorCountUniqueValues
-    });
-    calcItem({
-        menu,
-        protyle,
-        colId,
-        avId,
-        oldOperator,
-        operator: "Count empty",
-        label: window.siyuan.languages.calcOperatorCountEmpty
-    });
-    calcItem({
-        menu,
-        protyle,
-        colId,
-        avId,
-        oldOperator,
-        operator: "Count not empty",
-        label: window.siyuan.languages.calcOperatorCountNotEmpty
-    });
-    calcItem({
-        menu,
-        protyle,
-        colId,
-        avId,
-        oldOperator,
-        operator: "Percent empty",
-        label: window.siyuan.languages.calcOperatorPercentEmpty
-    });
-    calcItem({
-        menu,
-        protyle,
-        colId,
-        avId,
-        oldOperator,
-        operator: "Percent not empty",
-        label: window.siyuan.languages.calcOperatorPercentNotEmpty
-    });
-    if (["number", "template"].includes(type)) {
-        calcItem({
-            menu,
-            protyle,
-            colId,
-            avId,
-            oldOperator,
-            operator: "Sum",
-            label: window.siyuan.languages.calcOperatorSum
-        });
-        calcItem({
-            menu,
-            protyle,
-            colId,
-            avId,
-            oldOperator,
-            operator: "Average",
-            label: window.siyuan.languages.calcOperatorAverage
-        });
-        calcItem({
-            menu,
-            protyle,
-            colId,
-            avId,
-            oldOperator,
-            operator: "Median",
-            label: window.siyuan.languages.calcOperatorMedian
-        });
-        calcItem({
-            menu,
-            protyle,
-            colId,
-            avId,
-            oldOperator,
-            operator: "Min",
-            label: window.siyuan.languages.calcOperatorMin
-        });
-        calcItem({
-            menu,
-            protyle,
-            colId,
-            avId,
-            oldOperator,
-            operator: "Max",
-            label: window.siyuan.languages.calcOperatorMax
-        });
-        calcItem({
-            menu,
-            protyle,
-            colId,
-            avId,
-            oldOperator,
-            operator: "Range",
-            label: window.siyuan.languages.calcOperatorRange
-        });
-    } else if (["date", "created", "updated"].includes(type)) {
-        calcItem({
-            menu,
-            protyle,
-            colId,
-            avId,
-            oldOperator,
-            operator: "Earliest",
-            label: window.siyuan.languages.calcOperatorEarliest
-        });
-        calcItem({
-            menu,
-            protyle,
-            colId,
-            avId,
-            oldOperator,
-            operator: "Latest",
-            label: window.siyuan.languages.calcOperatorLatest
-        });
-        calcItem({
-            menu,
-            protyle,
-            colId,
-            avId,
-            oldOperator,
-            operator: "Range",
-            label: window.siyuan.languages.calcOperatorRange
-        });
-    }
-    const calcRect = calcElement.getBoundingClientRect();
-    menu.open({x: calcRect.left, y: calcRect.bottom, h: calcRect.height});
+    return cellValue;
 };
 };
 
 
 export const cellScrollIntoView = (blockElement: HTMLElement, cellElement: Element, onlyHeight = true) => {
 export const cellScrollIntoView = (blockElement: HTMLElement, cellElement: Element, onlyHeight = true) => {
@@ -427,7 +222,7 @@ export const popTextCell = (protyle: IProtyle, cellElements: HTMLElement[], type
     }
     }
     cellRect = cellElements[0].getBoundingClientRect();
     cellRect = cellElements[0].getBoundingClientRect();
     let html = "";
     let html = "";
-    const style = `style="position:absolute;left: ${cellRect.left}px;top: ${cellRect.top}px;width:${Math.max(cellRect.width, 58)}px;height: ${cellRect.height}px"`;
+    const style = `style="position:absolute;left: ${cellRect.left}px;top: ${cellRect.top}px;width:${Math.max(cellRect.width, 25)}px;height: ${cellRect.height}px"`;
     if (["text", "url", "email", "phone", "block", "template"].includes(type)) {
     if (["text", "url", "email", "phone", "block", "template"].includes(type)) {
         html = `<textarea ${style} class="b3-text-field">${cellElements[0].firstElementChild.textContent}</textarea>`;
         html = `<textarea ${style} class="b3-text-field">${cellElements[0].firstElementChild.textContent}</textarea>`;
     } else if (type === "number") {
     } else if (type === "number") {
@@ -439,6 +234,8 @@ export const popTextCell = (protyle: IProtyle, cellElements: HTMLElement[], type
             openMenuPanel({protyle, blockElement, type: "asset", cellElements});
             openMenuPanel({protyle, blockElement, type: "asset", cellElements});
         } else if (type === "date") {
         } else if (type === "date") {
             openMenuPanel({protyle, blockElement, type: "date", cellElements});
             openMenuPanel({protyle, blockElement, type: "date", cellElements});
+        } else if (type === "checkbox") {
+            updateCellValue(protyle, type, cellElements);
         }
         }
         if (!hasClosestByClassName(cellElements[0], "custom-attr")) {
         if (!hasClosestByClassName(cellElements[0], "custom-attr")) {
             cellElements[0].classList.add("av__cell--select");
             cellElements[0].classList.add("av__cell--select");
@@ -548,22 +345,28 @@ const updateCellValue = (protyle: IProtyle, type: TAVCol, cellElements: HTMLElem
             const cellId = item.getAttribute("data-id");
             const cellId = item.getAttribute("data-id");
             const colId = item.getAttribute("data-col-id");
             const colId = item.getAttribute("data-col-id");
             const inputValue: {
             const inputValue: {
-                content: string | number,
-                isNotEmpty?: boolean
-            } = {
-                content: (avMaskElement.querySelector(".b3-text-field") as HTMLInputElement).value
-            };
+                content?: string | number,
+                isNotEmpty?: boolean,
+                checked?: boolean,
+            } = {};
             const oldValue: {
             const oldValue: {
-                content: string | number,
-                isNotEmpty?: boolean
-            } = {
-                content: type === "block" ? item.firstElementChild.textContent.trim() : item.textContent.trim()
-            };
+                content?: string | number,
+                isNotEmpty?: boolean,
+                checked?: boolean,
+            } = {};
             if (type === "number") {
             if (type === "number") {
                 oldValue.content = parseFloat(oldValue.content as string);
                 oldValue.content = parseFloat(oldValue.content as string);
                 oldValue.isNotEmpty = typeof oldValue.content === "number" && !isNaN(oldValue.content);
                 oldValue.isNotEmpty = typeof oldValue.content === "number" && !isNaN(oldValue.content);
                 inputValue.content = parseFloat(inputValue.content as string);
                 inputValue.content = parseFloat(inputValue.content as string);
                 inputValue.isNotEmpty = typeof inputValue.content === "number" && !isNaN(inputValue.content);
                 inputValue.isNotEmpty = typeof inputValue.content === "number" && !isNaN(inputValue.content);
+            } else if (type === "checkbox") {
+                const useElement = item.querySelector("use")
+                inputValue.checked = useElement.getAttribute("xlink:href") === "#iconUncheck"
+                oldValue.checked = !inputValue.checked
+                useElement.setAttribute("xlink:href", inputValue.checked ? "#iconCheck" : "#iconUncheck")
+            } else {
+                inputValue.content = (avMaskElement.querySelector(".b3-text-field") as HTMLInputElement).value
+                oldValue.content = type === "block" ? item.firstElementChild.textContent.trim() : item.textContent.trim()
             }
             }
             if (objEquals(inputValue, oldValue)) {
             if (objEquals(inputValue, oldValue)) {
                 return;
                 return;
@@ -607,6 +410,6 @@ const updateCellValue = (protyle: IProtyle, type: TAVCol, cellElements: HTMLElem
         focusBlock(blockElement);
         focusBlock(blockElement);
     }
     }
     setTimeout(() => {
     setTimeout(() => {
-        avMaskElement.remove();
+        avMaskElement?.remove();
     });
     });
 };
 };

+ 28 - 1
app/src/protyle/render/av/col.ts

@@ -353,6 +353,8 @@ export const getColIconByType = (type: TAVCol) => {
             return "iconPhone";
             return "iconPhone";
         case "template":
         case "template":
             return "iconMath";
             return "iconMath";
+        case "checkbox":
+            return "iconCheck";
     }
     }
 };
 };
 
 
@@ -379,7 +381,7 @@ export const addAttrViewColAnimation = (options: {
         if (index === 0) {
         if (index === 0) {
             html = `<div class="av__cell" data-icon="${options.icon || ""}" data-col-id="${options.id}" data-dtype="${options.type}" style="width: 200px;white-space: nowrap;">
             html = `<div class="av__cell" data-icon="${options.icon || ""}" data-col-id="${options.id}" data-dtype="${options.type}" style="width: 200px;white-space: nowrap;">
     <div draggable="true" class="av__cellheader">
     <div draggable="true" class="av__cellheader">
-        ${options.icon ? unicode2Emoji(options.icon, "av__cellicon", true) : `<svg class="av__cellicon"><use xlink:href="#${getColIconByType(options.type)}"></use></svg>`}
+        ${options.icon ? unicode2Emoji(options.icon, "av__cellheadericon", true) : `<svg class="av__cellheadericon"><use xlink:href="#${getColIconByType(options.type)}"></use></svg>`}
         <span class="av__celltext">${options.name}</span>
         <span class="av__celltext">${options.name}</span>
     </div>
     </div>
     <div class="av__widthdrag"></div>
     <div class="av__widthdrag"></div>
@@ -825,6 +827,31 @@ export const addCol = (protyle: IProtyle, blockElement: Element) => {
             });
             });
         }
         }
     });
     });
+    menu.addItem({
+        icon: "iconCheck",
+        label: window.siyuan.languages.checkbox,
+        click() {
+            const id = Lute.NewNodeID();
+            transaction(protyle, [{
+                action: "addAttrViewCol",
+                name: window.siyuan.languages.checkbox,
+                avID,
+                type: "checkbox",
+                id
+            }], [{
+                action: "removeAttrViewCol",
+                id,
+                avID,
+            }]);
+            addAttrViewColAnimation({
+                blockElement: blockElement,
+                protyle: protyle,
+                type: "checkbox",
+                name: window.siyuan.languages.checkbox,
+                id
+            });
+        }
+    });
     menu.addItem({
     menu.addItem({
         icon: "iconLink",
         icon: "iconLink",
         label: window.siyuan.languages.link,
         label: window.siyuan.languages.link,

+ 4 - 2
app/src/protyle/render/av/render.ts

@@ -85,9 +85,9 @@ data-icon="${column.icon}" data-dtype="${column.type}"  data-pin="${column.pin}"
 style="width: ${column.width || "200px"};
 style="width: ${column.width || "200px"};
 ${column.wrap ? "" : "white-space: nowrap;"}">
 ${column.wrap ? "" : "white-space: nowrap;"}">
     <div draggable="true" class="av__cellheader">
     <div draggable="true" class="av__cellheader">
-        ${column.icon ? unicode2Emoji(column.icon, "av__cellicon", true) : `<svg class="av__cellicon"><use xlink:href="#${getColIconByType(column.type)}"></use></svg>`}
+        ${column.icon ? unicode2Emoji(column.icon, "av__cellheadericon", true) : `<svg class="av__cellheadericon"><use xlink:href="#${getColIconByType(column.type)}"></use></svg>`}
         <span class="av__celltext">${column.name}</span>
         <span class="av__celltext">${column.name}</span>
-        ${column.pin ? '<div class="fn__flex-1"></div><svg class="av__cellicon"><use xlink:href="#iconPin"></use></svg>' : ""}
+        ${column.pin ? '<div class="fn__flex-1"></div><svg class="av__cellheadericon"><use xlink:href="#iconPin"></use></svg>' : ""}
     </div>
     </div>
     <div class="av__widthdrag"></div>
     <div class="av__widthdrag"></div>
 </div>`;
 </div>`;
@@ -172,6 +172,8 @@ style="width: ${column.width || "200px"}">${getCalcValue(column) || '<svg><use x
                                     text += `<span class="b3-chip av__celltext--url" data-url="${item.content}">${item.name}</span>`;
                                     text += `<span class="b3-chip av__celltext--url" data-url="${item.content}">${item.name}</span>`;
                                 }
                                 }
                             });
                             });
+                        } else if (cell.valueType === "checkbox") {
+                            text += `<svg class="av__checkbox"><use xlink:href="#icon${cell.value?.checkbox?.checked ? "Check" : "Uncheck"}"></use></svg>`;
                         }
                         }
                         if (["text", "template", "url", "email", "phone", "number", "date", "created", "updated"].includes(cell.valueType) &&
                         if (["text", "template", "url", "email", "phone", "number", "date", "created", "updated"].includes(cell.valueType) &&
                             cell.value && cell.value[cell.valueType as "url"].content) {
                             cell.value && cell.value[cell.valueType as "url"].content) {

+ 1 - 1
app/src/protyle/wysiwyg/index.ts

@@ -385,7 +385,7 @@ export class WYSIWYG {
                 const scrollElement = nodeElement.querySelector(".av__scroll");
                 const scrollElement = nodeElement.querySelector(".av__scroll");
                 const contentRect = protyle.contentElement.getBoundingClientRect();
                 const contentRect = protyle.contentElement.getBoundingClientRect();
                 documentSelf.onmousemove = (moveEvent: MouseEvent) => {
                 documentSelf.onmousemove = (moveEvent: MouseEvent) => {
-                    newWidth = Math.max(oldWidth + (moveEvent.clientX - event.clientX), 58) + "px";
+                    newWidth = Math.max(oldWidth + (moveEvent.clientX - event.clientX), 25) + "px";
                     scrollElement.querySelectorAll(".av__row, .av__row--footer").forEach(item => {
                     scrollElement.querySelectorAll(".av__row, .av__row--footer").forEach(item => {
                         (item.querySelector(`[data-col-id="${dragColId}"]`) as HTMLElement).style.width = newWidth;
                         (item.querySelector(`[data-col-id="${dragColId}"]`) as HTMLElement).style.width = newWidth;
                     });
                     });

+ 4 - 0
app/src/types/index.d.ts

@@ -71,6 +71,7 @@ type TAVCol =
     | "template"
     | "template"
     | "created"
     | "created"
     | "updated"
     | "updated"
+    | "checkbox"
 type THintSource = "search" | "av" | "hint";
 type THintSource = "search" | "av" | "hint";
 type TAVFilterOperator =
 type TAVFilterOperator =
     "="
     "="
@@ -1094,6 +1095,9 @@ interface IAVCellValue {
     }
     }
     template?: {
     template?: {
         content: string
         content: string
+    },
+    checkbox?: {
+        checked: boolean
     }
     }
     date?: IAVCellDateValue
     date?: IAVCellDateValue
     created?: IAVCellDateValue
     created?: IAVCellDateValue