fix table delete

This commit is contained in:
Timi
2026-08-28 16:38:20 +08:00
parent b12cc2c243
commit b013d3b557
2 changed files with 106 additions and 17 deletions
@@ -1,5 +1,36 @@
<template> <template>
<t-button v-popup="'插入表格'" :variant="active ? 'base' : 'text'" :theme="active ? 'light' : 'default'" @click="openPopup"> <t-popover
v-if="active"
v-model="actionVisible"
class="popover"
placement="bottom"
theme="light"
:show-arrow="false"
>
<t-button variant="base" theme="light">
<t-icon name="table" />
</t-button>
<template #content>
<div class="actions">
<t-button
class="action"
size="extra-small"
variant="text"
block
@click="onContinueInsert"
>继续插入</t-button>
<t-button
class="action"
size="extra-small"
variant="text"
theme="danger"
block
@click="onDeleteTable"
>删除表格</t-button>
</div>
</template>
</t-popover>
<t-button v-else v-popup="'插入表格'" variant="text" @click="openPopup">
<t-icon name="table" /> <t-icon name="table" />
</t-button> </t-button>
<bottom-popup <bottom-popup
@@ -44,6 +75,7 @@ const props = defineProps<{
}>(); }>();
const visible = ref(false); const visible = ref(false);
const actionVisible = ref(false);
const hoverRow = ref(1); const hoverRow = ref(1);
const hoverCol = ref(1); const hoverCol = ref(1);
@@ -68,6 +100,16 @@ function openPopup() {
visible.value = true; visible.value = true;
} }
function onContinueInsert() {
actionVisible.value = false;
openPopup();
}
function onDeleteTable() {
actionVisible.value = false;
props.editor?.chain().focus().deleteTable().run();
}
function onReset() { function onReset() {
hoverRow.value = 1; hoverRow.value = 1;
hoverCol.value = 1; hoverCol.value = 1;
@@ -83,35 +125,44 @@ function onSelect(row: number, col: number) {
return; return;
} }
props.editor.chain().focus().insertTable({ rows: row, cols: col, withHeaderRow: true }).run(); props.editor.chain().focus().insertTable({ rows: row, cols: col, withHeaderRow: true }).run();
visible.value = false;
} }
watch(() => props.active, (active) => {
if (!active) {
actionVisible.value = false;
}
});
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
.table-picker { .table-picker {
width: min(20rem, calc(100vw - 2rem)); padding: 0 1rem calc(1rem + env(safe-area-inset-bottom));
padding: 1rem 1rem calc(1rem + env(safe-area-inset-bottom)); display: flex;
box-sizing: border-box; box-sizing: border-box;
background: var(--td-bg-color-container, #fff); background: var(--td-bg-color-container, #fff);
justify-content: center;
flex-direction: column;
.tip { .tip {
height: 1.5rem; height: 1.5rem;
color: var(--td-text-color-secondary, #666); color: var(--td-text-color-secondary, #666);
font-size: .75rem; font-size: .75rem;
text-align: center;
line-height: 1.5rem; line-height: 1.5rem;
} }
.grid { .grid {
gap: .125rem; gap: .5rem;
width: fit-content;
display: grid; display: grid;
margin: 0 auto;
grid-template-columns: repeat(7, 1fr); grid-template-columns: repeat(7, 1fr);
}
.cell { .cell {
width: 1.75rem; width: 2rem;
height: 1.75rem; height: 2rem;
padding: 0;
border: 1px solid var(--td-component-border, #dcdcdc); border: 1px solid var(--td-component-border, #dcdcdc);
padding: 0;
background: var(--td-bg-color-container, #fff); background: var(--td-bg-color-container, #fff);
&.active { &.active {
@@ -119,5 +170,14 @@ function onSelect(row: number, col: number) {
background: var(--td-brand-color-light, #e0edff); background: var(--td-brand-color-light, #e0edff);
} }
} }
}
}
.actions {
padding: 0 1rem;
.action {
height: 2rem !important;
}
} }
</style> </style>
+30 -1
View File
@@ -71,7 +71,7 @@
<t-button v-popup="'有序列表'" :variant="isActive('orderedList') ? 'base' : 'text'" :theme="isActive('orderedList') ? 'light' : 'default'" @click="run('orderedList')"> <t-button v-popup="'有序列表'" :variant="isActive('orderedList') ? 'base' : 'text'" :theme="isActive('orderedList') ? 'light' : 'default'" @click="run('orderedList')">
<t-icon name="order-list" /> <t-icon name="order-list" />
</t-button> </t-button>
<tiptap-table-button :editor="editor" :active="isActive('table')" /> <tiptap-table-button :editor="editor" :active="tableActive" />
<t-button v-popup="'无序列表'" :variant="isActive('bulletList') ? 'base' : 'text'" :theme="isActive('bulletList') ? 'light' : 'default'" @click="run('bulletList')"> <t-button v-popup="'无序列表'" :variant="isActive('bulletList') ? 'base' : 'text'" :theme="isActive('bulletList') ? 'light' : 'default'" @click="run('bulletList')">
<t-icon name="bulletpoint" /> <t-icon name="bulletpoint" />
</t-button> </t-button>
@@ -192,8 +192,14 @@ type RunType =
| "horizontalRule" | "horizontalRule"
| "clear"; | "clear";
type TiptapEditorEventApi = TiptapEditorInstance & {
on: (event: "selectionUpdate" | "transaction", callback: () => void) => void;
off: (event: "selectionUpdate" | "transaction", callback: () => void) => void;
};
const textColorDraft = ref("#000000"); const textColorDraft = ref("#000000");
const bgColorDraft = ref("#ffff00"); const bgColorDraft = ref("#ffff00");
const tableActive = ref(false);
const headingVisible = ref(false); const headingVisible = ref(false);
const colorPickerVisible = ref(false); const colorPickerVisible = ref(false);
const colorPickerType = ref<"text" | "bg">("text"); const colorPickerType = ref<"text" | "bg">("text");
@@ -251,6 +257,27 @@ function isActive(type: string) {
return props.editor.isActive(type); return props.editor.isActive(type);
} }
function syncTableActive() {
tableActive.value = props.editor?.isActive("table") ?? false;
}
watch(() => props.editor, (editor, previousEditor) => {
const previousEventApi = previousEditor as TiptapEditorEventApi | undefined;
previousEventApi?.off("selectionUpdate", syncTableActive);
previousEventApi?.off("transaction", syncTableActive);
const eventApi = editor as TiptapEditorEventApi | undefined;
eventApi?.on("selectionUpdate", syncTableActive);
eventApi?.on("transaction", syncTableActive);
syncTableActive();
}, { immediate: true });
onBeforeUnmount(() => {
const eventApi = props.editor as TiptapEditorEventApi | undefined;
eventApi?.off("selectionUpdate", syncTableActive);
eventApi?.off("transaction", syncTableActive);
});
function isAlignActive(align: AlignType) { function isAlignActive(align: AlignType) {
if (!props.editor) { if (!props.editor) {
return false; return false;
@@ -375,6 +402,8 @@ function confirmColor() {
<style lang="less" scoped> <style lang="less" scoped>
.toolbar { .toolbar {
--td-popover-padding: .25rem .5rem;
width: 100%; width: 100%;
position: relative; position: relative;
display: flex; display: flex;