优化:1,点击Refine后弹出refine弹窗,再次点击refine无法关闭。

2,截图所示refine弹窗的三角图标配色与弹窗不一致。
This commit is contained in:
jingrow 2026-06-14 02:07:42 +08:00
parent c695d2524e
commit 9216d5f658
3 changed files with 51 additions and 32 deletions

View File

@ -645,6 +645,7 @@ onBeforeUnmount(() => {
:visible="showReviewRefine"
:is-refining="isRefining"
:anchor-rect="refineAnchorRect"
:anchor-el="reviewBarRef?.refineBtnRef"
:t="t"
@submit="handleReviewRefine"
@close="showReviewRefine = false"

View File

@ -9,11 +9,14 @@ const props = withDefaults(defineProps<{
t?: (key: string) => string
isRefining?: boolean
anchorRect?: DOMRect | null
/** 触发按钮 DOM 引用,用于排除 toggle 点击的 outside-close */
anchorEl?: HTMLElement | null
}>(), {
visible: false,
t: (key: string) => key,
isRefining: false,
anchorRect: null,
anchorEl: null,
})
const emit = defineEmits<{
@ -27,18 +30,28 @@ const popoverRef = ref<HTMLElement | null>(null)
const popoverWidth = 320
const popoverHeight = ref(52)
const ARROW_SIZE = 8
const ARROW_SQ = 12 // 2 × ~8.5px
const GAP = 6
/** 箭头是否翻转到弹窗底部(弹窗向上弹出时) */
const arrowFlipped = computed(() => {
const rect = props.anchorRect
if (!rect) return false
const top = rect.top + rect.height + GAP + ARROW_SQ
return top + popoverHeight.value > window.innerHeight - 16
})
const popoverStyle = computed(() => {
const rect = props.anchorRect
if (!rect) return {}
let left = rect.left - 10
let top = rect.top + rect.height + GAP + ARROW_SIZE
const flipped = arrowFlipped.value
let top = flipped
? rect.top - popoverHeight.value - GAP - ARROW_SQ
: rect.top + rect.height + GAP + ARROW_SQ
const vw = window.innerWidth
const vh = window.innerHeight
const PAD = 16
if (left + popoverWidth > vw - PAD) {
@ -47,9 +60,6 @@ const popoverStyle = computed(() => {
if (left < PAD) {
left = PAD
}
if (top + popoverHeight.value > vh - PAD) {
top = rect.top - popoverHeight.value - GAP - ARROW_SIZE
}
return {
position: 'fixed' as const,
@ -72,9 +82,7 @@ watch(() => props.visible, async (val) => {
inputRef.value?.focus()
await nextTick()
const el = popoverRef.value
if (el) {
popoverHeight.value = el.offsetHeight
}
if (el) popoverHeight.value = el.offsetHeight
}
})
@ -89,9 +97,11 @@ function handleMousedown(e: MouseEvent) {
const el = popoverRef.value
if (!el) return
const target = e.target as Node
if (!el.contains(target)) {
emit('close')
}
// popover
if (el.contains(target)) return
// Refine toggle
if (props.anchorEl?.contains(target)) return
emit('close')
}
onMounted(() => {
@ -112,7 +122,11 @@ onBeforeUnmount(() => {
class="ai-refine-popover"
:style="popoverStyle"
>
<div class="arp-arrow" :style="{ left: arrowLeft }" />
<div
class="arp-arrow"
:class="{ 'arp-arrow--down': arrowFlipped }"
:style="{ left: arrowLeft }"
/>
<div class="arp-body">
<span class="arp-icon"></span>
@ -156,34 +170,35 @@ onBeforeUnmount(() => {
from { opacity: 0; transform: translateY(6px) scale(0.96); }
to { opacity: 1; transform: translateY(0) scale(1); }
}
/* ── 箭头:旋转方块法(规避 z-index 层叠问题) ── */
.arp-arrow {
position: absolute;
top: -8px;
width: 0;
height: 0;
border-left: 8px solid transparent;
border-right: 8px solid transparent;
border-bottom: 8px solid #fff;
filter: drop-shadow(0 -1px 1px rgba(0,0,0,0.08));
z-index: 1002;
top: -6px;
width: 12px;
height: 12px;
background: #fff;
border-top: 1px solid #e5e7eb;
border-left: 1px solid #e5e7eb;
transform: rotate(45deg);
z-index: 1;
}
.arp-arrow::after {
content: '';
position: absolute;
top: 1px;
left: -9px;
width: 0;
height: 0;
border-left: 9px solid transparent;
border-right: 9px solid transparent;
border-bottom: 9px solid #e5e7eb;
z-index: -1;
.arp-arrow--down {
top: auto;
bottom: -6px;
border-top: none;
border-left: none;
border-bottom: 1px solid #e5e7eb;
border-right: 1px solid #e5e7eb;
}
.arp-body {
position: relative;
z-index: 2;
display: flex;
align-items: center;
gap: 8px;
padding: 10px 14px;
background: #fff;
border-radius: 12px;
}
.arp-icon {
color: #8b5cf6;

View File

@ -22289,6 +22289,9 @@ msgstr "向 AI 提问..."
msgid "Refine the AI output..."
msgstr "精炼 AI 输出..."
msgid "进一步优化文本..."
msgstr "进一步优化文本..."
msgid "AI Suggestion"
msgstr "AI 建议"