feat: 提示词

This commit is contained in:
zhongyidian committed 2025-12-31 17:46:53 +08:00
1 parent b980f2993b
commit 6090abf955
15 files changed
+330 -54

No files matched your search

+2 -2
View File
@@ -137,7 +137,7 @@ const positionStyle = computed(() => {
}
.guide-panel {
@apply relative bg-white rounded-2xl shadow-2xl;
@apply relative bg-white rounded-2xl;
/* background: linear-gradient(135deg, #60a5fa 0%, #a855f7 100%);
border: 2px solid #60a5fa;
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1); */
@@ -170,7 +170,7 @@ const positionStyle = computed(() => {
}
.guide-content {
@apply flex items-start p-6 h-full;
@apply flex items-start pl-6 pt-9 pb-0 h-full;
}
.content-icon {
+4
View File
@@ -6,6 +6,7 @@
:target-selector="highlightSelector"
:padding="highlightPadding"
:border-radius="highlightRadius"
:highlight-mode="highlightMode"
/>
<div class="guide-align" :style="alignStyle">
<GuideDragon
@@ -73,6 +74,8 @@ interface Props {
highlightPadding?: number
/** 高亮圆角,默认16 */
highlightRadius?: number
/** 高亮模式:'border' 画框效果,'gradient' 渐变灯光效果,默认 'border' */
highlightMode?: 'border' | 'gradient'
/** 垂直偏移(仅Y轴),支持 number(px) 或 '10%'/'120px' */
positionOffsetY?: number | string
}
@@ -91,6 +94,7 @@ const props = withDefaults(defineProps<Props>(), {
highlightSelector: null,
highlightPadding: 8,
highlightRadius: 16,
highlightMode: 'border',
positionOffsetY: '50%'
})
+104 -12
View File
@@ -1,21 +1,18 @@
<template>
<div v-if="visible" class="spotlight-overlay">
<!-- 渐变遮罩层 -->
<div v-if="props.highlightMode === 'gradient'" class="spotlight-mask" :style="maskStyle"></div>
<!-- 画框模式:使用 box-shadow 遮罩 + 边框 -->
<div
v-if="props.highlightMode === 'border' && rect.width > 0 && rect.height > 0"
class="spotlight-hole"
:style="{
top: rect.top + 'px',
left: rect.left + 'px',
width: rect.width + 'px',
height: rect.height + 'px',
borderRadius: borderRadius + 'px',
boxShadow: `0 0 0 9999px rgba(0,0,0,0.6)`
}"
:style="holeStyle"
></div>
</div>
</template>
<script setup lang="ts">
import { reactive, watch, onMounted, onBeforeUnmount } from 'vue'
import { reactive, computed, watch, onMounted, onBeforeUnmount } from 'vue'
interface Props {
/** 是否可见 */
@@ -26,13 +23,19 @@ interface Props {
padding?: number
/** 圆角 */
borderRadius?: number
/** 渐变过渡范围(像素) */
gradientRange?: number
/** 高亮模式:'border' 画框效果,'gradient' 渐变灯光效果 */
highlightMode?: 'border' | 'gradient'
}
const props = withDefaults(defineProps<Props>(), {
visible: false,
targetSelector: null,
padding: 8,
borderRadius: 16
borderRadius: 16,
gradientRange: 100,
highlightMode: 'border'
})
const rect = reactive({ top: 0, left: 0, width: 0, height: 0 })
@@ -72,7 +75,78 @@ onBeforeUnmount(() => {
window.removeEventListener('scroll', onScroll)
})
const borderRadius = props.borderRadius
// 计算渐变遮罩样式
const maskStyle = computed(() => {
if (!props.visible || rect.width === 0 || rect.height === 0) {
return {
maskImage: 'none',
WebkitMaskImage: 'none'
}
}
// 计算中心点坐标(相对于视口)
const centerX = rect.left + rect.width / 2
const centerY = rect.top + rect.height / 2
// 计算椭圆半径(基于高亮区域)
// 使用较大的尺寸作为基准,确保覆盖整个高亮区域
const maxDimension = Math.max(rect.width, rect.height)
const aspectRatio = rect.width / rect.height
// 渐变范围
const gradientRangeValue = Math.max(0, props.gradientRange)
// 计算椭圆的半径(考虑宽高比)
// 对于椭圆,我们需要分别计算 x 和 y 方向的半径
const baseRadius = maxDimension / 2
const radiusX = baseRadius + gradientRangeValue
const radiusY = (baseRadius + gradientRangeValue) / aspectRatio
// 高亮区域边缘的半径(椭圆的主轴)
const highlightRadius = baseRadius
// 渐变停止点:从中心透明,到高亮边缘仍透明,然后向外渐变到不透明
// 计算渐变停止点的像素值
const highlightEdge = highlightRadius // 高亮区域边缘,保持透明
const gradientStart = highlightRadius + gradientRangeValue * 0.1 // 渐变开始
const gradientMid = highlightRadius + gradientRangeValue * 0.5 // 渐变中间
const gradientEnd = highlightRadius + gradientRangeValue // 渐变结束,完全不透明
// 创建径向渐变遮罩
// mask-image 中,transparent 表示遮罩透明(背景可见),black 表示遮罩不透明(背景被遮住)
// 我们需要从中心透明(高亮区域可见)渐变到边缘不透明(周围变暗)
// 使用平滑的多色停止点创建柔和的渐变效果
const gradient = `radial-gradient(
ellipse ${radiusX}px ${radiusY}px at ${centerX}px ${centerY}px,
transparent 0px,
transparent ${highlightEdge}px,
rgba(0, 0, 0, 0.2) ${gradientStart}px,
rgba(0, 0, 0, 0.5) ${gradientMid}px,
rgba(0, 0, 0, 0.9) ${gradientEnd * 0.9}px,
black ${gradientEnd}px
)`
return {
maskImage: gradient,
WebkitMaskImage: gradient
}
})
// 计算画框模式样式(box-shadow + 边框)
const holeStyle = computed(() => {
if (!props.visible || rect.width === 0 || rect.height === 0) {
return {}
}
return {
top: rect.top + 'px',
left: rect.left + 'px',
width: rect.width + 'px',
height: rect.height + 'px',
borderRadius: props.borderRadius + 'px',
boxShadow: `0 0 0 9999px rgba(0,0,0,0.6)`
}
})
</script>
<style scoped>
@@ -83,8 +157,26 @@ const borderRadius = props.borderRadius
z-index: 100000;
}
.spotlight-hole {
.spotlight-mask {
position: absolute;
inset: 0;
background: rgba(0, 0, 0, 0.6);
transition: opacity 0.3s ease-in-out;
mask-image: radial-gradient(ellipse, transparent 0%, black 100%);
-webkit-mask-image: radial-gradient(ellipse, transparent 0%, black 100%);
mask-repeat: no-repeat;
-webkit-mask-repeat: no-repeat;
pointer-events: none;
}
.spotlight-hole {
position: absolute;
border: 2px solid rgba(255, 255, 255, 0.9);
box-shadow:
0 0 0 1px rgba(0, 0, 0, 0.3),
0 0 20px rgba(255, 255, 255, 0.3),
0 0 0 9999px rgba(0, 0, 0, 0.6);
pointer-events: none;
transition: all 0.3s ease-in-out;
}
</style>