feat: enhance article editor and detail components with improved link handling and UI updates
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -284,8 +284,7 @@ onBeforeUnmount(() => {
|
||||
border-radius: 999px;
|
||||
background: #ffffff;
|
||||
box-shadow:
|
||||
0 4px 20px rgba(15, 23, 42, 0.08),
|
||||
0 0 0 1px rgba(15, 23, 42, 0.04);
|
||||
0 8px 32px rgb(17 17 17 / 28%), 0 0 0 1px rgba(15, 23, 42, 0.05);
|
||||
}
|
||||
|
||||
.editor-ai-assist__bar-icon {
|
||||
@@ -373,8 +372,7 @@ onBeforeUnmount(() => {
|
||||
border-radius: 16px;
|
||||
background: #ffffff;
|
||||
box-shadow:
|
||||
0 8px 32px rgba(15, 23, 42, 0.1),
|
||||
0 0 0 1px rgba(15, 23, 42, 0.05);
|
||||
0 8px 32px rgb(17 17 17 / 28%), 0 0 0 1px rgba(15, 23, 42, 0.05);
|
||||
}
|
||||
|
||||
.editor-ai-assist__result-box {
|
||||
|
||||
Reference in New Issue
Block a user