feat: enhance article editor and detail components with improved link handling and UI updates

This commit is contained in:
2026-04-07 19:38:29 +08:00
parent 98ebb12fa1
commit d0f0271346
7 changed files with 281 additions and 171 deletions
@@ -1,5 +1,6 @@
<script setup lang="ts">
import { computed, nextTick, onBeforeUnmount, onMounted, ref, watch, type Component, type CSSProperties } from "vue";
import { DownOutlined } from "@ant-design/icons-vue";
type EditorActionMenuItem = {
key: string;
@@ -8,6 +9,7 @@ type EditorActionMenuItem = {
danger?: boolean;
disabled?: boolean;
active?: boolean;
children?: EditorActionMenuItem[];
};
type EditorActionMenuGroup = {
@@ -132,21 +134,60 @@ onBeforeUnmount(() => {
>
<template v-for="(group, groupIndex) in groups" :key="group.key">
<div class="editor-action-menu__group" :style="resolveGroupStyle(group)">
<button
v-for="item in group.items"
:key="item.key"
type="button"
class="editor-action-menu__action"
:class="{
'editor-action-menu__action--active': item.active,
'editor-action-menu__action--danger': item.danger,
}"
:disabled="item.disabled"
@click="handleSelect(item)"
>
<component :is="item.icon" v-if="item.icon" />
<span>{{ item.label }}</span>
</button>
<template v-for="item in group.items" :key="item.key">
<a-dropdown
v-if="item.children && item.children.length > 0"
:trigger="['click']"
overlay-class-name="editor-action-menu__dropdown-overlay"
:overlay-style="{ zIndex: 2000 }"
>
<button
type="button"
class="editor-action-menu__action"
:class="{
'editor-action-menu__action--active': item.active,
'editor-action-menu__action--danger': item.danger,
}"
:disabled="item.disabled"
>
<component :is="item.icon" v-if="item.icon" />
<span v-if="resolvedVariant === 'tile'">{{ item.label }}</span>
<DownOutlined class="editor-action-menu__dropdown-icon" />
</button>
<template #overlay>
<a-menu>
<a-menu-item
v-for="child in item.children"
:key="child.key"
:disabled="child.disabled"
@click="handleSelect(child)"
>
<span
class="editor-action-menu__dropdown-item"
:class="{ 'editor-action-menu__dropdown-item--danger': child.danger }"
>
<component :is="child.icon" v-if="child.icon" />
<span>{{ child.label }}</span>
</span>
</a-menu-item>
</a-menu>
</template>
</a-dropdown>
<button
v-else
type="button"
class="editor-action-menu__action"
:class="{
'editor-action-menu__action--active': item.active,
'editor-action-menu__action--danger': item.danger,
}"
:disabled="item.disabled"
@click="handleSelect(item)"
>
<component :is="item.icon" v-if="item.icon" />
<span v-if="resolvedVariant === 'tile'">{{ item.label }}</span>
</button>
</template>
</div>
<div v-if="groupIndex < groups.length - 1" class="editor-action-menu__divider"></div>
@@ -251,8 +292,9 @@ onBeforeUnmount(() => {
.editor-action-menu--inline .editor-action-menu__action {
display: flex;
align-items: center;
justify-content: center;
gap: 10px;
min-height: 46px;
min-height: 36px;
padding: 0 14px;
border-radius: 12px;
background: #f7f9fc;
@@ -296,4 +338,31 @@ onBeforeUnmount(() => {
.editor-action-menu__action:disabled {
cursor: not-allowed;
}
.editor-action-menu__dropdown-icon {
font-size: 10px !important;
color: #8c9eb5 !important;
transition: transform 0.2s;
}
.editor-action-menu__dropdown-item {
display: flex;
align-items: center;
gap: 8px;
font-size: 13px;
font-weight: 500;
color: #3f4a5c;
}
.editor-action-menu__dropdown-item--danger {
color: #cf1322;
}
.editor-action-menu__dropdown-item--danger :deep(svg) {
color: #cf1322;
}
:global(.editor-action-menu__dropdown-overlay) {
z-index: 2000;
margin-top: 10px;
}
</style>